Controller Model Repository 搭配Dto的快速開發架構

前言:

在開發系統的這段期間,我們寫了N支API,然而每個操作的動作都離不開Create, Update, Read, Delete 這些動作

為了加速以及更懶惰(誤),我們團隊討論出一個夠嚴謹也可以更快開發的架構

結構說明:

Controller : 作爲Api的入口也作為整個資料流程的控管,其他的事情都讓Service、Repository來處理

Model : 定義資料表內容、定義資料驗證規則、定義表與表之間的relation

Repository : 作為資料操作的動作定義,直接控制Model做資料存取

Dto們 : 作為資料傳遞的介面,嚴格定義傳入Controller或者傳入Service的資料結構,這樣做可以一定程度的避免錯誤

一切的開端:

當每個API都需要Create, Update, Read, Delete這些方法的時候,我們第一個想到的是

那就寫個抽象類別來繼承好了,這樣就可以把需要的方法都先定義好,大約可以解決6成以上重複性的原始碼

但是面臨的就是下一個問題,舉例來說每一次的Create如果沒有特別需要處理資料那麼都是從Controller中呼叫Reposiroty的Create function就結束了

這樣的話,是不是可以再寫的更簡單一些?

加速原則 :

相同的命名原則,讓開發可以更快

舉個簡單的例子先,如果我們要對Customer做Create,也就是新增一筆客戶資料

那麼資料流應該會長這樣子

因此我們寫了一個BaseController,在其中定義好repository_name, model_name 以及Dto

而且預設就是跟Controller相同的名字,整理一下上述案例,在CustomerController中,我們只要繼承了BaseController就會擁有以下

為了要在Controller一初始化就把以上物件準備好,我們會需要用上之前提過的callAction

Laravel Controller中的callAction

我們在BaseController中先定義幾件事情

接著定義幾個init_開頭的function,用來初始化以上的變數內容

簡單說明一下這幾個function,分別是一句Controller的名稱初始化name , __main_model__ , repo , __dto__ 等等這幾個變數

接著在我們覆寫掉callAction這個function,讓以上幾個function可以正確的執行過一次

以上這幾行,就是簡單的把init_開頭的function找到,然後透過動態呼叫全部執行一次

PHP 動態呼叫函數(variable functions)與@see

那Repository做什麼用?

Repository作為直接操作Model進行資料存取的元件,我們也是做了一層抽象處理,這樣這樣一來基本的Create, Update, Delete, Read都可以描述完成

每個各別的Repository繼承後只要描述關於relation的部分就可以了,大致像這樣子

舉Create的例子來說,透過定義好的Dto傳入需要寫入的正確資料,然後讓relation_processor處理相關聯表單所需要寫入的資料

這麼一來,我們回到CustomerController的Create function中,就只剩下以下內容

邏輯上是把傳入值塞入CreateCustomerDto中,如果這時候傳入的資料不是預期的欄位就會直接報錯

接著將new出來的CreateCustomerDto交給CustomerRepository的Create function處理

是不是變得有夠簡單好寫呢?