軟體架構設計 - 希望開始就知道的 5 件事

閱讀時間約 8 分鐘

Buy someone a cup of coffee to learn how to architect your software from their stories.


當我們從事軟體開發工作一段時間後,有些人會開始接觸軟體架構設計。由於每個軟體架構設計者的對問題的理解與知識經驗差異會導出不同的設計架構。

近期與同事的軟體設計案例經驗交流後,就很希望自己剛開始學習軟體架構設計的時候就有人能用實際的軟體架構設計經驗來帶我入門。儘管這次討論的軟體架構設計規模較小,亦足以作為起點來聊聊作為一個新的軟體架構設計者希望開始就知道的 5 件事。

學會用軟體架構設計工具

軟體架構設計的產出是 SAS (Software Architecture Specification) 也就是軟體架構設計規格書,此設計文件乘載了架構設計者的理念、對問題的理解與如何解決問題的觀點。

有時候軟體架構設計過程可以很簡單,例如一人統包設計兼開發的小專案,架構設計甚至簡單至一張紙、一草圖足矣;如果架構設計者面對的是跨團隊、大型複雜的軟體專案時就需要透過軟體設計工具 (ex: UML),來產出對應設計文件與團隊成員溝通協作。

當架構設計者要跟開發團隊討論靜態設計架構時就會用靜態類別圖 (Class Diagram) 來表達軟體內部的類別物件們與它們之間的彼此關聯性;想要說明物件互動狀態時,會用時序圖 (Sequence Diagram) 以時間軸的角度來呈現軟體元件間的互動與資料流動狀態;其他像是案例圖 (Use Case)、流程圖 (Flow Chart) 也能用來協助與非軟體職能的角色 (ex: PM) 進行溝通。

對架構設計者而言,學會一套軟體架構設計工具是必備的手段,利用工具做好架構設計、達成團隊的溝通才是真正的目的。

嚴謹觀點達到設計共通性

我認為一個好的軟體架構設計必須超越程式語言的限制達到設計共通性,換句話說,負責開發實作的人拿到設計圖後不管使用哪一種程式語言都要能順利實作才行。

舉例,在使用靜態類別圖用設計軟體架構時,設計者最好是選用對物件導向有嚴謹定義的程式語言來思考設計,例如 C#, Java 。嚴謹的語法定義提供了必要的類別 class、抽象類別 abstract 、介面 interface 等設計元素, public, private, protected 等能見度關鍵字也讓設計者能對成員(Member)、方法(Method)進行控制做好類別封裝的工作。

不過這次用來設計的程式語言是 Python,其物件導向的語法定義沒有可以用來宣告「介面」或「抽象類別」等關鍵字(只能觀察 Member 是否有 @abstract 的 decorator),類別成員與方法能見度也預設只有 public 一種,因此僅用 Python 作為觀點的架構設計者很容易受限。

只能用「類別與繼承」的設計方式,就像只用一隻手打架完全無法發揮真正實力。

單一繼承+介面 vs 多重繼承

Java 跟 C# 都是單一繼承+介面的設計理念,當我們想要描述 public abstract class A extends B implements C, D (C,D 是 Interface)的設計時,很容易在靜態類別圖上實現,開發者可以很清楚看出抽象類別 A 繼承了 B 且必須實作兩個介面 C, D(UML 的類別跟介面的 Icon 長不一樣)。

沒有介面關鍵字的 Python 設計者就只能把介面改用一般類別,然後想辦法在靜態設計圖上採取多重繼承方式來呈現上述的關係(或許 Python 的 Duck Type 也是一種介面的方式吧),於是同樣一句話到了 Python 這邊就會變成 class A extends B, C, D,想當然耳開發者拿到這樣的設計圖跟本無法意會哪些是應該設計成抽象類別、哪個又該設計成介面。

要記住軟體架構設計(ex: 類別圖)是設計給人看的,要避免模糊的定義或使用複雜多重繼承設計,因為那只會讓合作的開發者們感到困惑,增加你的溝通成本降低團隊開發效率而已。做為一個軟體架構設計者,我的主張是能使用單一繼承就不要搞多重繼承,化簡為繁並不是我們該做的事。

多重繼承能做到的設計,單一繼承+介面可以做得更漂亮

複雜類別用合成取代繼承

當我們在學習物件導向的繼承概念時最常被拿來說的好處就是 Reuse,因為子類別繼承父類別後就可直接調用繼承父類別過來成員與方法 (假設都是 public),而達成所謂的 Reuse,似乎有意地想把繼承跟 Reuse 畫上等號。

如果繼續把這樣的觀念發揮到極致的話,就會為了實現一個複雜物件的功能而繼承多個父類別或實作了一堆介面進而生出一個具有龐大複雜繼承體系的怪物物件。雖然這種的設計方式還是能被實作出來,但設計邏輯上並不符合現實世界的設計方式,想要解決這類設計問題的方式就是用合成(或聚合)來取代繼承關係。

所謂的「符合現實世界的設計」是指獨立模組功能、整合由小而大,整體通過整合不同的模組介面控制來實現我們想要的功能。以手機的拍照功能為例,手機實現照相功能並不是通過「繼承」相機來獲取照相功能的,不信的話可以把手機拆開觀察其內部(網路找圖,別真的自己拆手機),手機的照相功能是「合成」了一個或多個相機模組來實現的;換句話說,我們看的到的手機,就是一個合成了多個功能模組的集合體,所以「獨立模組功能、整合從小而大、整體通過模組介面整合」才是我們符合現實世界的設計邏輯。

對,使用合成取代繼承除了符合設計邏輯外,功能獨立的模組也代表變化的部分封裝的更好;整體可以通過介面控制的模組也代表耦合性低,才是我們該做的事。

在軟體架構設計上力求「高內聚、低耦合」

介面設計會更有優勢

我認為一個好的架構設計者除了具備上述良好的設計邏輯的觀念外,也應該仔細思考共同模組的設計策略。可以採用 top-down 從全局觀察的介面設計或是 bottom-up 先建構物件後再來進一步抽象化最終達到介面設計。除非我們一開始入行很幸運就落腳在一個組織規模夠大、角色分工明確的軟體團隊裡接受專業的架構設計訓練,否則我想大部分的人也都應該都是從 bottom-up 的方式逐步修練、累積設計經驗值成長起來的。

Bottom-up 的策略很簡單直覺,通常是先把需要的類別物件按照專案要求先個別設計出來,等專案活動告一段落後再回頭重構。重構過程中不斷整理提取抽象概念逐步改善,等累積更多開發設計經驗後,再嘗試進一步提取成介面為主的架構設計。Bottom-up 過程需要多次的迭代過程看似緩慢,但對於剛入門或經驗不足架構設計者我反而覺得這是很好的訓練,在每一次重構過程中培養自己抽象化思考的能力,這也是大部分自學架構設計者的自然成長模式。

相較之下經驗豐富的架構設計者會更傾向於採用 top-down 的方式,不急著著手設計物件細節,而是會先做各種調查活動想辦法掌握全局思維,因為他們知道使用介面為主的設計會更優秀。當我們想要設計通訊協議的模組給不同的產品使用時,有經驗設計者會先觀察此模組要提供給哪些產品用,如果一個產品支持多種協議,那麼不同的協議間又有甚麼行為的共通性,透過問各種問題逐步分析思考應該定義哪些的介面來規劃通訊模組與產品整合所需介面。

例如在經過觀察了多種產品的各種通訊協議後發現所有通訊最基礎的能力就是讀跟寫,就可以定義一個 IProtocol 介面來要求具備通訊介面物件都要實作讀跟寫兩種能力;對常見的 Modbus 通訊模組來說就是可以從 IProtocol 衍生的 IModbus 介面來規範 read write register, coil 等能力。

介面設計可以讓物件的控制行為保持一致性與具備可隨意替換的彈性。

結論

只用案例來看架構設計難免以管窺天,卻是新手軟體設計者一窺堂奧的開始。對於想從事軟體架構設計工作的人來說,先有耐心地完備該有的知識理論絕對必要的,現在的資訊發達,想學習軟體架構設計的知識跟工具等資源幾乎都能免費取得,不用擔心知識匱乏,反而是有實踐理論的實戰案例才是難得的。如果你是想入門或正修行學習軟體架構設計的人,我會建議一定要睜大你的眼睛去尋找你團隊裡最有實戰經驗的高手們學習,請他們喝杯咖啡、分享你的設計,多聽聽聽他們的故事你會看見不同的世界。

avatar-img
14會員
61內容數
WarrenLo's 軟體設計武功祕笈
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Warren Lo的沙龍 的其他內容
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
經過這麼多年的觀察與實踐,一個成熟的軟體工程師還需要第四個要素,它是讓決定你通往熟手的重要關鍵沒有之一。
整合測試的時候突然遇到一個突然無法登入產品網站的問題,把程式模組單獨拉出來測試又正常,觀察測試報告後發現出現發生登入異常的時間點並不固定,而且只要發生就會連續發生一段時間,程式被中斷掉。後來確認問題在...
當這產品的這個 API 被呼叫,再從回傳內容的某個欄位欄位來判斷,只要“這個欄位”顯示 false 就代表不支援」,雖然這樣的設計也能滿足功能需求…
關於程式語言的學習,只要掌握住幾個基本特性要熟悉幾種程式語言也不困難,這三個基本特性就是…
IDE 升級後出現了一樣的錯誤,手上程式碼沒有 pylint black-format 檢查上不了 gitlab,我又點開了那個很小很小的 x 符號,裡面 logs 提示的解決方式是升級..
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
經過這麼多年的觀察與實踐,一個成熟的軟體工程師還需要第四個要素,它是讓決定你通往熟手的重要關鍵沒有之一。
整合測試的時候突然遇到一個突然無法登入產品網站的問題,把程式模組單獨拉出來測試又正常,觀察測試報告後發現出現發生登入異常的時間點並不固定,而且只要發生就會連續發生一段時間,程式被中斷掉。後來確認問題在...
當這產品的這個 API 被呼叫,再從回傳內容的某個欄位欄位來判斷,只要“這個欄位”顯示 false 就代表不支援」,雖然這樣的設計也能滿足功能需求…
關於程式語言的學習,只要掌握住幾個基本特性要熟悉幾種程式語言也不困難,這三個基本特性就是…
IDE 升級後出現了一樣的錯誤,手上程式碼沒有 pylint black-format 檢查上不了 gitlab,我又點開了那個很小很小的 x 符號,裡面 logs 提示的解決方式是升級..
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
這篇文章介紹了網站的整體架構以及開發時所使用的工具和套件,包括 Next.js、Tailwind CSS 和 socket.io 等。文章回顧了程式碼的重構與優化,幫助開發者提高工作效率,適合希望深入瞭解前端開發和網站架構的讀者。
先學習 HTML, CSS, JavaScript 基礎觀念, 再透過實作專案,慢慢熟悉不同的語法使用方式。
Thumbnail
這篇內容,將會講解什麼是表達式(Expression),什麼是陳述式(Statement)。有了這些概念,各位會更容易理解,要如何設計程式碼。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
Thumbnail
你好,在下最近在學習開發web,學了html css js,也得出一些心得,由於網路上已有許多教學,所以我會著重在如何開發出to do List,以及解釋我寫的程式碼。相關的教學我會直接貼網址。如果我有什麼地方出錯,或者是可以寫得更好,歡迎在下方留言,討論。 首先先介紹我的開發環境: 我用了vs
Thumbnail
介紹C++ 語法 資料型態,架構說明 程式語言為人類與電腦溝通的工具 程式設計流程: 定義問題 -> 問題分析 -> 撰寫演算法 ->程式撰寫 -> 程式執行及維護
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
這篇文章介紹了網站的整體架構以及開發時所使用的工具和套件,包括 Next.js、Tailwind CSS 和 socket.io 等。文章回顧了程式碼的重構與優化,幫助開發者提高工作效率,適合希望深入瞭解前端開發和網站架構的讀者。
先學習 HTML, CSS, JavaScript 基礎觀念, 再透過實作專案,慢慢熟悉不同的語法使用方式。
Thumbnail
這篇內容,將會講解什麼是表達式(Expression),什麼是陳述式(Statement)。有了這些概念,各位會更容易理解,要如何設計程式碼。
Thumbnail
這篇內容,將會講解什麼是函式,以及與函式相關的知識。包括函式的簡介、Runtime Function、自訂函式、Script Function 腳本函式、Method 方法。
Thumbnail
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
Thumbnail
你好,在下最近在學習開發web,學了html css js,也得出一些心得,由於網路上已有許多教學,所以我會著重在如何開發出to do List,以及解釋我寫的程式碼。相關的教學我會直接貼網址。如果我有什麼地方出錯,或者是可以寫得更好,歡迎在下方留言,討論。 首先先介紹我的開發環境: 我用了vs
Thumbnail
介紹C++ 語法 資料型態,架構說明 程式語言為人類與電腦溝通的工具 程式設計流程: 定義問題 -> 問題分析 -> 撰寫演算法 ->程式撰寫 -> 程式執行及維護