在架構師們很喜歡的 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 規則是必然的。沒有辦法。