标签:software engineering

Go的软件架构方法论迷思

Go的软件架构方法论迷思

奇怪的思潮

最近东瀛Go业界有种奇怪的思潮:把Clean Architecture带进Go。我一直以为这只是某些小公司的自娱自乐,后来跟一些同行谈了一下,发现也不是个别现象。一个项目能不能用、活不活得下来还不知道,domain、repository、entity、use-case倒是整了一大堆。

其实Go的设计的最佳实践,官方文档和博客已经写得非常明白,从包名设计,到错误以处理,都有一套官方标准。这也是Go这门语言的优秀之处:简单,节制,让所有人都在一个约束下跳舞。至于应该用何种软件架构,却甚少见人提及。

如果大家读Go标准库或者一些优秀的Go的OSS代码,像HashiCorpCoreOSPingCAP,甚至是面向初学者的CURD项目RealWorld,会发现并没人把Clean Architecture等方法论用在这些项目上。这些代码点到即止,都在努力用最少的代码用最简练的方式实现它们所定义的目标。不止Go,著名的C、Rust、Python项目里我也没见过所谓的Clean Architecture。这股工业界的暗涌,跟OSS最佳实践显然是割裂的。

Clean Architecture试图解决的问题

不管是Clean Architecture,还是DDD、TDD、MVC,其诞生都有其道理。所有的软件设计框架和设计模式,它们都是对现实中某类复杂的问题的一般解。这些解不是也不可能是银弹,有其制约性。

我们看看Clean Architecture试图达成的主要目标:

  • 从粗到细的开发流程,延迟细节决定。
  • 责任分离。
  • 可测试。

首先,从粗到细的开发其实并不需要什么架构,只要写好伪代码就好。很多程序员并不写伪代码,一上来就写细节,这是一种不好的习惯。不仅程序,文章、计划书,也是这么写的。写程序不是DFS,而是BFS。很庆幸我初中的第一本JAVA书教会了我这个道理。

其次,责任分离在Go下只要用好interface就好,也跟架构关系不大。

最后,可测试当然很重要,前提是你TMD要写测试啊!各位Clean Architecture信者问一下自己,你们真的有写测试吗?有吗?!

Go的解

Go的设计之初,就考虑过各种软件架构和设计模式的问题。作者给出的答案,就是Go本身。比如刚才提到的interface,其目的之一就是为了解决责任分离。一个语言特性,胜千万架构与模式。

大家可以翻一下Java的23种设计模式,再对照Go的实现,就会发现很多原来在Java下得用设计模式解决的问题,在Go下都在语言层面下解决了。

让上帝的归上帝,凯撒的归凯撒

难道Go就不用设计模式了吗?也不全是。Go给的解也非银弹,不能解决所有问题,其设计目标是系统语言,而并非全栈语言,它并没有义务对它设计目标以外的问题给出一般解。

来看看号称“世界上第一个全栈语言”的Red所给出的图,看看语言的栈都有哪些:

Scope of Red compared to other programming languages

虽然这图没给出Go的栈范围,但我们知道它是在OS到Applications之间的非常狭窄的一段。

正因Go并非全栈语言,抛开设计模式用Go做其不擅长的业务逻辑密集的应用就会显得捉襟见肘。Go的Channel,Goroutinue,为系统应用设计的高级特性全用不上;而没有泛型、没有模式匹配、没有高级的错误处理,则让人如鲠在喉。

Google发明并送给所有人一台从清洗到叠衣服全自动的洗衣机,但你只关心它能不能把土豆洗干净。

也许有人会说,语言特性不重要,关键是写程序的人。然而,历史上所有的杀手级应用,都是有其相匹配的语言基础作支撑的。比如DHH写Rails时,找不到一门语言去实现它的想法,直到遇上的Matz的Ruby,其强大的元编程特性才成就了Rails。而Rails的大部分模仿者,都因为语言的原因无法达到Rails一样的高度。

全自动洗衣机让最厉害的工程师改装一下当然也能洗土豆,但我相信没一个工程师会想在自己简历上写自己干过这种浪费人力物力蠢事:毕竟出门左转就有农用器械专卖。

原罪与未来

问题的原罪,就是Google的工程师太优秀,没有考虑到这个星球上还有这么多写程序不动脑子的拿来主义码农。这问题显然是无解的,未来也不乐观。但既然献身了开源,自然就得有被全世界批斗的觉悟。Go从开源到现在已有十载,早已不是那个仅为了满足Google需要而开发的语言,它开始承载越来越多不在当初设计范围的特性。我们看到了Go2的改变,还有像v语言这种挑战。

Go开发团队是节制的,然而同人逼死官方的事也不是没发生过,Java就是一个活生生的例子,它在发明的时候也不是企业级开发的代名词。在破乎上对于Go是否要用DI这个问题有过激烈的讨论,其中某大V的一句话震耳发聩:

等什么时候出现了50万行的go程序,用户压低价格导致工资还开不了太高的时候,你们鄙视的东西统统都回来了。想想Java,也不是天生需要设计模式的。

大家还是洗洗写Rust去吧。