4.1 細粒度、低耦合、可復用的架構
4.1.1 軟件架構
好的軟件架構讓軟件能夠比較容易地擴展新的功能,或者改進已有的功能,從而讓軟件具有較高的可維護性、可復用性。而從軟件交付過程的視角來看,軟件架構也很重要。
例如,無論是一個大型的單體應用,還是一組在運行時相互配合的微服務,對軟件交付過程有什么影響呢?如果是大型的單體應用,則意味著構建慢,部署也慢,寫幾行代碼想運行一下試試,半小時后見結果。此外,由于構建時就綁定在一起,所以總有很多人在修改,一起集成,一起測試,有很多協調工作要做,而且還相互拖累——一旦某一部分出現問題,整體進度就會被拖慢。
而如果是微服務架構,那么對每個微服務的構建和部署就快得多。如果各個微服務之間的耦合性較弱的話,則通常開發一個新功能只需要改動某一個微服務即可。于是各個微服務可以分頭集成、測試和發布,而不會相互影響、相互等待,不用“等火車”“趕火車”“扒火車”,減少了等待時間。系統解耦得越好,各個子系統、微服務的交付過程就越獨立自主。
軟件不僅是由代碼組成的,還包括軟件部署運行的環境,以及各種配置參數、數據庫表結構等。它們之間的耦合性最好也比較弱,可以分別單獨進行修改變更。例如,不必因為不同環境中配置參數的不同而重新構建源代碼,也不必因為調整業務配置參數而重新走一遍“開發—集成—測試—發布”流程。這也是軟件架構要支持的內容。
構建慢、部署慢、測試慢,代碼合并沖突多,集成頻率低,發布頻率低……遇到這些情況,先往上游看看,看架構是否合理,有沒有改進的空間。如果架構是分層、分模塊的,模塊是細粒度的,模塊間是低耦合的,各模塊是可以分別構建和部署、在運行時才通過API相互配合的,那么集成、測試、發布就好做,就快;反之就不好做,就慢。
4.1.2 測試腳本和測試數據的架構
軟件架構首先影響代碼編寫的效率,這發生在軟件交付過程之前。而軟件架構對軟件交付過程本身的影響,倒像是“副產品”。相比之下,自動化測試腳本和測試數據的架構,對軟件交付過程最重要的影響就是:測試腳本和測試數據的架構好,實現測試用例的速度就快,就好維護,就可以進行更多的自動化測試。于是,軟件交付過程就更快了。
比如數據驅動是把測試腳本與測試數據分離,同一個測試腳本可以跑好幾批數據,分別測試各種正常情況、邊界情況、異常情況。這樣,就不必為每種情況再寫一遍高度類似的測試腳本了。
再比如頁面對象模型,以Web頁面或移動端原生應用頁面為單位來封裝頁面上的控件,以及控件的部分操作。而測試腳本調用操作函數,基于頁面封裝對象來完成具體的頁面操作。這樣,可以清楚地看到在什么頁面上執行了什么操作,也可以更容易地將具體的測試步驟轉換成測試腳本,同時代碼的可讀性和可維護性也得到了大幅提升。
類似地,還有業務流程抽象、關鍵字驅動等。這些方法的本質都是通過合理的分層架構來提高復用性。
4.1.3 組織架構
軟件系統的架構,以及測試腳本和測試數據的架構,要細粒度、低耦合、可復用,由人構成的組織的架構也是這樣的。組織架構也要小團隊、低耦合、可復用,為的是開發并上線一個新特性,最好是一個小團隊甚至一個人就能完成,自主完成工作。不然就會出現很多人和人之間,以及團隊和團隊之間的配合協作、排優先級、工作交接等事情,這些都是很消耗時間和精力的。
在敏捷中經常提到的特性團隊是這么定義的:“特性團隊是指長期的、具備交付價值所需的各種角色的、可以協同完成完整用戶價值交付的團隊。”注意,“特性團隊”中所說的特性,不是指幾天就能開發完成的一個小特性,而是更像一個需要長期開發和維護的獨立產品,或者一個完整功能。我們把特性團隊的定義拆解來看看。
? 長期團隊。團隊應該長期負責某個系統或者系統的某部分,比如某個子系統、某個功能或者某個組件。也就是說,一方面,團隊不能總是打一槍換一個地方;另一方面,某塊內容總是有一個長期負責它的團隊。為什么呢?因為隨著時間的流逝,這個團隊對其所負責的部分越來越了解,開發效率就會越來越高,交付效率也會越來越高。并且團隊會有主人翁責任感,始終注意不讓架構腐化或者別那么快地腐化。此外,在有后續需求或者發現缺陷時能迅速做出反應。總之,這個團隊對這個部分越有自主性,效率就越高,也越讓人踏實。
? 跨職能團隊(或者叫全功能團隊、全流程團隊、Stream-aligned team等)。這個團隊具備交付價值所需的各種角色——每個職能部門不能都是一個豎井,以至于設計、開發、集成、測試、發布時必須到各個職能部門轉一圈兒。各種測試工作,最好是團隊內部的開發人員和測試人員一起就能完成,而不是每次都跑到測試部門去申請本次測試資源。部署操作也一樣,不論是往測試環境中部署還是往生產環境中部署,都應該由團隊自己輕松完成,無須提交變更單給運維人員。敏捷運動興起時,重點強調了需求、開發、測試最好由一個團隊負責,而DevOps運動將其擴展到了部署運維以及安全。
? 獨立完成開發。各個開發團隊之間的劃分也有講究,本質上也是要自主、要解耦。一個新功能的開發,或者一個已有功能的改造,最好是一個團隊就能單獨完成,而不需要牽扯到若干團隊,比如,必須由他們分別來改各自負責的源代碼,否則在軟件交付過程中出現跨團隊的集成、測試、發布等一系列協作時,會很麻煩。如果軟件架構做得好,細粒度、低耦合,那么就比較容易實現各個開發團隊之間的解耦:不同開發團隊和軟件模塊相互對應。由于通常改一個模塊就能實現需求,這就意味著一個需求由一個開發團隊就能獨立實現。
除了特性團隊定義中提到的上述三個要點,團隊規模也很重要。你可能聽說過亞馬遜的“兩個披薩原則”[1]。一個團隊5~9人最佳,團隊再大最好也別超過15人,更大的團隊就要細分,讓每一部分專注于自己的業務,并且擁有相當程度的自主性,可以對結果負責。它的核心是要提高運作效率。
有人是這么評論亞馬遜的做法的:“你可以在不添加新的內部結構或直接報告的情況下添加新的產品線,你不用開會、不必經歷一系列項目流程,就能在物流和電子商務平臺上添加它們。你不需要(從理論上說)飛往西雅圖,安排一場會議,讓人支持你在意大利開展的項目,或者說服任何人將新業務加入他們的路線圖。”
除了細粒度、低耦合,好的組織架構還有一個重要特點就是可復用。以軟件交付為例,應該有組織級的工具平臺團隊,來評估、比選、引入、運維、集成、定制甚至開發與軟件交付相關的工具平臺。這比讓每個開發團隊都重復地做這些事情要劃算得多。在推動軟件交付過程的改進方面,最好也要有組織級的領導協調,根據本企業的業務特點,制定相對統一或至少比較收斂的規范和流程,讓相關人員不用費心就能走上正確的道路,而組織結構調整、轉崗之類的人員流動所帶來的學習成本也會明顯降低。
此外,要留意康威定律。康威定律說的是,你把組織結構做成什么樣子,那么所開發的軟件系統的架構就會長成什么樣子。所以,為了讓軟件系統有一個好的架構,就需要對組織結構深思熟慮,讓它符合我們想要的未來的系統架構。
總之,需要有合理的組織架構,其中的核心就是細粒度、低耦合、可復用,讓每個團隊都具備自主性,獨立負責一個模塊,而這個模塊是細粒度、低耦合甚至是可復用的。于是,整個軟件開發過程就會順暢、高效得多,當然也包括其中的軟件交付過程。
架構細粒度、低耦合、可復用,自己完成一件事情,不要總是動輒牽扯到別的人、別的事,這是軟件交付的第1個策略。合理的組織架構、軟件架構、測試腳本與測試數據架構,讓軟件交付過程順暢、高效。