開始重構程式碼,前幾天有提到 Controller 越來越肥大,程式碼越來越多,根本就已經超出人類想要看的範圍了!就像一篇好的文章,字數太多也是一件壞事,要有足夠的耐性才會想看。
這系列鐵人賽目前的 Controller 程式碼還不算太多,還算簡單拆開來相對容易,講解也比較清楚。
預計這樣拆開目前的 Controller
- 驗證會員等級權限 - 已由
Policy
負責 - 驗證使用者輸入資料 - 需再加入
Request
- 商業邏輯或外部資源 - 需再加入
Service
- 轉換資料結構 - 已由
Resource
負責
為了達到接近單一職責原則預計把Controller 拆成這個樣子! 降低程式之間的耦合性!對目前的程式來說比較好!檔案不會拆太多太細,又可以讓程式可讀性增加, Policy
、Resource
已經完成了!現在來拆解 Service
、驗證資料
先來說說重構,重構程式碼並不是看心情去寫的,盡量減少打掉重來比較快的想法。現有的程式碼,經歷過不斷的除錯,才有現在穩定功能,想必有很多細節都有注意到。重構是希望可以讓程式碼更好維護,但功能要一樣,不然出問題了會覺得自己很野小!
這也是為什麼重購一開始要先寫一點測試的原因。先寫系統再來寫測試,我認為是目前業界比較常看到的模式屬於防禦類型,預防修改帶來的錯誤,另外一種現在蠻多新創公司的開發模式叫 TDD 先寫測試再來打造系統,讓輸入輸出固定好結構再全力衝刺! (離題了~)
驗證資料
先從驗證資料開始,我們以新建動物資源的API來拆分驗證資料Request
檔案!
請先開啟自動執行測試
功能,如果忘記的可以參考昨天的文章 開始拆分到 Service - 寫一點點測試
新建檔案
php artisan make:request StoreAnimalRequest
撰寫程式
app/Http/Requests/StoreAnimalRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreAnimalRequest extends FormRequest
{
/**
* 是否登入才能請求
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* 請求的資料欄位規則
*
* @return array
*/
public function rules()
{
// 把 app/Http/Controllers/AnimalController.php 中 store 方法裡,之前寫的驗證表單規則複製過來
return [
'type_id' => 'required',
'name' => 'required|max:255',
'birthday' => 'required|date',
'area' => 'required|max:255',
'fix' => 'required|boolean',
'description' => 'nullable',
'personality' => 'nullable'
];
}
}
app/Http/Controllers/AnimalController.php
use App\Http\Requests\StoreAnimalRequest;
/**
* Store a newly created resource in storage.
*
* @param App\Http\Requests\StoreAnimalRequest $request
* @return \Illuminate\Http\Response
*/
public function store(StoreAnimalRequest $request)
{
// 這裡原本寫的可以全部刪掉
// $this->validate($request, [
// 'type_id' => 'required',
// 'name' => 'required|max:255',
// 'birthday' => 'required|date',
// 'area' => 'required|max:255',
// 'fix' => 'required|boolean',
// 'description' => 'nullable',
// 'personality' => 'nullable'
// ]);
// 這個store方法只會剩下下面兩行
$animal = Animal::create($request->all());
return response($animal, Response::HTTP_CREATED);
}
確認執行結果是否一樣
如果你是自己打程式碼不是複製貼上某些地方遺漏了!未注意到或是忘記引入 App\Http\Requests\StoreAnimalRequest
甚至可能忘記替換 store(StoreAnimalRequest $request)
的程式碼,不管哪一種,因為剛剛有開啟存檔自動執行測試!
它會給一些錯誤提示,如下圖所示,它寫道 AnimalTest::testCanCreateAnimal
的測試程式錯誤,應該要回傳狀態碼 201 卻返回 500,還記得狀態碼500的意思嗎? 回去看這篇 Day 22 進階 RESTful API 討論
反正就是伺服器錯誤,這時候有兩種方法可以確認錯誤的提示,就是看Log
或手動用Postman
送一次新建動物資源的請求(因為現在 Laravel 不是產品模式,所以它會顯示錯誤的位置,並且給予提示!)
就算測試功能正確!但是因為我們這次修改的內容是驗證使用者提供的資料,若不符合規定會產生提示,這部分我們沒有撰寫到測試,也就是測試覆蓋率沒有覆蓋到的地方,所以囉!我們來手動測試一下!
打開 Postman
送新建動物資源的請求確認一下! 因為我們的測試程式只有測試使用者提供資料正確時,回傳的資料是否正確,並沒測試使用者送來的資料不正確時的狀況。因此測試程式還是會顯示通過!
你們可以注意看到
這邊故意把 fix
的欄位(動物是否已經結紮)故意亂輸入一個值,並不是規定的 true
或 false
,所以回傳資料格式錯誤的訊息,這是我們要的結果,表示我們的修改正確,功能正常!
明天繼續拆分 Controller 讓它越來越瘦!