軟體架構設計 - 希望開始就知道的 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
Warren Lo的沙龍
29會員
80內容數
WarrenLo's 軟體設計武功祕笈
Warren Lo的沙龍的其他內容
2024/07/02
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
Thumbnail
2024/07/02
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
Thumbnail
2024/04/08
經過這麼多年的觀察與實踐,一個成熟的軟體工程師還需要第四個要素,它是讓決定你通往熟手的重要關鍵沒有之一。
Thumbnail
2024/04/08
經過這麼多年的觀察與實踐,一個成熟的軟體工程師還需要第四個要素,它是讓決定你通往熟手的重要關鍵沒有之一。
Thumbnail
2024/03/08
整合測試的時候突然遇到一個突然無法登入產品網站的問題,把程式模組單獨拉出來測試又正常,觀察測試報告後發現出現發生登入異常的時間點並不固定,而且只要發生就會連續發生一段時間,程式被中斷掉。後來確認問題在...
Thumbnail
2024/03/08
整合測試的時候突然遇到一個突然無法登入產品網站的問題,把程式模組單獨拉出來測試又正常,觀察測試報告後發現出現發生登入異常的時間點並不固定,而且只要發生就會連續發生一段時間,程式被中斷掉。後來確認問題在...
Thumbnail
看更多
你可能也想看
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
在 vocus 與你一起探索內容、發掘靈感的路上,我們又將啟動新的冒險——vocus App 正式推出! 現在起,你可以在 iOS App Store 下載全新上架的 vocus App。 無論是在通勤路上、日常空檔,或一天結束後的放鬆時刻,都能自在沈浸在內容宇宙中。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
Thumbnail
如果你也是從事軟體相關工作的人,一定會遭遇突然需要你去學習一套你不熟悉的程式語言狀況吧,此時你會怎麼做呢? 是趕快去買書來看嗎? 還是趕快找一門程式課來上? 又或者乾脆去找會的同事來教學?
Thumbnail
本書大多數的內容都以 OO 的概念出發,詳列了許多設計的臭味道,也有大量的例子。個人雖然不會這樣寫程式,但仍是覺得受益良多,至少在 code review 時能更清楚知道該怎麼描述問題。不過,即便不是用 OO 的概念,有些章節還是可以帶來一些想法,用 OO 概念寫程式的人更不該錯過這本好書。
Thumbnail
本書大多數的內容都以 OO 的概念出發,詳列了許多設計的臭味道,也有大量的例子。個人雖然不會這樣寫程式,但仍是覺得受益良多,至少在 code review 時能更清楚知道該怎麼描述問題。不過,即便不是用 OO 的概念,有些章節還是可以帶來一些想法,用 OO 概念寫程式的人更不該錯過這本好書。
Thumbnail
實際就業後,會發現收集與分析需求,通常都不是工程師在做,會有另一群人,以非工程的角度收集及分析需求,然後在開發過程中蹦出不同的火花,於是很好奇另一群人的想法是什麼?我不敢說這本書能完全代表另一群人的想法,但確實能夠得到很多有用的思維。推薦給所有的軟體工程師。
Thumbnail
實際就業後,會發現收集與分析需求,通常都不是工程師在做,會有另一群人,以非工程的角度收集及分析需求,然後在開發過程中蹦出不同的火花,於是很好奇另一群人的想法是什麼?我不敢說這本書能完全代表另一群人的想法,但確實能夠得到很多有用的思維。推薦給所有的軟體工程師。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
軟體系統的發展歷程大多相似,首重解決基本需求、提供操作介面,進而提升安全性、擴充功能、優化操作。
Thumbnail
經過這麼多年的觀察與實踐,一個成熟的軟體工程師還需要第四個要素,它是讓決定你通往熟手的重要關鍵沒有之一。
Thumbnail
經過這麼多年的觀察與實踐,一個成熟的軟體工程師還需要第四個要素,它是讓決定你通往熟手的重要關鍵沒有之一。
Thumbnail
列出一套完整的程式 程式設計有許多種方法,不過通常會先列出清單的再逐一執行,這樣會加快程式設計的速度。設計通常會採取順推的辦法。所以順推的程式設計方式就是經歷觀念溝通、系統分析、資料統合、權限管理、頻率與時間、後台管理、畫面設計等等階段後,將框架設計完了以後,先列出一套完整的程式,將所有使用者都確
Thumbnail
列出一套完整的程式 程式設計有許多種方法,不過通常會先列出清單的再逐一執行,這樣會加快程式設計的速度。設計通常會採取順推的辦法。所以順推的程式設計方式就是經歷觀念溝通、系統分析、資料統合、權限管理、頻率與時間、後台管理、畫面設計等等階段後,將框架設計完了以後,先列出一套完整的程式,將所有使用者都確
Thumbnail
程式設計中不可或缺的一部分 介面是使用者與程式互動的媒介,因此介面的設計會影響使用者的體驗和感受。一個清晰明白、易懂的介面,可以讓使用者輕鬆地使用程式,並獲得良好的使用體驗。 需要與程式設計師密切溝通 設計師需要了解程式的功能和需求,並根據使用者的習慣和需求進行設計。設計師和程式設計師之間的溝
Thumbnail
程式設計中不可或缺的一部分 介面是使用者與程式互動的媒介,因此介面的設計會影響使用者的體驗和感受。一個清晰明白、易懂的介面,可以讓使用者輕鬆地使用程式,並獲得良好的使用體驗。 需要與程式設計師密切溝通 設計師需要了解程式的功能和需求,並根據使用者的習慣和需求進行設計。設計師和程式設計師之間的溝
Thumbnail
資料的統合 在程式設計中,其他人通常關心是否注意到執行的細節。作為程式設計師,主要應該關心的是程式的表現,但往往忽略了很多細節,這些細節可以決定程式的好壞。程式的好壞很大程度上取決於資料的統合,也就是資料是否被正規化。 不同類型的資料在系統中呈現一致 正規化可能對一些人來說聽起來很抽象,有些人
Thumbnail
資料的統合 在程式設計中,其他人通常關心是否注意到執行的細節。作為程式設計師,主要應該關心的是程式的表現,但往往忽略了很多細節,這些細節可以決定程式的好壞。程式的好壞很大程度上取決於資料的統合,也就是資料是否被正規化。 不同類型的資料在系統中呈現一致 正規化可能對一些人來說聽起來很抽象,有些人
Thumbnail
系統的分析與規劃 在談到程式設計時,首要的是進行系統的分析與規劃。程式設計的起點通常是系統分析與規劃,這涉及到如何分析和設計系統的大原則和方向。為了達到預期效果,重要的是擁有對產業的清晰邏輯認識和深入了解。 進行深入了解 若要進行系統分析,必須對企業的設計和程式設計的對象進行深入了解,以充分理
Thumbnail
系統的分析與規劃 在談到程式設計時,首要的是進行系統的分析與規劃。程式設計的起點通常是系統分析與規劃,這涉及到如何分析和設計系統的大原則和方向。為了達到預期效果,重要的是擁有對產業的清晰邏輯認識和深入了解。 進行深入了解 若要進行系統分析,必須對企業的設計和程式設計的對象進行深入了解,以充分理
Thumbnail
關於程式語言的學習,只要掌握住幾個基本特性要熟悉幾種程式語言也不困難,這三個基本特性就是…
Thumbnail
關於程式語言的學習,只要掌握住幾個基本特性要熟悉幾種程式語言也不困難,這三個基本特性就是…
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News