在架构师们很喜欢的 Domain Driven Design,即 DDD 中,第一课就是教导团队造成本身独有的通用语言(Ubiquitous Language),做为业务概念沉淀下来。javascript
做为非英语母语的国家,咱们在平常交流中使用的是中文,在公司业务战略描述上使用的是中文,在高层进行任务拆分的时候使用的是中文,在领导安排工做的时候使用的是中文。惟独到了具体实现,即代码这一环节便变成了英文。固然这里咱们不考虑有些公司会有汉语拼音这种尴尬的状况。php
两种语言天生便有难以填平的鸿沟,在业务人员编写代码时,从中文到英文的转换,每每丢失一部分业务信息,产生一部分信息噪音,或者发生概念上的偏移。java
英文语系的人对业务进行建模时,与业务方(领域专家)交流时,产生的概念和反馈能够直接落实到代码上,他们所使用的词汇不会发生变化。而其它语系的人就会在编写代码的时候发生概念偏移,好比我司是作打车业务,快车在不一样的系统中会存在不一样的翻译,有人称之为 fastcar,有人称之为 quickcar,有人甚至就直接是 kuaiche。甚至同一个系统中,对于同一个概念也会存在不一样形式的自创翻译。即便以文档的形式记录了业务的标准翻译,但显然以国内业务叠代的速度,这种词汇上的统一是作不到的。即便在一个只有 7~8 我的的组中都作不到。并非全部人的英文均可以达到可用的程度,有些代码中的词汇可能根本就是词不达意,是某些搜索引擎中给出的直译结果,与真实的含义相差十万八千里。git
这样的代码会给后来人带来理解上的困惑。一旦在同一个系统中,针对同一个业务概念存在三种以上的不一样词汇,就须要阅读者在这些“错误”的词汇上不停地进行上下文切换,以正确地理解错误词汇的涵义。程序员
可能有些人会提出反驳意见,碰上这种状况咱们只要对代码进行重构就能够了,并不须要被这种弱智的事情折磨啊。重构虽好,在不少状况下,词汇的重构是不可能的。打个比方,上面提到的 fastcar 出如今咱们系统提供给别人所用的 api 的关键字段中,quickcar 出如今咱们内部数据库的字段名中,kuaiche 出如今异步发送的消息中。这种时候修改任何一个单词,对于咱们来讲都是不可能的事情。api 和事件中的字段名是咱们对于外部系统的承诺,这种承诺也是编程契约中的一部分,不能随便修改。即便咱们想要修改,在当今大多数互联网公司的架构下,根本就无法知道究竟是谁在使用你的哪个字段。也就是说,咱们没有办法得到粒度细到“字段”级别的外部使用信息,因此咱们没有办法对契约自己进行重构。若是将来的微服务管理能对服务间的依赖进行标准化,而且可以对服务之间字段的依赖进行显式管理,那么契约就是能够进行变动的了(就像单模块的重构那样),不过这也就是个设想,显然不太可能。而数据库中的字段虽然有重命名方法,而且在 《Refactoring Databases》这本书中也给出了各类数据库重构的完善方案。但一样的,上了体量的互联网公司,想要动动数据库结构,是比登天还难的(等五年后应该好一些)。github
因此当你接手到这样的系统时,读代码的时候确定是会骂娘的,可是读完以后也确实没有什么办法。只要你负责维护,就持续地接受这种痛苦吧。数据库
通用语言的问题不仅是单模块中存在,跨模块时也存在。在微服务的架构下,不少需求是必然会跨越模块的。别说不可能,那些鼓吹中台的公司跨模块的需求更广泛。一个需求改 20 个模块都不奇怪。编程
模块间负责人探讨新功能的实现时,混乱的命名和词汇也极可能让两边的沟通变得驴头不对马嘴。在服务之间是接力棒式运做,没有中心服务时,这种状况特别广泛。相信你也遇获得。api
遗憾的是,目前推崇的微服务架构是没有办法解决这样的问题的。在肉眼可见的未来,程序员依然会由于概念产生的歧义而不断地受苦。缓存
这些苦痛最终都会体现到业务开发迭代的速度上。
微服务的布道师们特别喜欢鼓吹一个观点:拆分微服务以后,咱们能够随意地对小模块进行重构,选择最合适的技术栈,而且若是写失败了随时对这个模块拿其它语言进行重写。这一点被大多数布道师看成微服务的重点优点。
可是布道师们有意地把这样作所带来的问题忽略了,或者更恶意的是,他们明知道有问题,可是不说?啊哈哈。
一个公司业务上有多种语言的话,理论上能够吸引到各类“语言的人才”。这确实不假,而且能够提供给各类语言大佬一个互相掐架的优秀竞技场,只要干掉对手(其它语言的大佬)了,我就能够扩张团队,让团队把全部其它语言的模块用咱们擅长的语言重写一遍,善哉善哉。小伙子们一年的事情就都安排上了。
可是显然这种说辞是有问题的。在现行的微服务架构下,除了业务自己的研发人力投入以外,在业务以外的支持系统的研发工做也有很大的工做量,好比典型的,服务发现,熔断,优雅重启,存储系统 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 规则是必然的。没有办法。