讓你的程式更美好 – 重構現有的程式碼

開始重構程式碼,前幾天有提到 Controller 越來越肥大,程式碼越來越多,根本就已經超出人類想要看的範圍了!就像一篇好的文章,字數太多也是一件壞事,要有足夠的耐性才會想看。

這系列鐵人賽目前的 Controller 程式碼還不算太多,還算簡單拆開來相對容易,講解也比較清楚。

預計這樣拆開目前的 Controller

  • 驗證會員等級權限 – 已由 Policy 負責
  • 驗證使用者輸入資料 – 需再加入 Request
  • 商業邏輯或外部資源 – 需再加入 Service
  • 轉換資料結構 – 已由 Resource 負責

為了達到接近單一職責原則預計把Controller 拆成這個樣子! 降低程式之間的耦合性!對目前的程式來說比較好!檔案不會拆太多太細,又可以讓程式可讀性增加, PolicyResource 已經完成了!現在來拆解 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) 的程式碼,不管哪一種,因為剛剛有開啟存檔自動執行測試!

phpunit測試出現誤

它會給一些錯誤提示,如下圖所示,它寫道 AnimalTest::testCanCreateAnimal 的測試程式錯誤,應該要回傳狀態碼 201 卻返回 500,還記得狀態碼500的意思嗎? 回去看這篇 Day 22 進階 RESTful API 討論

phpunit測試出現誤

反正就是伺服器錯誤,這時候有兩種方法可以確認錯誤的提示,就是看Log 或手動用Postman 送一次新建動物資源的請求(因為現在 Laravel 不是產品模式,所以它會顯示錯誤的位置,並且給予提示!)

就算測試功能正確!但是因為我們這次修改的內容是驗證使用者提供的資料,若不符合規定會產生提示,這部分我們沒有撰寫到測試,也就是測試覆蓋率沒有覆蓋到的地方,所以囉!我們來手動測試一下!

打開 Postman 送新建動物資源的請求確認一下! 因為我們的測試程式只有測試使用者提供資料正確時,回傳的資料是否正確,並沒測試使用者送來的資料不正確時的狀況。因此測試程式還是會顯示通過!

Postman嘗試送一次請求

你們可以注意看到 這邊故意把 fix 的欄位(動物是否已經結紮)故意亂輸入一個值,並不是規定的 truefalse ,所以回傳資料格式錯誤的訊息,這是我們要的結果,表示我們的修改正確,功能正常!


明天繼續拆分 Controller 讓它越來越瘦!


發佈留言