在架构师们很喜欢的 Domain Driven Design,即 DDD 中,第一课就是教导团队形成自己独有的通用语言(Ubiquitous Language),作为业务概念沉淀下来。
作为非英语母语的国家,我们在日常交流中使用的是中文,在公司业务战略描述上使用的是中文,在高层进行任务拆分的时候使用的是中文,在领导安排工作的时候使用的是中文。唯独到了具体实现,即代码这一环节便变成了英文。当然这里我们不考虑有些公司会有汉语拼音这种尴尬的情况。
两种语言天生便有难以填平的鸿沟,在业务人员编写代码时,从中文到英文的转换,往往丢失一部分业务信息,产生一部分信息噪音,或者发生概念上的偏移。
英文语系的人对业务进行建模时,与业务方(领域专家)交流时,产生的概念和反馈可以直接落实到代码上,他们所使用的词汇不会发生变化。而其它语系的人就会在编写代码的时候发生概念偏移,比如我司是做打车业务,快车在不同的系统中会存在不同的翻译,有人称之为 fastcar,有人称之为 quickcar,有人甚至就直接是 kuaiche。甚至同一个系统中,对于同一个概念也会存在不同形式的自创翻译。即使以文档的形式记录了业务的标准翻译,但显然以国内业务叠代的速度,这种词汇上的统一是做不到的。即使在一个只有 7~8 个人的组中都做不到。并不是所有人的英文都可以达到可用的程度,有些代码中的词汇可能根本就是词不达意,是某些搜索引擎中给出的直译结果,与真实的含义相差十万八千里。
这样的代码会给后来人带来理解上的困惑。一旦在同一个系统中,针对同一个业务概念存在三种以上的不同词汇,就需要阅读者在这些“错误”的词汇上不停地进行上下文切换,以正确地理解错误词汇的涵义。
可能有些人会提出反驳意见,碰上这种情况我们只要对代码进行重构就可以了,并不需要被这种弱智的事情折磨啊。重构虽好,在很多情况下,词汇的重构是不可能的。打个比方,上面提到的 fastcar 出现在我们系统提供给别人所用的 api 的关键字段中,quickcar 出现在我们内部数据库的字段名中,kuaiche 出现在异步发送的消息中。这种时候修改任何一个单词,对于我们来说都是不可能的事情。api 和事件中的字段名是我们对于外部系统的承诺,这种承诺也是编程契约中的一部分,不能随便修改。即使我们想要修改,在当今大多数互联网公司的架构下,根本就没法知道到底是谁在使用你的哪一个字段。也就是说,我们没有办法获得粒度细到“字段”级别的外部使用信息,所以我们没有办法对契约本身进行重构。如果未来的微服务管理能对服务间的依赖进行标准化,并且能够对服务之间字段的依赖进行显式管理,那么契约就是可以进行变更的了(就像单模块的重构那样),不过这也就是个设想,显然不太可能。而数据库中的字段虽然有重命名方法,并且在 《Refactoring Databases》这本书中也给出了各种数据库重构的完善方案。但同样的,上了体量的互联网公司,想要动动数据库结构,是比登天还难的(等五年后应该好一些)。
所以当你接手到这样的系统时,读代码的时候肯定是会骂娘的,但是读完之后也确实没有什么办法。只要你负责维护,就持续地接受这种痛苦吧。
通用语言的问题不只是单模块中存在,跨模块时也存在。在微服务的架构下,很多需求是必然会跨越模块的。别说不可能,那些鼓吹中台的公司跨模块的需求更普遍。一个需求改 20 个模块都不奇怪。
模块间负责人探讨新功能的实现时,混乱的命名和词汇也很可能让两边的沟通变得驴头不对马嘴。在服务之间是接力棒式运作,没有中心服务时,这种情况特别普遍。相信你也遇得到。
遗憾的是,目前推崇的微服务架构是没有办法解决这样的问题的。在肉眼可见的将来,程序员依然会因为概念产生的歧义而不断地受苦。
这些苦痛最终都会体现到业务开发迭代的速度上。
原文 http://xargin.com/disaster-of-microservice-ul/