本文是對于軟件復雜度的零碎思考和記錄。 內容包括,軟件復雜度本身沒有統一定義; 介紹常見代碼復雜度,圈復雜度;比較復雜度和難度關系;最后回答從三個方面如何降低軟件的難度(復雜度,能力,以及項目控制)。
前面文章介紹軟件復雜度是軟件最大的敵人,其對于軟件開發和維護帶來挑戰。如果復雜度沒有不能很好的控制,甚至失控,那么必然成本超出,時間延誤,功能不能滿足期望,那就災難。軟件危機就是這么來的。
Complexity is the enemy of flexibility. It entangles us in unintended consequences. It blocks our attempts to change. It hides potential defects, making it impossible to be sure our systems will function correctly. Performance, transparency, security — all these highly desirable attributes leak away in the face of increasing complexity.
定義
復雜度可以被感知,影響也被普遍認可,然而對于復雜度卻沒有統一的定義,當然也沒有統一的衡量方式,可以參考不同人的理解。
但是對于軟件不同的側面,可以定義不同的復雜度,可以幫助了解某一個側面或者一個點的復雜度。 比如衡量算法的時間復雜度,常用大O來表示; 算法的空間復雜度; 下面介紹一個常用的衡量代碼復雜的 函數的圈復雜度。
- 函數圈復雜度(cyclomatic complexity)
The cyclomatic complexity of a section of source code is the number of linearly independent paths within it.
簡單就可以數代碼里面分叉(if),循環(for、while)的個數,當做圈復雜度。 如果圈復雜度太大,比如超過10,那么代碼有 1024(2^10) 個獨立路徑 。 那么如何保證代碼的正確,就不是一件容易的事。理論上要測試所有的路徑,至少需要1024個測試用例。啟發 降低函數的圈復雜度??梢酝ㄟ^重構,將巨型函數變為小函數。
上面介紹圈復雜度,只是衡量代碼的復雜度。其實已經與軟件本身的復雜度已經范圍縮小很多了。
復雜度vs難度
復雜度是系統客觀存在的屬性,與系統組成元素,種類,數量,狀態有關,同時元素之間互動,信息交換的頻度有關。這些是系統本身的復雜度,而系統的實現映射到計算機里面,有會帶來偶然的復雜度。同樣系統的開發與維護,需要團隊協作,復雜度增大。 此外,隨著時間系統繼續在演變,大腦對于信息的遺忘,復雜度有上一個臺階。
難度,是我們個體的一種感覺。隨著復雜度的增加,會越的系統越來越難。那么對于系統中如何降低難度,我們就有下面幾個思路。
-
降低客觀復雜度
問題復雜度。 對于正確事情的認識,清楚的表達,以及如何驗證定義清楚,減輕需求蔓延,降低問題復雜度。 USM,BDD,sbe 這些都是從軟件的根源澄清價值,定義范圍,避免二義性,減少折騰。
技術復雜度。 更高的抽象,分解,信息封裝手段; 使用成熟的軟件的框架,庫,標準(http,servlet , rest, sql ...),中間件(event queue, cache, nigix...); 更加靈活的架構,隨著軟件持續演化的架構; 更高界別語言,dsl; 提高代碼的可讀性和維護性,clean code , simple design, 重構等。
環境的限制。 infrastructure as code 的理念,使用Docker提供的封裝和標準環境, 自動化部署,持續發布,k8s 自動化的調度, 監控,這些大大降低環境復雜度和運行的復雜度。
-
提高團隊個人的能力。
- 這個主要是提高團隊或者開發者的技能, 所謂會者不難。
- 深化自己的技術棧.
- 團隊持續學習。
-
通過項目管理,降低軟件開發的干擾。
項目管理,溝通協作,降低項目的干擾,從而減少復雜度。流程,使得軟件開發過程更有秩序,信息暢通,信息透明,加強信任,減少干擾。 這里暫且不談,會在軟件的生命周期里面談到。
敏捷工程實踐,提高對軟件的控制力。 比如TDD, 單元測試,重構,持續集成,持續部署, 自動化。通過反饋,來提高對于系統的感知和控制力。
極限編程和ASE開發都會提高對于軟件的控制力
reference