跟控制器說再見吧,從今天開始使用請求處理器(Request Handlers) 範式

在過去幾年中, PHP 開發環境發生了很大的變化。我們開始使用更多更好的設計模式,比如 DRYSOLID) 設計模式原則。但爲什麼我們仍然在使用控制器?

如果您以前曾經參與過大型項目的架構編寫,那麼您可能已經注意到遲早會出現控制器過多的這種現象。即使您將控制器邏輯分離到各種類庫或服務類中,大量的依賴項和方法以及代碼的行數還是會隨着時間的推移不斷增長。

我來介紹一下請求處理器。這個概念很簡單,但很多 PHP 開發人員都不知道。請求處理器可以理解爲僅包含單個動作(Action)的控制器,能夠使請求到響應的流程更加清晰明確。這個概念與 Paul M. Jones 提出的 Action-Domain-Responder 設計模式有相似之處,後者是MVC模式的替代品。

file

一個好的方法去建立請求處理器就是使用調用類。可調用類是使用PHP中的魔術方法 __invoke ,把他們變成一個 Callable ,這將允許他們作爲函數調用。這裏有一個關於調用類的簡單例子:

class Greeting
{
    public function __invoke($name)
    {
        echo 'Hello ' . $name;
    }
}

$welcome = new Greeting();
$welcome('John Doe'); //輸出 Hello John Doe

看到這裏你大概會想;“我爲什麼要這樣做?”。我知道這是一個有點荒謬的例子。但是它與某些代碼一起使用時例如可調用對象和依賴注入,它將變得很有意義。一個好的使用例子是路由的請求處理在Laravel和Slim框架中。

Route::get('/{name}', Greeting::class);

是否讓你大吃一驚?沒有?讓我們把它和你通常寫的比較一下:

Route::get('/{name}', 'SomeController@greeting');

還沒有?除了代碼好看之外,還有其他優點。讓我們先去看看使用請求處理程序比控制器有那些優點。

單一模式

SOLID 的第一個原則是“單一模式”。在我看來,控制器中存在許多的方法,就打破了這個原則。請求處理程序提供了一個很好的解決方案,可以將這些操作分成它們自己的類,使它們更易於維護,重構和測試。

這是從 UsersController 中提取的2個請求處理程序的示例,它處理用戶配置文件的編輯和保存:

class EditUserHandler
{
    public function __construct(
        UserRepository $repository,
        Twig $twig
    ) {
        ...
    }

    public function __invoke(Request $request, Response $response)
    {
        ...
    }
}

class UpdateUserHandler
{
    public function __construct(
        UserRepository $repository,
        UpdateUserValidator $validator,
        ImageManager $resizer,
        Filesystem $storage
    ) {
        ...
    }

    public function __invoke(Request $request, Response $response)
    {
        ...
    }
}

接下來讓我們看下一個優勢;

測試性能

你最近有沒有爲你的項目編寫過單元測試?在編寫單元測試的時候你可能編寫了一些與測試無關的模擬依賴項。由於請求處理器將不同的控制器操作拆分爲單獨的類,因此您只需注入或綁定該動作所需要的依賴項即可。

這是 Jeffrey Way 的一些建議 Twitter

提示:讓你的功能測試儘可能更加詳細具體,使用測試用例來描述重要的規則和能力。

這基本不會讓你的請求處理器都有一個測試文件。對於那些繁瑣的控制器測試文件來說是一個非常好的改進。

重構

PhpStorm 和其他的編輯器都有強大的代碼重構功能,但是如果你使用的是 Laravel 或者 Slim 框架默認的路由方法將控制器綁定到路由,那麼你可能會遇到這種問題。

例如重命名:

Route::get('/{name}', Greeting::class);

比這簡單得很多:

Route::get('/{name}', 'SomeController@greeting');

結論

請求處理器是控制器很好的替代品。控制器的動作(Actions)被分爲多個獨立的請求處理器類,分別負責響應單一的動作。這使整個項目的代碼更易於維護、重構和測試。

您是否應當使用請求處理器替換所有控制器?可能不是。對於小型應用程序而言,爲了簡單,將動作組合成控制器或許更加合理。當我開始在 Teamleader 工作後,我纔開始發掘請求處理器,我覺得近期沒什麼換回控制器的必要了。

如果有什麼不清楚或有疑問,請在下面留下評論告訴我,我會更新這篇文章。

轉自 PHP / Laravel 開發者社區 https://laravel-china.org/top...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章