close

初學者學習 Framework 通常是乖乖的將程式填入 MVC 架構內,導致 controller 與 model 異常的肥大,當專案開始變大後就會發現,維護是一件很痛苦的事情,而經高人提點後得知此設計架構,也希望讓更多人知道什麼是好的設計架構,除了容易維護擴充減少程式碼重複等特點。

我們常常把「資料樣式的轉換」、「資料撈取的邏輯」、「資料格式的驗證」、「資料處理的順序及商業邏輯」都是放在 Model 或Controller 去處理,小專案的時候並不會有什麼感覺,但是一但專案越來越大的時候,這些不同類別的資料全部只由前兩者去處理會讓人很頭痛,程式碼難以維護,那我們該怎麼做呢?別將我們的思維侷限在MVC內! 如下圖:

1.Entity: 僅當成 Eloquent class。
2.Repository : 輔助 model,處理資料庫邏輯,然後注入到 service。
3.Service : 輔助 controller,處理商業邏輯,然後注入到 controller。
4.Controller : 接收 HTTP request,調用其他 service。
5.Presenter : 處理顯示邏輯,然後注入到 view。
6.View : 使用 blade 將資料 binding 到 HTML。

其中藍色為原本的 MVC,你可能會有疑問,那 Model 跑哪去了? 其實被拆成三個部分也是本文要介紹的的重點 : Entity、Repository 與 Service,當然也可以不取 Entity 取原來的 Model 也行,重點在於內容物 ! 但因為教學上怕混淆所以這邊以不同名字來介紹, 而 Presenter 能使view更專注於顯示。

首先! 你要建立目錄

別害怕在 Laravel 預設目錄以外建立的其他目錄,根據 SOLID 的單一職責原則,class 功能越多,責任也越多,因此越違反單一職責原則,所以你應該將你的程式分割成更小的部分,每個部分都有它專屬的功能,而不是一個 class 功能包山包海,也就是所謂的萬能類別,所以整個專案不應該只有 MVC 三個部分,放手根據你的需求建立適當的目錄,並將適當的 class 放到該目錄下。

你可能會有疑問,不是說把 Model 拆開了嗎?為什麼還會有 Model 資料夾? 那是因為我要在既有的專案上新增功能,而新功能才是套用在此架構,所以舊有的當然是原封不動囉!

其次,要了解每個元素的功能

1. 實體(Entity)

實體就是我們用來 Eloquent Model 的相關設定,像是資料表名稱($table)、主鍵名稱($primaryKey) 等等,裡面除了 Eloquent 相關設定以外,不要擺任何的商業邏輯或資料撈取方法,實體與資料表的關係是「1 對 1」的關係,有幾個資料表就有幾個實體

程式碼範例:

2.資源庫(Repository)

資源庫是專門用來撈取資料表資料的各個邏輯,不會有其他種類的程式碼,我們將撈取資料的邏輯抽離出來後,下次如果有需要撈取同樣的資料時,就可以重複的去使用它,而且不會有重複的程式碼出現在專案的各個地方,讓管理程式碼變得簡單!資源庫與實體的關係是「1 對 1」的關係,有幾個實體就有幾個資源庫

程式碼範例:

3.服務(Service)

服務代表我們程式要處理資料的商業邏輯,將各個功能邏輯獨立成一個服務,像是使用者「註冊身份驗證」是一個服務,而使用者「個人隱私設定」也是一個服務。服務與資源庫的關係是「多 對 1」的關係。當商業邏輯被抽至 Service 後會發現 Controller 不再複雜,清楚的知道接收HTTP Request,調用了哪些 Service,回傳了哪些的值,顯示哪個 view 。

程式碼範例:

5.Presenter

在中大型專案,會有2個主要問題 :

1. blade 與 HTML 夾雜,不太適合寫太複雜的程式,只適合做一些簡單的 binding,否則很容易流於傳統 PHP 的義大利麵程式。

2. 無法對顯示邏輯做 “重構" 與 “物件導向"。

若使用 presenter 輔助 blade,再搭配 @inject() 注入到 view,view 就會非常乾淨,可專心處理將資料 binding 到 HTML 的職責。將來只有 layout 改變才會動到 blade,若是顯示邏輯改變都只會修改 presenter。

Presenter 程式碼範例:

Blade 程式碼範例:

本文談到的架構只是邁向 Artisan 的開始,資料夾數量、名字與位置都沒有一定的規範,你可以依照實際需求增加或減少目錄與 class,當你發現你的 MVC 違反 SOLID 原則時,就大膽的將 class 從 MVC 拆開重構,讓我們一起成為 Artisan 吧! 

arrow
arrow

    Mayuge 發表在 痞客邦 留言(0) 人氣()