通用语言的劫难

在架构师们很喜爱的 Domain Driven Design,即 DDD 中,第一课就是教诲团队造成本人独有的通用语言(Ubiquitous Language),作为业务概念积淀下来。

作为非英语母语的国家,咱们在日常交换中应用的是中文,在公司业务策略形容上应用的是中文,在高层进行工作拆分的时候应用的是中文,在领导安顿工作的时候应用的是中文。唯独到了具体实现,即代码这一环节便变成了英文。当然这里咱们不思考有些公司会有汉语拼音这种难堪的状况。

两种语言天生便有难以填平的鸿沟,在业务人员编写代码时,从中文到英文的转换,往往失落一部分业务信息,产生一部分信息乐音,或者产生概念上的偏移。

英文语系的人对业务进行建模时,与业务方(领域专家)交换时,产生的概念和反馈能够间接落实到代码上,他们所应用的词汇不会发生变化。而其它语系的人就会在编写代码的时候产生概念偏移,比方我司是做打车业务,慢车在不同的零碎中会存在不同的翻译,有人称之为 fastcar,有人称之为 quickcar,有人甚至就间接是 kuaiche。甚至同一个零碎中,对于同一个概念也会存在不同模式的借鉴翻译。即便以文档的模式记录了业务的规范翻译,但显然以国内业务叠代的速度,这种词汇上的对立是做不到的。即便在一个只有 7~8 集体的组中都做不到。并不是所有人的英文都能够达到可用的水平,有些代码中的词汇可能根本就是词不达意,是某些搜索引擎中给出的直译后果,与实在的含意相差十万八千里。

这样的代码会给起初人带来了解上的困惑。一旦在同一个零碎中,针对同一个业务概念存在三种以上的不同词汇,就须要阅读者在这些“谬误”的词汇上不停地进行上下文切换,以正确地了解谬误词汇的涵义。

可能有些人会提出反驳意见,碰上这种状况咱们只有对代码进行重构就能够了,并不需要被这种弱智的事件折磨啊。重构虽好,在很多状况下,词汇的重构是不可能的。打个比方,下面提到的 fastcar 呈现在咱们零碎提供给他人所用的 api 的关键字段中,quickcar 呈现在咱们外部数据库的字段名中,kuaiche 呈现在异步发送的音讯中。这种时候批改任何一个单词,对于咱们来说都是不可能的事件。api 和事件中的字段名是咱们对于内部零碎的承诺,这种承诺也是编程契约中的一部分,不能轻易批改。即便咱们想要批改,在当今大多数互联网公司的架构下,基本就没法晓得到底是谁在应用你的哪一个字段。也就是说,咱们没有方法取得粒度细到“字段”级别的内部应用信息,所以咱们没有方法对契约自身进行重构。如果将来的微服务治理能对服务间的依赖进行标准化,并且可能对服务之间字段的依赖进行显式治理,那么契约就是能够进行变更的了(就像单模块的重构那样),不过这也就是个构想,显然不太可能。而数据库中的字段尽管有重命名办法,并且在 《Refactoring Databases》这本书中也给出了各种数据库重构的欠缺计划。但同样的,上了体量的互联网公司,想要动动数据库构造,是比登天还难的(等五年后应该好一些)。

所以当你接手到这样的零碎时,读代码的时候必定是会骂娘的,然而读完之后也的确没有什么方法。只有你负责保护,就继续地承受这种苦楚吧。

通用语言的问题不只是单模块中存在,跨模块时也存在。在微服务的架构下,很多需要是必然会逾越模块的。别说不可能,那些宣扬中台的公司跨模块的需要更广泛。一个需要改 20 个模块都不奇怪。

模块间负责人探讨新性能的实现时,凌乱的命名和词汇也很可能让两边的沟通变得驴头不对马嘴。在服务之间是接力棒式运作,没有核心服务时,这种状况特地广泛。置信你也遇失去。

遗憾的是,目前推崇的微服务架构是没有方法解决这样的问题的。在肉眼可见的未来,程序员仍然会因为概念产生的歧义而一直地受苦。

这些苦痛最终都会体现到业务开发迭代的速度上。

技术栈的劫难

微服务的布道师们特地喜爱宣扬一个观点:拆分微服务之后,咱们能够随便地对小模块进行重构,抉择最合适的技术栈,并且如果写失败了随时对这个模块拿其它语言进行重写。这一点被大多数布道师当作微服务的重点劣势。

然而布道师们无意地把这样做所带来的问题疏忽了,或者更歹意的是,他们明晓得有问题,然而不说?啊哈哈。

一个公司业务上有多种语言的话,实践上能够吸引到各种“语言的人才”。这的确不假,并且能够提供给各种语言大佬一个相互掐架的优良竞技场,只有干掉对手(其它语言的大佬)了,我就能够扩张团队,让团队把所有其它语言的模块用咱们善于的语言重写一遍,善哉善哉。小伙子们一年的事件就都安顿上了。

然而显然这种说辞是有问题的。在现行的微服务架构下,除了业务自身的研发人力投入之外,在业务之外的支持系统的研发工作也有很大的工作量,比方典型的,服务发现,熔断,优雅重启,存储系统 client,音讯队列 client,缓存 client,配置零碎 client 等等。。各种周边零碎版本顺次叠代下来,那可能也是几百上千人一两年的工作。为什么会带来这么多的工作量?其中很大一部分就是因为语言和技术栈凌乱造成的。比方一个公司的技术栈可能对立到 java 的话,那没什么说的,大家都用 Spring Cloud 全家桶或者 Dubbo 全家桶就能够了。然而你们既有 java 又有 Go 又有 PHP 又有 C++ 又有 NodeJS 又有 Rust,这样显然就很难在泛滥神仙中达成统一。比方你想要选用 java 的 Spring Cloud 生态,然而这外面的服务发现或者配置零碎并没有打算对其它语言进行反对,即便反对可能也反对地不全面。一旦反对不全面,公司内的轮子党们肯定会跳进去,强行给你找出几十个毛病,一杆子打回去,最终失去肯定要本人造这些轮子的论断。

好家伙,五种语言八种框架,一个服务发现的 client 轮子造五遍都能算少的了。目前开源界的趋势是将那些和业务无关的非功能性需要从模块中剥离进去,比方 service mesh 就是很好的尝试,只不过现阶段用过的都说坑。说好的那都是不怀好意,拉人入坑。对于研发人员来说,一个轮子造五遍真的没什么意思,可能也就是相熟了五种语言的语法,并且写出了五种风格各异的 bug。只不过满足了局部中层治理老板的人员扩张野心。

语言和框架太多,对于公司来说显然是劫难。比方常见的公司组织架构调整,业务技术部门进行重组,不同部门的零碎个别会进行暴力交接。这里说的“暴力”的意思是,不论你能不能接得下来,反正我是给你了。之后的保护也别来找我,甚至连简略的问答可能原部门都不肯定违心做。尽管公司对程序员的要求是能够随便地在不同语言技术栈之间切换,但程序员个别都有本人执著的美学偏好。让 java 程序员写 Go,往往是会翻车的。大多数 java 程序员在语言内的生态足够好,能满足简直所有需要时,没有任何志愿去学习一门新语言。这是人造的抗拒心理,能够了解。咱们这里曾经有有数的案例表明,java 程序员转 Go,在写不满三个月的工夫内就会到职 2333。就算不说 java,国内的 php 专家们也是不违心写 Go 的,那些 PHP 大佬们哪怕在 swoole 之类的框架中从新实现一套 goroutine,也不违心间接去写更原生的 Go 语言,因为用他人的货色体现不出轮子哥的价值啊。

对于一个公司来说,不应该听信那些微服务布道师的胡言,任由公司内的技术栈随便决裂。最终在公司调整或者变动的时刻才发现积重难返。那些几千甚至上万研发的“大公司”,大多都没有做到技术栈的对立,哪怕是在线业务技术栈也是如此。

拆分与收敛的劫难

在之前写事变驱动开发的时候,提到过,在企业中的我的项目进行开发时,只有是本人不便,一个人能够用拆分和收敛同时作为本人的规范。所以大家都是双标狗。

目前业界的微服务方法论个别也没有固定的套路,比方在 《Building Microservice》 一书中,作者也讲到了服务之间合作的时候,能够抉择编排(orchestration)和协同(choreography)这两种形式来对服务进行架构。所以在拆分阶段,就没有什么硬性的规范了,每个公司可能格调都有差异,并且都能够论述出本人的条条以反对本人的架构是“正确”的。

显然,这件事件没有相对正确的解法。无论哪种拆分形式,都会遇到业务边界的问题。在大企业中,顶着“架构师”头衔的这些架构师们基本就不会管任何实现上的细节。绝对较大的业务需要,个别也是一线的 RD 磋商怎么进行实现上的拆分。想要达到适合的职责划分,须要多个合作方的所有人都靠谱才行。这个要求切实是有点强人所难。比方在目前的公司内进行了三年多的开发,就和各种类型的人都打过交道。

脚踏实地的人比拟多,但也不乏一些齐全不负责任的人。有的素质奇差,只会逢迎甩锅,本人模块的职责都搞不清楚。原本本人该做的兜底不做,让所有上游零碎给他擦屁股。从应聘要求上来讲,程序员应该是一个重视逻辑能力,编码能力的职业。然而你总发现有些人是没有方法讲道理的(可能是晚期的一些能力个别的员工?),在与这些人探讨技术实现时,会陷入无穷无尽的无意义循环。而他能说(逼)服(迫)所有其它人就范的法宝,就是在两个小时的会议中一直地复读本人的观点,而齐全不听取任何他人的观点。一旦这样的人在你的某个零碎边界上待着,那你所面临的也是继续的苦楚。并且一直地在本人的零碎中进行斗争,做那些职责上跟你的零碎齐全没什么关系的货色。

除去人的问题,业务部门的大多数一线领导是须要有业务上的业绩的。这种业绩怎么来?个别都是揽各种各样的活儿,能揽多少就揽多少。

从设计原则上来讲,逻辑上雷同或者相似的代码应该放在一个中央来实现。这个略微学过一点 SOLID 中的 SRP 准则就应该晓得。这样能够防止逻辑自身过于扩散,益处是:“一个类(模块)只会因为一个理由而发生变化”,其实就是雷同的需要,尽量可能管制在单模块内实现。当然了这是一种现实状态,的确有些状况下达不到这种完满的均衡状态。微服务场景下这种业务边界往往划分都十分蹩脚。即便 Domain Driven Design 的观点讲述了再多的上下文划分技巧,你在理论工作中会发现没有多少人把这些思维、准则当回事,一线 leader 在乎的就是揽活儿而已。他们在划分模块的职责时只思考这么几点:

这件事件有没有业务收益,我能不能掺一脚
如果没有收益,这件事能不能甩给他人,我就不去做了
把业务上的影响全刨去,才会思考架构上的事件。有些大佬会讲,零碎是演变进去,而不是设计进去的,而这些“演化论”的大佬也是不参加一线开发的。你再看看理论的状况,只靠演变,可能演化出正当的零碎么?

不可能的,对人的要求切实太高。而且是对所有开发人员要求都高。大多数企业的业务零碎,都不足较为顶层的设计,有人管这个叫“策略设计”。绝对简单的业务逻辑,在企业的零碎中基本没法合了解耦,很多时候实现一套业务流程的代码会随便地散落在多个模块,在你把所有模块的代码都看过之前,你是没法确定哪局部逻辑在哪个模块里的。能够称之为薛定谔的业务逻辑。

这样在模块产生负责人到职或者工作交接时,所有 RD 都会进入十分苦楚的阶段,我只看本人的模块,基本没法理清全局的业务逻辑!对于产品来说也一样,所有逻辑的散布都具备不确定性,在哪里管制我须要去问研发,而研发还要再问其余的研发,其余的研发如果是刚接手,又要去看大量的代码能力确定到底是怎么回事。如果代码写的烂(对于大多数业务零碎来说,如果能够去掉),那可能连看都看不懂。就轻易胡诌应酬过来好了。事实就是如此荒诞。

在所有服务都在单体的时代,咱们能够在适合的工夫,参考《重构》书里的观点对咱们的模块进行重构。重构对系统自身的要求其实也不多,只有测试覆盖率足够,而后是强类型语言,大多数 IDE 对重构反对都很不错了。但演变到微服务的时代,原来很简略的重构就没那么简略了。在 http://xargin.com/disaster-of... 中咱们提到,凋谢的 API、音讯、数据库中的字段名基本没有方法进行重构,为什么没有方法,因为咱们的模块都被切开了,本来在代码中的强分割变成了分布式系统中的弱分割,薛定谔的分割。如果咱们想要实现和单体服务一样的重构性能要怎么办?基本实现不了。你至多须要上面这些设施反对能力实现这样的伟业:

所有其它模块对你都有集成测试,并且有对立的 API 平台治理所有你们之间的“分割”。
有全局所有模块的“同时重构”工具
上线时,能针对旧版和新版的流量主动进行辨认,避免新流量拜访到旧零碎
这个显然不可能啊,目前业界提出的 API 版本治理,也只是缓解了这种状况,新性能我如果在新版 API 实现,把旧版 API deprecated 掉,这样就能够逼迫用户放弃对我原来版本的依赖,平滑迁徙到新版 API 上来。但显然加上版本,也并没有从实质上来解决问题,API 的用户在没有迭代需要的前提下,因为依赖方进行了批改就不得不进行批改,这是额定的工作量。

你也看到了,拆分给咱们带来的并不全是坏事,以后中大规模公司的开发日常流程,可能最终还是会把零碎整体引向一片混沌。

难以治理的依赖天堂

微服务模式下,咱们的零碎中往往须要集成进各种各样的 SDK,这些 SDK 局部来自于非功能性的业务需要,例如 bool 表达式解析,http router,日期工夫解析;一部分来自于对公司内基础设施的绑定,如 MQ Client,配置下发 Client,其它服务的调用 SDK 等等。

个别的观点会认为公司内的 SDK 是较为牢靠的,而开源库的稳定性不可控,所以人们在降级公司外部库时往往较为激进,开源库版本升级较为激进。具体到 Go 语言,公司内的库,咱们可能会间接指定依赖的版本为 master(glide 中每次构建会应用 master 分支的代码)。

实际上真的如此么?业界有个名词叫 dependency hell,指的是软件系统因依赖过多,或依赖无奈满足时会导致软件无奈运行。导致依赖天堂的问题有:

依赖过多
一个软件包可能依赖于泛滥的库,因而装置一个软件包的同时要装置几个甚至几十个库包。
多重依赖
指从所需软件包到最底层软件包之间的层级数过多。这会导致依赖性解析过于简单,并且容易产生依赖抵触和环形依赖。
依赖抵触
即两个软件包无奈共存的状况。除两个软件包蕴含内容间接抵触外,也可能因为其依赖的低层软件包互相冲突。因而,两个看似毫无关联的软件包也可能因为依赖性抵触而无奈装置。
依赖循环
即依赖性关系造成一个闭合环路,最终导致:在装置A软件包之前,必须要装置A、B、C、D软件包,然而这是不可能的。
咱们编写的服务也属于软件系统的领域,所以也难以解脱依赖天堂的问题。在微服务场景下,因为本文结尾所述的起因,咱们必然会依赖一大堆内部 SDK。对于开发者来说,实际上真正有抉择势力的就只有我能够应用什么样的开源库。公司内的 SDK 是没有本人造轮子的价值的。毕竟本人造的司内 SDK 也没有人会帮你修 bug,原生 SDK 至多有独自的团队保护。

在开发 lib 时,比拟好的做法是尽量引入少的依赖,以防止下面提到的问题 1。实际上没有几个提供 SDK 的团队能做失去,想想当初 javascript 圈子的 leftpad 事件吧,即便是一行代码的库,被人删除就引起了有数大公司零碎无奈 build 的喜剧。对于目前 Go 编写的零碎,实际上存在同样的危险,咱们的依赖大多来自于 github,如果你们没有应用 vendor 计划把依赖缓存到本人的零碎中,他人删库了你有辙么?

个别 star 数比拟高的开源库作者还是比拟有节操的,删库的人毕竟是少,所以咱们先伪装这个问题不存在。公司内的理论开发过程中,咱们遇到的依赖天堂大多体现在依赖抵触上,这个比拟好了解,比方:

A --> B --> D.v1
A --> C --> D.v2
A 模块依赖 B 和 C,而 B 和 C 别离依赖 D 的不同版本,如果 D.v1 和 D.v2 恰好进行了 API 不兼容的更新,且都是在 github.com/xxx/D 门路下,通过 tag 来辨别版本。那么就会对咱们造成很大的麻烦,B 和 C 如果又恰好是公司内的不同部门的不同团队,要求他们因为这种起因进行兼容性更新就像是去求大爷一样难。

印象中之前 Go 社区是没有方法解决这种问题的,为了解决这个问题,我司还专门对 glide 进行了定制,以在依赖抵触的时候揭示用户,阻止构建,避免之后呈现问题。Go 的社区在这方面也做得的确不太好,gomod 我还没有试用,不分明是否对依赖抵触有优雅的解决方案。之前社区里大多数人对 Go 的依赖治理也始终颇有微词,心愿 gomod 能彻底解决这些问题吧。

除了语言自身的问题,我发现公司内的 library 研发们,基本没有任何开源界的节操,版本升级时基本不思考向前兼容或者向后兼容的问题,并且呈现问题的时候也不会做任何提醒,连日志都根本不打印。常常会有配置管理 v1 和配置管理 v2 的 sdk 同时存在模块中时,产生同一个全局变量初始化两次,发生冲突,逻辑不能失常运行,后果启动阶段没有任何 warning,直到执行阶段才呈现诡异谬误,导致用户在线上埋下定时炸弹的问题。

切实是不晓得该说什么好。

多模块之间的循环依赖就更不用说了,如果循环依赖呈现在单机零碎中,至多在 Go 语言中是没法编译通过的,而因为微服务的关系,循环依赖往往会存在那些没有正当划分业务边界的零碎当中。据我察看,呈现得还不少。

这时候你能从新划分职责,让循环依赖隐没么?

显然是不行的。程序员在以后的微服务架构下,将继续地被内部的垃圾 SDK 和各种莫名其妙的依赖问题所困。

嘴上最终统一,实则最终不统一

当初的架构师总喜爱把最终统一挂在嘴上,如同最终统一是解决分布式场景下数据统一问题的清规戒律。事实上又怎么样呢?

事实上的这些人嘴里的最终统一,往往都是最终不统一。在多个零碎之间进行数据传递时,无非通过 RPC 或者异步音讯。RPC 能保障一致性么?当 B 零碎须要 A 零碎提供数据时,想要达到统一的成果,那么在 A call B 时产生失败,那么必须让 A 中的逻辑终止。这样才可能使 B 中的状态或数据与 A 中的完全一致。这样实际上须要让 A 和 B 成为生死共同体,B 挂了,那 A 也得挂。可能么?在中大型规模的互联网公司的业务零碎中,其上游零碎往往有几十个,因而理论的场景是 A call B -> A call C -> A call D .... -> A call Z。这种状况下,你想让所有零碎中的状态都统一,那是不可能的。

有的架构师又拿出 saga pattern 来说事,我如果有写数据的逻辑,那么我天然会有一套回滚逻辑,只有在两头产生谬误,那么我就对之前的所有调用执行回滚逻辑即可。然而回滚是须要开发量的。我所有上游零碎那都得反对回滚才行啊,你感觉做失去么? saga pattern 的异样解决就更扯蛋了:回滚过程中产生失败的话,那须要人工染指,人肉解决。显然人肉是解决不过去的,机房网络抖动切实太失常了,可能一天两天的就会有一次,每次抖动都造成 bad case,研发人员不必干别的事件了,都去解决 bad case 好了。

当然下面这种状况比拟极其,个别公司内有靠谱的 MQ 计划的话,会选用 MQ 对这种数据同步的场景进行解耦。之前我做的一些总结也都提到过,只有往 MQ 发一条音讯,在字段上尽量满足上游零碎,那么我就不必挨个儿去调用他们了,能够很好地进行解耦。从设计的角度上来讲,这的确是比拟好的解耦模式。然而你要思考,逻辑执行和音讯发送这两步操作并不具备原子性,除非 MQ 反对事务音讯,我能力实现两个操作同时胜利或者失败,何况逻辑执行外部可能还有更多的子操作,这件事件远没有打打嘴炮那么简略。

也有的公司会将发送失败的音讯进行落盘,比方落进 MySQL 或者写入到磁盘,在发送失败之后,由后盾线程在适合的工夫进行重发,以让音讯可能最终收回。一些简略的场景,这样的确算是解决了问题。如果上游对于音讯自身有程序要求呢?比方订单的状态流转,如果程序错了,那状态机最终的状态都错乱了。又是一个麻烦的问题。

在以后的开发环境下,想要达到最终统一的成果须要上下游同时进行很多工作,例如下面说的异步音讯的场景,上游至多须要做失败落盘和后盾发送。而上游须要在状态机的失常状态流转之外,解决各种麻烦的乱序问题。这种乱序解决根本和业务是强相干的,并没有通用计划。即便是同一套状态机,针对不同的业务场景可能还须要定制不雷同的业务逻辑。

除了网络抖动,数据不统一的问题可能还会因为模块上线导致。有些公司(比方我司)为了简略 MQ 的生产逻辑,提供了一套由 MQ 平台生产,而后通过 http post 来将音讯发送给业务零碎的逻辑,升高了业务零碎的音讯生产开发成本(这样就不必应用 MQ 的 client)了。这种状况下如果模块产生上线的话,即便在 MQ 平台侧有 post 重试,但在模块上线时,还是有概率产生音讯失落。如果有一些状态机流转强依赖于这些音讯,那也会造成一部分 bad case。而且这种 bad case 查起来真是没什么意思。之后的数据修复也根本只能靠研发人员自行修复。

这种顽劣的场景下,也有一些人想到了一种办法,我在业务模块中插入多个桩,只有能够每过一段时间触发状态的全量更新,那么我就找一个其它模块来继续地刷新我零碎中的数据状态。从而达到“最终统一”。只有这些最终统一的数据没有裸露给用户,没人看得见,那就是最终统一。倒的确是个可用的计划。但架构师们在吹牛逼的时候,对于这种恶心的逻辑肯定是绝口不提的。

大多数公司的架构师嘴里的最终统一,依附的都是人肉而非技术。

单干的劫难

架构师们常讲的设计定律之中最为重要的是康威定律,康威定律的定义:

Conway's law is an adage named after computer programmer Melvin Conway, who introduced the idea in 1967. It states that. organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations.

这里的 'are constrained to' 即是该定律的精华所在。如果一个公司的组织架构曾经根本成型了,那么基本上设计出的零碎架构和其人员组织架构必然是统一的。

在微服务场景下,团队会依照其所负责的模块被顺次切开成为一个 5-10 人小团队,而后再由更为顶层的架构少来依照组织架构设计相应的零碎。然而这外面有一个先后关系,是先设计零碎,再依据零碎来造成对应的团队。但很多时候也并不一定是如此,因为某些公司招聘速度过快(笑),可能团队先造成了,而后才有零碎设计,这时候,零碎设计可能甚至会被团队架构所副作用(大略)。还是比拟荒谬的。

即便是失常的设计流程,业务需要总是难以预测的。架构师们个别在设计完最后版本的零碎架构之后,便会抽身到新的零碎中持续挖坑。新的需要却在后续的实现过程中慢慢发现无奈与最后的架构设计相匹配,具体体现在很难在以后架构上实现,或实现老本过于昂扬,单模块几人天的事件,在以后架构上须要以月计的工时,这显然是不可承受的。

这时候该怎么办呢?没什么好方法。一套零碎的架构一旦造成了,如果不是产生重大事件(例如迭代龟速导致公司在响应速度上跟不上竞争对手的步调;或者产生舆论事件,导致公司陷入风口浪尖,高层承诺短时间无奈兑现),个别零碎自身并不会有架构上的变动。一线的开发人员最能领会这时候的苦楚,然而苦楚也没有什么卵用,因为这时候没有人有能源去推动架构上的变动。试想,在惊涛骇浪的素日,没有任何一个一线 RD 能有能力去推动一堆比他们高两三级的“专家”做事。而一线的 leader 也没有能源去做这种于本人于本人组齐全有益的变动,哪怕明晓得现行架构已齐全无奈满足业务需要,多一锅不如少一锅。Manager 们就更不用说了,多一事不如少一事,能堆人解决的问题就尽量不必技术去解决。

所以你也看到了,这种问题是无奈解决的。已经在和共事探讨的时候,共事提出,依照这种说法来看的话,小公司的架构可能比大公司还要靠谱?

这当然也不肯定,小公司个别开不出优秀人才的价格,所以优良的架构师基本上是不会去小公司的,这就意味着大多数小公司的架构,必定更加不靠谱。除非他们能继续发展壮大,公司财务衰弱,在不进行服务治理没有方法持续做业务的窘境时,招入了适合的架构师来做全局把控,实现一次大的整体重构,彻底偿还历史技术栈,才会缓缓有所恶化。当然这也只是个空想,业务驱动的公司不可能把业务齐全停下来反对这种技术上的整体重构,记得阿里的人说在 09 年的时候进行公司的服务化,让整个公司的业务停了半年?这种我的项目如果最初成果不好,那负责人必定是要到职谢罪的。大多数技术老板也是肯定没有这个气魄让业务半年没有停顿的,这样搞不好间接就被 CEO 干掉了好吗。

从技术上来讲有解决方案的问题,如果把政治也思考在内,可能就变成了无解的问题。大多数公司内的业务零碎所要接受的这个苦楚的过程从公司倒退的历程上来讲,是必然的。所以各位技术同学,就不要埋怨业务代码写得乱了。

技术人员所能发挥作用的范畴被限度于本人的模块内,或者那些违心接本人需要的其它支持系统间。除了后面说的组织架构的问题,还须要思考 KPI 的问题。

之前和共事一起失去了一个在大公司内推动事件的靠谱论断,如果一件事件在一个部门内就能够解决,那能够开开心心地推动它解决。如果一件事件须要跨部门,那还须要本部门的大领导露面能力解决,哪怕这事件再小。如果一件事件须要跨两个部门,那就没治了,谁露面都不行。这种事件做不了的。而如果一件事件和你要跨的部门 KPI 有抵触,那就更别想了,把部门重组了能力解决,这是 CTO 能力干的事件。

如果想要在大公司失去较好的绩效,遵循 KPI 规定是必然的。没有方法。