前言
當我們在寫Laravel, Django 等MVC以及MTV的架構時,部分的人可能都會習慣把所有的邏輯,包含Use Case, 資料驗證 等等全部寫在同一包裡面
一開始或許開發的時候比較方便,你自己在自幹的時候想怎麼寫都沒差
但換個角度,當今天這個專案是10個人一起做的呢?甚至是過了10個月你再回來看,我們要花多少時間來看這些架構
再來,當我們今天要新增一個功能或是更改 Use Case 時,我們又要花多少時間來做閱讀?
其實在看過Clean Code, Clean Coder 和 Clean Architecture之後其實就會知道,傳統的MVC框架真的滿髒亂而且不容易維護的
一般MVC架構
看個範例,以註冊會員為例子好了,假設我們帶入member_name
, member_email
, member_password
1 | class MemberController extends Controller |
光是簡單的驗證和建立資料庫就已經有點長度了,如果我今天還要再加入更多功能進來,例如要付費才能建立會員,所以要使用金流,或是什麼註冊會員送好禮,所以又要使用物流等等的功能。
一開始可能還好,但不要忘了,隨著軟體生命週期的增長,維護的成本是會越來越高的。更不用說多數的人希望有新的功能加進自己的軟體裡面。
到時候一個新進來的人要花上多少時間來熟悉這些Code,且維護又要花上多少時間?
這個架構甚至連單元測試都測不了,出問題要從哪邊找起搞不好都是一個問題。
更不用說還有一堆公司會為了追求快速開發而把前後端的Code寫在同一包檔案裡面,到時候要加一個新功能都有很有可能要花很大的時間去修改和Study
甚至這不是你寫的Code,還要花多少時間來讀懂作者的邏輯?
軟體的維護
隨著時間時間增長,可能會有新增加的功能,或是配合市場要調整的部分,此時架構或是Code如果不夠乾淨,那維護的時間將是隨著指數增長
我們引用Clean Code這本書中的資料
80年代某不願具名軟體公司的內部統計資料:
工程人員的增長 | 同一時期的生產力 | 每行程式碼的平均成本 |
---|---|---|
我們可以發現幾件事情
- 工程人員持續且倍數的增長
- 每行程式碼的平均成本也是持續且倍數的增長
- 但生產力自從第三年之後就沒有增長多少,後續甚至是幾乎持平的
「當對程式碼的整潔程度或設計的結構沒有多少想法時,那你就會跟這條曲線一樣走到最終悲慘的結局」
取自: Clean Architecture (p.6)
再舉一個極端的例子
「我知道有一間公司在 80 年代後期開發了一個殺手級應用,但後來發行的週期開始拖長,程式裡的錯誤也無法在下次發行之前修復,程式載入的時間與崩潰機率也愈來愈長和高。不久,這家公司就倒閉了。我問他當時發生了什麼…」
「急於將產品上市,導致他們的程式碼變得一團糟,當他們加入愈來愈多的產品特點時,程式碼就變得愈來愈糟糕,一直到他們再也無法管理這團混亂。劣質的程式碼導致了這家公司的倒閉」
取自: Clean Code (p.3)
如果你問我說,「我的主管要求我一定要在三天內產出這個專案,那我該怎麼辦?」
我建議你先去看一下Clean Coder,上面有很多身為一個專業人士該做的事情和應對方式。
如果主管還是不合理的要求你,那我只好搬出那句話,程式跟人只要有一個能跑就好。
隨時準備好可以跳槽的準備。
實作
傳統 MVC 和 MTV
我們先來看看傳統 MVC 或是 MTV 架構的樣子
其實滿簡單的,就是Model負責與資料庫有關的操作,Controller和其他兩層溝通,View負責畫面顯示
以傳統的MVC來說,甚至會有前後端不分離也就是伺服器端渲染(Server-Side Rendering,簡稱 SSR)的狀況
但這個模式到現在,隨著前端技術的進步,以及開始重視團隊協作的現在,過去的 SSR 其實顯得有非常多的問題,像是開發效率、維護性等等。
現代的MVC可能連View那一層都不會有了(後端的部分),因為View的部分已經給了前端
調整過後的架構
這邊我從bxcodec的go-clean-arch得到很大的靈感
以上方的 註冊會員 為例子,我們需要驗證、儲存資料、金流和物流以及回傳資料
我們可以得到這張圖
搭配一下時序圖來了解狀況
我們可以得知這個順序是
- Request 進入 Controller
- Controller 向 Validator 驗證使用者的資料
- Controller 向 UseCase 傳遞資料(處理業務邏輯,像是金流物流)
- Controller 向 Repository 請求建立資料
- Repository 向 Model 請求建立資料
- Model 向 DB 建立資料
- Controller 向 Formatter 請求回傳資料
- Controller 給出 Response
也就是說,我們這邊盡量讓Controller只做資料傳遞的動作,不處理其他的業務邏輯
Code大概會長這樣(這邊先不講DI的部分,有時間這個移到鐵人賽再說XD)
1 | class MemberController extends Controller |
這麼做最大的好處有幾個
- 我可以撰寫單元測試,來驗證每一個function的邏輯是否正確
- 以後要加什麼功能,我可以很清楚知道我要在哪裡做
- 他不再是互相依賴的關係,而是有需要才會使用到
結語
如果我真的要把裡面用到的概念全部講完,大概要好幾篇文章
這個留到鐵人賽再來說吧,如果我有參賽,沒意外應該是會講Laravel的開發流程,且不走傳統的方式,但可惜我對前端不熟,我不太會寫 HTML,可能我也不太會花時間去講太多 Blade 的東西
畢竟我也滿討厭把前端跟後端的邏輯寫在一起的。
參考資料
Day 01: 【序】– 架構與設計、代碼、工程師
打造 Laravel 優美架構
DAY6 - 你的 Backend 可以更有彈性一點 - Clean Architecture 概念篇
go-clean-arch
Clean Code
Clean Coder
Clean Architecture
如果有錯誤的部份,歡迎指正,謝謝。
如果你喜歡這篇文章,請幫我拍手
只需要註冊會員就可以囉,完全不用花費任何一毛錢就可以用來鼓裡創作者囉