[創意菜色] 每個軟體設計師的心中都有一張設計圖

軟體設計師隨著開發的經驗越來越多,累積的經驗會轉化成一個 Pattern,這個 Pattern 也會經由解決問題、學習新技術…等經驗的餵食而慢慢地進化,當累積到一定的豐富程度之後,我們就可以用一張圖來把它給表達出來,大概就像這樣。

這張圖是我參考過去的經驗及幾位前輩們的文章,在試著 run 過幾個專案之後綜合出來的結果,它是以 3-Layer 架構為基礎,加入一部分 AOP 的概念所設計出來的。

當然它不是最完美的,因為軟體的設計會隨著系統的需求而不一樣,但是相對上來講一個軟體專案基本應該要考慮到的面向,這張設計圖都有考慮到,最近以這樣子的設計來做 pre-architecture 的幾個專案,開發的過程都很順利,包含有需要 issue tracing 的時候也都很容易。

我個人認為我們本職上是在做設計的工作,每位設計師的想法跟經驗,會左右設計出來的成果,好的設計會讓開發的過程猶如置身於天堂,不好的設計則會讓開發的過程像在鬼打牆,設計好與壞的差異是很大的。

Layer vs. Tier

剛剛有提到上面的那張設計圖是以 3-Layer 架構為基礎,在研究分層式架構的時候我們很常聽到 2-Layer、3-Layer、N-Layer、3-Tier、N-Tier,翻譯都叫「2 層、3 層或 N 層」,一樣叫做「層」其實意義是不太一樣的,差別只在於有沒有做實體上的切割,關於 Layer 及 Tier 的差異,在網路上都可以找到很多相關的資訊,如果懶得找也可以直接看這篇文章 N-Tier 和 N-Layer

而上面那張設計圖中每個 Layer 代表的意義及各自掌管的職責是什麼?下面我就稍微說明一下。

Physical Layer

主要的職責在處理與資料庫、磁碟機、檔案伺服器…等的實體資料的交換,簡單來講只要有 touch 到檔案的存取、網路的連接、周邊硬體設備的存取,我就會把程式封裝在這一層。

Logic Layer

這一層主要是放商業邏輯的地方,在設計這一層的時候需要做適度的抽象化,並且指揮 Physical Layer 提供商業邏輯所需要的資料,因此 Physical Layer 也不是自己愛怎麼玩就怎麼玩,必須要依照 Logic Layer 的需要來實作資料存取的 Library。

Service Layer

這邊是用來 Host Logic Library 的地方,這一層就比較單純了,就看我們要選擇哪一種方式跟外部元件做溝通,我們可以選擇 Web Api、Web Service、WCF、Socket…等等,想用什麼就用什麼,等於把 Logic Layer 再用一層協定封裝起來,讓 Logic Layer 可以服務不同協定的外部元件。

Presentation Layer

顧名思義,這一層就是單純用來展示資料用的,說單純,其實這一層一點也不單純,展示資料的方式有千百種,光 Desktop、Web、App 這三種就有得玩了,而且還分不同作業系統、不同瀏覽器、不同的 Framework,因此這一層我把它歸類為「外部元件」,切得越乾淨越好。

我忘了是從哪裡聽來的,有一句話是這樣講的「前端世界如月亮,初一十五不一樣。」,這裡講的前端原本指的是 Web 的 Front-End,不過我們也可以把它看得廣泛一點,只要是使用者操作端的部分,就可以看作是前端,前端可以選擇的技術非常多,請大家謹慎小心地選擇,因為有可能我們選的技術隔沒多久就 face out 了。

Infrastructure Layer

在這一層我們會將跨 Layer 的功能抽出來,在 Layers 之間找幾個合適的攔截點,把抽出來的功能插入到這個攔截點裡面,做統一的處理。

舉例來說,像寫 Log,如果每個 Layer 都要寫 Log 就很辛苦,而且很容易漏掉,但是寫 Log 又很重要,所以我們把寫 Log 這件事情抽出來,做一個 LogHandler 在需要寫 Log 的 Layer 找一個攔截點插進去,實際開發的時候就不用管 Log 有沒有寫,有關 Log 的一切交給 LogHandler 來處理,另外還有像是 Exception 的攔截及處理、資訊安全過濾、客戶端驗證…等,都會放在這一層來做。

Special Components

有幾個擺在 Layer 裡面比較特殊的 Component,另外獨立出來說明。

Data Validation

在資料正確性的驗證上,前後端都需要做,過去我們都有看過一些例子,前端做了資料檢查但後端沒做,形成了一個安全上的漏洞,讓有心人士透過這個漏洞去竊取資料、攻擊系統。

在設計上我把 Data Validation 放在 Presentation Layer 及 Logic Layer,資料展示層要做資料正確性的驗證就 follow 各前端的技術,該怎麼做就怎麼做,如果後端是用 OO 來開發的,可以參考我這篇文章[料理佳餚] 使用 Decorator Pattern 分離參數檢查與資料處理,把驗證資料的部分跟資料處理的部分分開,做關注點分離。

Unit Testing

在 Physical Layer、Logic Layer、Service Layer 都需要做 Unit Test,原因很簡單,我連我自己的 Code 都信不過了,怎麼還會信任別人的 Code?寫 Unit Test 來架設安全防護網,是讓自己多一份安心。

E2E Testing(End to End Testing)

在 Presentation Layer 掛一個端到端的整合測試,來確保每個 Layer 在兜起來之後是會 Work 的,而且執行的結果是我們要的,技術的部分可以參考 Cucumber

結論

設計這件事完全就是見人見智,絕對不會有一個完美的設計,但也是因為這樣有非常多很好的 idea 才有發揮的空間,在要設計這條路上持續的進步,學習跟實作是不二法門,因為學得越多才知道有什麼事可以做,做得越多才知道有什麼事不能做,Kevin 哥有寫過一篇文章你要 Coding 多久呢?,如果我們已經失去熱情的話,可以讀一讀。

參考資料

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學