敏捷的軟體架構設計:可擴展的軟體架構

敏捷底下的軟體架構

圖片取自:http://m.001zf.com/newshow.php?itemid=696

前一篇,我分享了您的軟體架構夠敏捷嗎?而我寫過許多關於架構設計的相關文章,但今天這一篇,可能是最難寫的一篇?因為,在(確定的需求/沒有 Deadline 的時間壓力下),寫程式並不件難事,對吧?那麼真正難的在哪裡?真正難的是在,有限的時間 與 資源內,發展出(符合客戶需要/為客戶產生價值)的商用軟體,且這個軟體須具備一定的可延展性、擴充性、可維護性,並在企業的可控制的成本範圍內,或者,在敏捷的每一個迭代開發裡,逐漸發展成為客戶所需要的軟體,對吧?軟體公司為企業創造與量身訂做軟體也是為了賺錢,若軟體開發所投注的成本成為無限的話,虧本的生意沒有人會想做的。


傳統的軟體開發產生的架構問題

圖(一)、傳統軟體開發的前身 SDLC (Software/System Development Life Cycle)

SDLC 是早期用以描述一個資訊系統,從無開始規劃、分析、建立、測試、直到最終完成的一個過程。看似無任何問題,事實上,它也運作了幾十年,似乎也確實沒有任何問題,許多團隊也是能夠創造與交付出符合客戶需求的軟體,可是,慢慢的,許多團隊與軟體公司漸漸地發現,當需求變動性高、需求不確定因素高的時候、或者在許多實際的市場機制下,軟體的『開發』與『發展』逐漸與慢慢地跟不上時代的演進 與 市場的變化了。這怎麼說呢?因為當不了解需求、不了解客戶想要的價值時,你所花的(工/成本)絕大部分是浪費的,因為軟體開發越到後期修復的成本是越高的。

以傳統瀑布式開發來說,我得先做完需求分析、才可進行系統的設計,而當系統設計完成後、才可開始進行系統的(程式碼撰寫/Implementation/實作),但問題來了,什麼叫做【系統設計完成】?難道我得在一開始,弄清楚客戶的所有需求?因為系統設計完成、也代表架構設計完成了?如果軟體架構可以在程式碼撰寫前就確定,這不就代表需求必須固定?問題是…. 這是不可能的….. 這其實是一個【雞生蛋、蛋生雞的問題】

圖(二)、雞生蛋、還是蛋生雞?


0 缺陷的架構 = 0 擴展的軟體架構

在早期,曾經有團隊/軟體公司 將所有功能均提供在軟體產品裡,也就是大雜燴的方式,嘗試滿足市場各種不同的需求,筆者很早期待過的軟體公司也還真的經歷過這樣的模式,而在當時,筆者也還真的認定為,這是理所當然的,因為這麼一來,我們的軟體架構只需要被設計一次,如果我們能涵蓋市場裡 70% 的客戶的需求,而我們也能夠接下這些客戶,而不費吹灰之力,就能快速的開發出客戶所需的軟體,因為我們只是把開發好的眾多的模組(Module/Functions)、根據同一個 Domain Known-how 所可能會需要的功能,都加以開發好,並分門別類。再透過抽換、或抽離,客製成目前這個客戶所需的一個軟體。

這樣的方式看似很美好,但是事實上淺藏極大的架構問題,為什麼我這麼說呢?

(1). 使用單一功能滿足所有企業的使用者難以永久滿足… (因為總是會有需要客製的部分)

(2). 功能一定會微調、若為此開立分支(Version Control)將產生另一個災難

(3). 客戶一多,表示你的功能分支越多、這又會產生另一個災難

(4). 軟體架構因為為滿足 A 客戶的某 Function ==> 而導致 B 客戶另一個 Function 失敗

(5). 疊床架屋的軟體終究越來越龐大、每修正一個 Function 或是 擴增一個 Function 都會是一個耗時耗力的過程

(6). 更不用說測試了….

…. 還有說不完的問題…..


軟體架構應該要可以逐步的發展

圖(三)、Implementing Lean Software Development: From Concept to cash

再近代的軟體開發理論裡,包括在『Implementing Lean Software Development: From Concept to cash』的書中,都提到了應該不需要等到軟體架構都完全確定後,才可以開始撰寫程式。且實際的軟體開發中,筆者最近2-3年來實做專案時,嘗試以敏捷方法與迭代方式進行專案的開發,不過筆者以 OOAD/UML 來驅動 Domain Model 的設計,以 Use Case Model 來確定需求的 boundary,但我是搭配 User Story Mapping ,就是用一種方法,一種如何將你最後產出的『用戶活動 (User Activity)』與 最後更加細節的『用戶故事 (User Story)』推展至 Use Case 中,但我不是完全的設計,有些朋友看見 UML 後就會認為會花費許多時間在做文件,其實事實上,我通常只需要半小時就可以畫出一個三角關係的 UML 圖形,只是這個圖形必須夠抽象。有興趣的讀者可參考我另一篇文章『決戰 OOAD 系列(一):使用 UML 分析的黃金三角』,並結合 Clean Architecture 的插件式軟件架構,逐步展現出架構的全貌。詳細關於 Clean Architecture 在實務上的例子,可以參考筆者先前的文章:『從使用者需求、談架構設計(二)- Clean Architecture 一個整潔的架構篇』。

傳統的瀑布式 Waterfall 為人所詬病的就是,當你確定完需求、開始做系統設計、接著開始實作 Programming 時,而這時候,往往已經過度設計了。


測試是迭代開發的最佳保護網

在 『Specification by Example中文版:團隊如何交付正確的軟體』一書中提到,因為敏捷的思想,幾乎改變了整個軟體開發對於【交付階段】的看法,因為我們不可能凍結『變化』、市場隨時會改變,透過『迭代』為基礎,使的 Spec 的實例化變得可行,而且可獲得極大好處,加上將軟體開發切割成多個衝刺(Sprint),要在每一個極短的衝刺時間內、 完成一個交付階段 (MVP, Minimum Viable Product),每一個衝刺所需要完成的代辦項目(PBI)得透過價值來排列優先順序、並消除常見的重工 (Rework) 的問題=漸少浪費,這與先前提到的 Clean Architecture (插件式設計) 避免過度的設計也完全的相互輝映(避免更多浪費與技術債),從價值來決定軟體 Scope 規模。


TDD/ATDD

而然而,這樣就夠了嗎?在極短的時間內交付 MVP 增量開發+根據功能設計勘用與可擴展的軟體架構時,若沒有測試的保護,軟體開發仍然存在極大的風險,即便是敏捷開發也一樣,沒有撰寫測試的軟體,除了測試成本無法降低外,也代表著系統物件的職責容易牽扯在一起,也表示容易設計出系統複雜高的軟體架構,複雜度高也導致軟體不容易維護。所以,結合 TDD 與 ATDD 的開發方法會是迭代開發中,最佳的保護網。

待續…




關於 Gelis:

資深 .NET 技術顧問

FB 社團 (軟體開發之路):

https://www.facebook.com/groups/361804473860062/

FB 粉絲團 (Gelis 的程式設計訓練營):

https://www.facebook.com/gelis.dev.learning/

我講授過的課程 SlideShare:

https://www.slideshare.net/GelisWu


以下是我經營的項目與內容:

(1). 企業內訓課程

(2). 專業顧問


企業內訓課程:

1. .NET Core 3.1 從入門到進階

先前實體課程連結

2. 跨平台的 Web API Framework 框架設計

先前實體課程連結

3. 決戰 OOAD 系列課程 - 使用 UML

先前實體課程連結

4. 單元測試 UnitTest 與 Moq 物件實務課程

先前實體課程連結

5. 快速開發系列 - C# Project Templates 範本設計

留言

這個網誌中的熱門文章

什麼是 gRPC ?

什麼是 gRPC(二)- 來撰寫第一個 Hello World 吧!

常見的程式碼壞味道(Code Smell or Bad Smell)