🌱不乾淨軟體架構講座
Unclean Architecture
我想寫程式的人大概都知道軟體界有本很出名的書?
這本書名叫做 Clean Architecture,是 Robert C. Martin(Uncle Bob)所著。
他更出名的是 Clean Code。
不過我相信 ( 同時我也自己搜尋過 ) 教這些知識的部落格文章或影片太多了。
所以我想,不需要我再錦上添花了。
三島由紀夫的書「不道德教育講座」,從我第一次讀過到現在還不停的再版,足見其熱賣程度!
不如我也來寫一篇「不乾淨架構講座」好了!
1. 階層式架構的問題點 ?
沒有問題的!
階層式架構的英文是 Layered Architecture。
傳統的三層式架構是:網頁層、領域層、資料存取層。
網頁就是使用者介面,領域層負責商業邏輯,資料存取層負責與資料庫溝通。
他的目的是讓層與層之間有清晰的分界線,讓每一個層只負責自己的工作。
這樣實在是太乾淨了,會造成維護上的辛苦,明明可以快速取得資料,卻要透過層與層之間的交換來完成。
你的 Controller 只是要去資料庫拿一筆資料顯示在畫面上, 為什麼要經過 Service 層? 還要經過 Repository 層?這不是脫褲子放屁嗎?
我們直接在 Controller 裡面呼叫 Entity Framework 的 DbContext, 一行程式碼 _db.Users.ToList() 就解決了! 多麼直覺!
1. 資料庫驅動設計
傳統的階層式架構,最底層通常都是資料庫。
通常領域邏輯或是商業邏輯會希望與其他任何物件都解偶。
商業邏輯要先考慮正確,才去加入資料庫存取邏輯。
不過我們的資料庫驅動,顧名思義,把重點放在資料庫存取上,商業邏輯反而是次要的。
為什麼呢?
你想想看哦,老是注重商業邏輯,卻不去注意資料是否正確,是不是有問題?
2. 在階層中偷吃步
可稱之為「放鬆的階層系統」。
這時候「偷吃步」的好處就來了!
我們直接在 Controller 裡面呼叫 Entity Framework 的 DbContext,一行程式碼 _db.Users.ToList() 就解決了!多麼直觀,多麼高效!
雖然教科書上會說這導致了「邏輯洩漏」跟「UI 與資料庫緊密耦合」,但誰在乎呢? 反正現在能動就好。以後如果資料庫欄位改了,我們就享受「全局搜尋與取代」的快感, 這才是工程師加班的浪漫啊!
如果每一層都嚴格把關,那要怎麼展現我們「快速交付」的神奇速度?
3. 難以執行的測試
你是否覺得寫單元測試 (Unit Test) 很浪費時間?
恭喜你,傳統的階層式架構完全支持你的想法!
因為我們的架構是「資料庫驅動」的,所有的商業邏輯都死死地依賴著資料庫。
如果你想測試「計算訂單折扣」這個邏輯,你必須先啟動一個真的 SQL Server,
然後塞入假資料,跑完測試後還要記得把資料刪掉。
這簡直是太棒了!
因為測試這麼難寫(甚至可以說是「不可測試」),
我們就有完美的藉口跟主管說: 「因為架構限制,寫單元測試的成本太高,CP 值不符,我們直接人工手測就好!」
這不但省下了寫 Mock 物件的時間,還能讓測試人員 (QA) 有事做,創造就業機會。
反觀 Clean Architecture 強調的「不依賴 UI、不依賴 DB 就能測試」,
簡直是在剝奪我們偷懶的權利。
4. 使用案例在哪裡?
當你打開一個專案,看到資料夾結構是 Controllers、Views、Models、Helpers 時,你會有什麼感覺?
你會看到一堆「技術名詞」,但完全看不出這套軟體在「做什麼」。這就是所謂的「尖叫式架構 (Screaming Architecture)」的相反——「沉默式架構」。
這對保持神祕感非常有幫助!
如果你的專案結構清楚地寫著 CreateOrder、CancelSubscription,
那新來的同事豈不是一天就能看懂系統在幹嘛了?這樣你的「資深」地位要往哪擺?
最好的架構就是讓「使用案例 (Use Cases)」隱藏在幾千行的 Controller 或 Service 裡面。
想知道系統怎麼運作?慢慢看程式碼吧!
這就像是在玩尋寶遊戲,把商業邏輯分散在 UI 層、SQL Stored Procedures 和各種 Helper 裡面,能有效防止核心技術外流。
5. 平行分工困難
在這種層層堆疊的架構下,開發一個新功能通常需要「貫穿」所有層級。你需要改 UI,改 Controller,改 Service,改 DAO,改 Database。
這代表什麼呢?
如果有三個人同時開發三個功能,大家都會擠在同一個 UserService.cs 或 OrderController.cs 裡面修改。
這是促進團隊溝通的絕佳機會。
Git Merge 的時候一定會發生衝突,這時候你就不得不轉過頭去跟同事說話:「欸,你為什麼要把我的 Code 蓋掉?」、「為什麼你改了這個 Public Method 沒跟我說?」
這種架構強迫大家「密切接觸」,絕對比什麼 Team Building 活動都有效。反觀那些強調「垂直切分」或「功能獨立」的架構,大家各做各的,多冷漠啊!
6. 如何讓軟體邁向可維護性的目標?
如果你是一個生性保守、不喜歡冒險、討厭加班修 Bug、而且希望下班後手機不要響的工程師,那你可能覺得上面講的那些「優點」聽起來像是地獄。
這真的是你想要的嗎?