1. 程式人生 > >架構師必看-架構之美第14章-兩個系統的故事:混亂大都市(一)

架構師必看-架構之美第14章-兩個系統的故事:混亂大都市(一)

                你們修築、修築,預備道路,將絆腳石從我百姓的路中除掉。                                        —《以賽亞書》第57章14節

                 我們要看的第一個軟體系統名為“混亂大都市”。它是我喜歡回顧的一個系統—既不是因為它很好,也不是因為它讓參與開發的人感到舒服,而是因為當我第一次參與它的
開發時,它教給了我有價值的軟體開發經驗。

                  我第一次接觸“混亂大都市”,是在我加入了建立它的公司時。初看上去這是一份有前途的工作。我將加入一個團隊,參與基於Linux的、“現代”的C++程式碼集開發,已有的
程式碼集已經開發幾年了。如果你像我一樣擁有特殊的技術崇拜,就會覺得很興奮。

                   工作起初並不順利,但是你不能指望在加入一個新團隊、面對新的程式碼集時會覺得很輕鬆。然而,日復一日(周復一週),情況卻沒有任何好轉。這些程式碼要花極長的時間來學習,沒有顯而易見的進入系統中的路徑。這是個警告訊號。從微觀的層面來說,也就是從每行程式、每個方法、每個元件來看,程式碼都是混亂而粗糙地壘在一起的。不存在一致性、不存在風格、也沒有統一的概念能夠將不同的部分組織在一起。這是另一個警告訊號。系統中的控制流讓人覺得不舒服,無法預測。這又是一個警告訊號。系統中有太多的“壞味道”(Fowler 1999),整個程式碼集散發著腐爛的氣味,是在大熱天裡散發著刺激性氣體的一個垃圾堆。這是一個清晰的警告訊號。資料很少放在使用它的地方。經常引入額外的巴羅克式快取層,目的是試圖讓資料停留在更方便的地方。這又是一個警告訊號。

                      當我試圖在大腦中建立“大都市”的全圖時,沒有人能解釋它的結構;沒有人知道它的所有層、它的藤蔓,以及那些黑暗、隔離的角落。實際上,沒有人知道它究竟有多少部分是真正能工作的(它實際上靠的是運氣和英雄式的維護程式設計師)。人們知道他們面對的那一小部分割槽域,但沒人瞭解整個系統。很自然,沒有任何文件。這也是一個警告信
號。我需要的是一份地圖。

                      這是一個悲傷的故事,我曾是其中的一部分:“大都市”是城市規劃的惡夢。在你開始整治混亂之前,先要理解混亂,所以我們花了很大的精力和毅力,得到了一份“架構圖”。我們標出了每一條公路、每一條主幹道、每一條很少人瞭解的小路、所有燈光昏暗的輔路,並將它們畫在一張主圖上。我們第一次看到了這個軟體的樣子,並不令人賞心悅目。它是一些混亂的區塊和線條。為了讓它更好理解一些,我們用顏色標出了控制路徑,突出了它們的型別。然後我們後退一步看著它。

                      它令人吃驚。它令人目眩神迷。它就像一隻喝醉了的蜘蛛,跌進了一些海報顏料罐裡,然後在一張紙上織成了一張彩色的網。它看起來就像圖2-1那樣(這是一個簡化後的版本,細節已經修改了,為了保護那些有罪的人)。事情變得很清楚了。我們畫出了倫敦地鐵圖。它甚至有環線。

                       

圖2-1:“混亂大都市”的“架構”

             這就是那種讓跑遍各地的銷售員惱怒的系統。實際上,它與倫敦地鐵的相似性讓人印象深刻:從系統的一端到另一端有很多條路線,哪條路最好通常是不明顯的。地理位置很近的目的地常常很難到達,你希望能在兩點之間再挖掘一條隧道。有時候,走出地鐵換乘巴士實際上是更好的選擇。或者乾脆步行。

              無論從哪個角度來看,這都不是一個“好的”架構。“大都市”的問題超出了設計的範疇,它涉及開發過程和企業文化。這些問題實際上導致了許多架構腐爛。程式碼經過幾年
的“有機”生長,沒有人進行過任何架構設計,而且各個部分是隨著時間推移,沒有經過太多思考就栓在一起的。我們這麼說真的算是客氣的了。沒有人停下來為程式碼建立一個理智的結構。它增長、膨脹,成為絕對沒有任何架構設計的系統的一個典型。程式碼集從來不會沒有架構。這個系統只是擁有一個很糟糕的架構。

              如果我們回顧建立“大都市”的公司的歷史,它所處的狀態是可以理解的(但是不可寬恕):這是一個初創的公司,快速提供許多新版本的壓力很大。延期是不可容忍的—這會帶來財務災難。軟體工程師被迫盡其極限,快速交付。所以程式碼是以一系列瘋狂衝刺的方式壘在一起的。

注意:不好的公司結構和不健康的開發過程將在糟糕的軟體架構中得到反映。

               2.1.1 後果

              大都市”缺少城市規劃,這帶來了許多後果,我們將在這裡進行分析。這些後果的影響是很嚴重的,遠遠超出了你對不良設計的天真想象。地鐵變成了雲宵飛車,飛速地朝下猛衝。

               不可理解
               正如你已經看到的,“大都市”的架構以及缺乏強制的結構,導致了一個很難理解的軟體系統,實際上幾乎不可能修改。新加入專案的團隊成員(譬如我)會被複雜性驚呆,不能夠搞清楚狀況。

                壞的設計確實會招致在它上面疊加壞的設計(實際上它簡直就是迫使你那樣做),因為沒有一種明智的方式可以擴充套件該設計。在所有能解決手上工作的方法之中,阻力最小的總會被採用,沒有明顯的辦法來修復這些結構問題,所以只要能減少麻煩,就會扔進去新的功能。

注意:重要的是要保持軟體設計的品質。壞的架構設計會招致更壞的架構設計。                缺乏內聚

              系統的元件完全沒有內聚性。每個元件本來都應該有一個定義良好的角色,但是它們卻包含了一堆雜亂的、不一定相關的功能。這使我們很難確定元件存在的原因,也很難弄明白系統中已經實現了哪項具體的功能。

              很自然,這讓缺陷修復成為了一場噩夢,嚴重地影響了軟體的品質和可靠性。

               功能和資料都放在了系統中錯誤的地方。許多你認為是“核心服務”的部分卻沒有在系統的核心部分實現,而是由邊遠的模組來模擬實現(非常痛苦並且代價很大)。

               進一步的軟體歷史考察揭示了原因:原來的團隊中存在個人鬥爭,所以一些關鍵程式設計師開始建立他們自己的軟體小帝國。他們把自己認為酷的功能放到他們的模組中,即使它不應該屬於那裡。為了做到這一點,他們於是又實現了更為巴羅克式的通訊機制,把控制連回到正確的地方。

注意:開發團隊中健康的工作關係將直接有益於軟體設計。不健康的關係和個性膨脹會導致不健康的軟體。                內聚和耦合 軟體設計的關鍵品質是內聚和耦合。這不是什麼新奇的“面向物件”概 念;自從20世紀70年代出現結構化設計開始,開發者對這一概念已經談論 了許多年。我們的目標是通過設計使系統的元件具備下列品質: • 高內聚(Strong cohesion) 內聚是一個測量指標,說明相關的功能如何聚集在一起,模組內的各部分 作為一個整體工作得如何。內聚性是將模組粘成一個整體的膠水。 弱內聚的模組是不良分解的訊號。每個模組都必須具有清晰定義的角色, 而不只是一堆不相關的功能。 • 低耦合(Low coupling) 耦合是模組之間獨立性的測量指標—它們之間進出“電線”的數量。在 最簡單的設計中,模組幾乎沒有什麼耦合,所以彼此間的依賴關係較少。 顯然,模組不能夠完全解耦,否則它們將根本不能夠一起工作! 模組之間的聯絡有多種方式,有的是直接的,有的是間接的。模組可以調 用其他模組中的函式,或被其他模組所呼叫。它可能使用其他模組提供的 Web服務或設施,可能使用其他模組的資料型別,或提供某些資料讓其他模 塊使用(可能是變數或檔案)。 好的軟體設計會限制通訊的線路,只提供那些絕對需要的。這種通訊線路 是確定架構的一部分因素。

                不必要的耦合
                “大都市”沒有清晰的分層。模組之間的依賴關係不是單向的,耦合常常是雙向的。元件A會到達元件B的內部,目的是完成它的一項任務。在其他的地方,元件B又通過硬編碼呼叫了元件A。系統沒有最底層,也沒有控制中心。它是整體式的一大塊軟體。這意味著系統的各部分之間耦合非常緊密,你想啟動系統骨架就不得不建立所有的元件。單個元件的任何改變都會波及其他元件,需要修改許多依賴它的元件。孤立地看程式碼元件沒有任何意義。

                 這使得低層次的測試不能夠進行。不僅是程式碼層次的測試不可能進行,而且元件層次的整合測試也不能夠建立,因為每個元件都依賴於幾乎所有其他元件。當然,在公司中,測試從來也不具有很高的優先順序(我們根本沒有時間來做這種測試),所以這“不成為
問題”。不必說,這個軟體不太可靠。

注意:好的設計考慮到內部元件連線的連線機制和連線數(以及連線性質)。系統的單個部分應該能夠獨立存在。緊耦合將導致不可測試的程式碼。

               程式碼問題
              不良的頂層設計所帶來的問題也影響到了程式碼層面。問題會引起其他問題(參見Hunt和Davis[1999]中關於破窗理論的討論)。因為沒有通用的設計,也沒有整體專案“風格”,所以也沒有人關心共同的編碼標準、使用共同的庫,或採用共同的慣例。元件、類和檔案都沒有命名慣例。甚至都沒有共同的構建系統。膠帶、Shell指令碼、Perl膠水與makefile和Visual Studio專案檔案混在一起。編譯這個怪物被視為一場複雜的成人儀式!

               “大都市”最微妙而又最嚴重的問題是重複。由於沒有清晰的設計,也不清楚功能應該處於的位置,所以輪子在整個程式碼集中不斷重新發明。一些簡單的東西,如通用演算法和資料結構,在許多模組中重複出現,每種實現都帶有自己的一些未知的缺陷和怪異的行
為特徵。更大範圍的關注點,如外部通訊和資料快取,也實現了許多次。

                  更多的軟體歷史考察揭示了原因:“大都市”開始是從一系列獨立的原型拼起來的,這些原型本該拋棄。“大都市”實際上是偶然形成的城市群。當代碼元件縫合在一起時,元件之間匹配得不好。隨著時間的推移,這種隨意的縫合開始破裂,所以元件互相拉扯,
導致程式碼集破碎,而不是和諧地協作。

注意:鬆弛而模糊的架構將導致每個程式碼元件編寫得不好,並且相互之間匹配得不好。它也會導致重複的程式碼和工作。

                   程式碼以外的問題“大都市”內部的問題已經超越了程式碼集,在公司中其他的地方導致了混亂。不僅開發團隊中有問題,而且架構的腐爛也影響到了支援和使用該產品的人。

                   開發團隊
                   專案的新成員(例如我)被複雜性驚呆了,不能夠搞清楚狀況。這很好地解釋了為什麼很少有新人能在公司裡待下來—員工流失率非常高。那些留下來的人非常努力地工作,專案的壓力非常大。規劃新的功能會導致極大的恐懼。

                    緩慢的開發週期
                    由於維護“大都市”是一項恐怖的任務,所以即使是最簡單的變更或“很小的”缺陷修復都不知道要花多少時間。管理軟體開發週期非常難。客戶只好等著實現重要的特徵,管理層對開發團隊不能滿足業務目標感到越來越沮喪。

                   支援工程師
                   在支援這個極不尋常的產品時,產品支援工程師度過了可怕的時光,他們要設法弄明白很小的軟體版本差異之間錯綜複雜的行為差異。

                    第三方支援
                   專案開發了一個外部支援協議,支援其他裝置遠端控制“大都市”。由於它只是軟體內部結構上面薄薄的一層,所以它反映了“大都市”的架構,這意味著它也是巴羅克式的、難以理解的、容易偶爾出錯的、不可能使用的。第三方工程師的生活也
被“大都市”的可怕結構搞得一團糟。

                   公司內部政治
                   開發問題導致了公司內部不同“種族”的分裂。開發團隊與營銷銷售團隊之間關係緊張,每次新版本要推出時,製造部門總是要承受巨大的壓力。經理們已經絕望了。

注意:不良架構的影響不僅限於程式碼。它會進一步影響到人、團隊、過程和時間表。                   清晰的需求

                 軟體歷史考察凸顯了“混亂大都市”之所以混亂的一個重要原因:在專案開始之初,團隊並不知道要構建的是什麼。本來的初創公司知道它要佔領哪個市場,但不知道哪種產品能佔領這個市場。所以他們兩面下注,要求一個可以做許多事情的軟體平臺。噢,我們昨天就想得到它了。所以程式設計師們急急忙忙建立了一個毫無希望的總體基礎設施,它具有做任何事情的潛力(但做得不好),而不是建立一個把一件事情做好的架構,並能夠在將來進行擴充套件,做更多的事情。

注意:重要的是要在開始設計系統之前知道你打算設計什麼。如果你不知道它是什麼,也不知道它將做什麼,暫時不要開始設計它。只設計你知道需要的東西。

                 在規劃“大都市”的早期階段,有太多的架構師。面對糊塗的需求,他們都拿著一塊拼不起來的拼圖,試圖獨自工作。他們在工作時沒有考慮到整個專案,所以當他們試圖將這些拼圖拼在一起時,就拼不起來了。沒有時間進一步思考架構,軟體設計的各個部分有一些重疊,於是開始了“大都市”的城市規劃災難。

2.1.2 現狀

                “大都市”的設計幾乎完全是無可救藥的—相信我,隨著時間的推移,我們也嘗試過修復它。修復工作需要返工、重構、修改程式碼結構中的問題,這些已經成為不可能的任務。重寫也不是省事的方案,因為支援老的、巴羅克式的控制協議是需求的一部分。你可以看到,“大都市”的“設計”產生的後果是殘酷的,並且會無情地變得更糟。很難加入新的特性,所以人們只是忙著新增更多不完善的功能、救急補丁和編造的謊言。沒有人在面對程式碼時感到愉快,專案正盤旋著向下栽。缺乏設計導致了不良的程式碼,從而又導致了不良的團隊精神和不斷變長的開發週期。這最終導致了公司嚴重的財務問題。最後,管理層宣佈“混亂大都市”已經不盈利了,它被拋棄了。對於任何組織機構來說,這都是勇敢的一步,特別是這個公司一直都眼高手低,同時又試圖避免沉淪。帶著團隊從以前版本中得到的所有C++和Linux經驗,他們在Windows上用C#重寫了系統。猜猜看會怎麼樣。
              2.1.3 來自“大都市”的名信片

              那麼我們學到了什麼?不良的架構會產生深遠的影響和嚴重的反彈。在“混亂大都市”中缺少預見性和架構設計,導致了下面的問題:
• 低品質的軟體和漫長的版本釋出週期。
• 系統沒有彈性,不能夠適應變更或新增新的功能。
• 無處不在的程式碼問題。
• 員工問題(壓力大、士氣低、跳槽等)。
• 大量混亂的公司內部政治。
• 公司不能成功。
• 許多痛苦和麵對程式碼深夜加班。

相關推薦

架構-架構14-系統故事混亂大都市()

                你們修築、修築,預備道路,將絆腳石從我百姓的路中除掉。                                        —《以賽亞書》第57章14節                  我們要看的第一個軟體系統名為“混亂大都市”。

架構的工作都幹些什麼?!想做架構

之前有網友說想看架構師升級的文章,所以寫了本文。先給本文中架構師做個定義:第一,能力上達到(似乎是廢話),第二,公司肯承認,不僅能給架構師的頭銜,更能按架構師的標準發工資。 對於程式設計師來說,架構師是職業發展的一道坎,如果跨過去了,後面就前途無量了,否則可能一直得做著

成為Java高階架構的15本書

作為Java程式設計師來說,最痛苦的事情莫過於可以選擇的範圍太廣,可以讀的書太多,往往容易無所適從。我想就我自己讀過的技術書籍中挑選出來一些,按照學習的先後順序,推薦給大家,特別是那些想不斷提高自己技術水平的Java程式設計師們。 Java程式設計入門類 對於沒有Java程式設計經驗的程式設計

架構微服務架構綜述

目錄如下: 一、微服務架構介紹 二、出現和發展 三、傳統開發模式和微服務的區別 四、微服務的具體特徵 五、SOA和微服務的區別 六、如何具體實踐微服務 七、常見的微服務設計模式和應用 八、微服務的優點和缺點 九、思考:意識的轉變 十、參

架構軟體架構圖的藝術

要點 設計軟體架構圖並非一件輕而易舉的事情,即使是很簡單的一個架構圖也可能會出錯。有意義且具備一致性的架構圖有助於為不同的利益相關者澄清事實,並達成共識。 在大多數情況下,問題的根源並不在於是否使用了一門有效的架構描述語言(比如UML),而在於

Java架構的10本書

1、大型網站系統與JAVA中介軟體實踐 本書圍繞大型網站和支撐大型網站架構的Java中介軟體的實踐展開介紹。 從分散式系統的知識切入,讓讀者對分散式系統有基本的瞭解;然後介紹大型網站隨著資料量、訪問量增長而發生的架構變遷;接著講述構建Java中介軟體的相關知

架構的工作都幹些什麼?!想做架構

先給本文中架構師做個定義:第一,能力上達到(似乎是廢話),第二,公司肯承認,不僅能給架構師的頭銜,更能按架構師的標準發工資。 對於程式設計師來說,架構師是職業發展的一道坎,如果跨過去了,後面就前途無量了,否則可能一直得做著程式碼coding的事情。 本文將從“如何升級”和

數學 3 統計語言模型

語料原理上越多越好,但是要把握好一個度的問題比如機器翻譯中的雙語預料就比較少的,還有就是有很多資料都有噪聲和錯誤的,訓練語料的噪聲高低也會對模型的效果產生一定的影響,因此在訓練資料的時候通常會對訓練資料進行預處理,一般情況下,少量的隨機噪聲清理的成本非常高,通常就不做處理,還有就是有些噪聲處理的太乾淨反而是不

數學 2 自然語言處理-從規則到統計

2,如果僅僅使用文法規則就想覆蓋哪怕是20%真是的語句,文法規則的數量至少也要幾萬條,而且還要說明各個規則特定的使用環境,也就說你能考好  資料結構期末試卷,但是換成 考研的試卷你就考不好了,換成軟體工程裡的資料結構你照樣考不好,也就是說呢,你永遠也窮舉不完的。

.NET Core實戰專案CMS 設計篇-系統開發框架設計

這兩天比較忙,週末也在加班,所以更新的就慢了一點,不過沒關係,今天我們就進行千呼萬喚的系統開發框架的設計。不知道上篇關於架構設計的文章大家有沒有閱讀,如果閱讀後相信一定對架構設計有了更近一部的理解,如果你沒有閱讀也希望大家能好好閱讀一下!其實說白了,架構是為了應對軟體系統複雜度而提出的一個解決方案,架構設計的

《程式設計》——程式設計判斷連結串列是否相交

問題: 給出兩個連結串列的頭指標,判斷這兩個連結串列是否相交。假設兩個連結串列均不帶環。 分析與解法: 【解法一】 如果兩個連結串列都無環,則可以把第二個連結串列接在第一個連結串列後面,如果

面試案例

== 一個 nbsp 復雜 else font null 整數 lse 7.1 案例一 面試題49:把字符串轉換成整數 題目:將一個字符串轉換成一個整數,要求不能使用字符串轉換整數的庫函數。 數值為0或者字符串不是一個合法 的數值則返回0 思路:若為負數,則輸出負數

架構十二-好的架構

        我們曾提到,架構師玩的是折中的遊戲。對於一組給定的功能需求和品質需求,沒有唯一的正確架構和唯一的“正確答案”。我們從經驗中得知,應該對架構進行評估,確定它是否滿足其需求,然後再投入資金

Java 架構 -- 讀書單

評論 mybatis blog 競爭 事情 美國 上下 好的 案例 “學習的最好途徑就是看書“,這是我自己學習並且小有了一定的積累之後的第一體會。 個人認為看書有兩點好處: 1.能出版出來的書一定是經過反復的思考、雕琢和審核的,因此從專業性的角度來說,一本好書的價值遠超其

(轉)MySQL數據庫的優化-運維架構會高薪技能,筆者近六年來一線城市工作實戰經驗

發的 端口號 忘記 從服務器 mysql啟動 釋放資源 range 參數取值 如果 標簽:服務器 數據庫 老男孩 高薪技能 一線城市 原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://liangweilin

菜鳥要做架構——java效能優化for迴圈

完成同樣的功能,用不同的程式碼來實現,效能上可能會有比較大的差別,所以對於一些效能敏感的模組來說,對程式碼進行一定的優化還是很有必要的。今天就來說一下java程式碼優化的事情,今天主要聊一下對於for(while等同理)迴圈的優化。 作為三大結構之一的迴圈,在我們編寫程式碼的時候會經常用到。

優秀後端架構會知識史上最全MySQL大表優化方案總結

本文原作者“ manong”,原創發表於segmentfault,原文連結:segmentfault.com/a/1190000006158186 1、引言 MySQL作為開源技術的代表作之一,是網際網路得以廣泛流行的重要基礎技術之一。 國外 GitHub、Airbnb、Yelp、

.NET Core實戰專案CMS 設計篇-白話架構設計

原文: .NET Core實戰專案之CMS 第九章 設計篇-白話架構設計 前面兩篇文章給大家介紹了我們實戰的CMS系統的資料庫設計,原始碼也已經上傳到伺服器上了。今天我們就好聊聊架構設計,在開始之前先給大家分享一下這幾天我一直在聽的《從零開始學架構》裡面關於架構設計的定義以及架構設計的三大原則,希望能對大家

Java高架構、分散式架構、高可擴充套件、高效能、高併發、效能優化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分散式專案實戰學習架構

工作1-5年開發經驗,當你們提出漲工資的時候,或者要offer的時候底氣怎麼樣,是不是底氣十足,不給漲工資就辭職,是不是有自信提出來主管、或者是專案經理都能同意,他們相當設法把你留住。如果這樣你才是成功。什麼技術都沒有何談工資! 給你分析一下這些技術,給大家羅列一些技術,看