【问题标题】:Controller in Clean Architecture清洁架构中的控制器
【发布时间】:2017-04-14 14:54:01
【问题描述】:

我正在尝试在 Laravel 应用程序中向 Bob 叔叔申请 Clean Architecture

我关心的是:正如鲍勃叔叔所描述的,控制器应该属于第三个圈子:接口适配器(从内到外)。这意味着Controller只依赖于Use Case Circle(第2个),并且不应该对第4个循环中的框架有任何了解。

但是有些框架中的controller需要扩展一个基类(比如一个AbstractController类),它还需要接收一个Request对象,有时还需要返回一个Response对象,所以这有点打破了依赖规则 清洁架构,因为它知道外圈的框架。

我误会了吗?如果没有,有什么解决方案可以不破坏依赖规则

我的控制器看起来像这样:

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use User\UseCase\FetchUsers;
use User\UseCase\FetchUsersRequest;

class UserController extends Controller
{
    public function index(Request $request, FetchUsers $fetchUsersUseCase)
    {
        $useCaseRequest = new FetchUsersRequest(
            // extract data from Request
        );

        $useCaseResponse = $fetchUsersUseCase->handle($useCaseRequest);

        return [
            'users' => $useCaseResponse->users,
        ];
    }
}

【问题讨论】:

    标签: controller clean-architecture dependency-rule


    【解决方案1】:

    有点晚了,但您可以在用例圈中创建一个特定控制器的接口(这在干净架构中称为输入端口)。

    然后就可以实现第三圈的接口了,比如

    // In the use-cases circle
    interface UserControllerInterface(){
    
        public function index(Request $request, FetchUsers $fetchUsersUseCase);
    
    }
    
    // In the third circle
    class UserController extends Controller implements UserControllerInterface{
    
        public function index(Request $request, FetchUsers $fetchUsersUseCase){
            $useCaseRequest = new FetchUsersRequest(
                // extract data from Request
            );
    
            $useCaseResponse = $fetchUsersUseCase->handle($useCaseRequest);
    
            return [
                'users' => $useCaseResponse->users,
            ];
        }
    }
    

    这样你就不会违反纪律了。

    【讨论】:

    • 你确实违反了纪律,因为第三个圈子知道框架。框架应该在最外层。
    【解决方案2】:

    AbstractController 属于第三个圈子。所以你不会破坏任何依赖。如果您在 用例圈中有 数据传输对象 (DTO) 用于将数据传输到 第三圈,则不会破坏任何依赖关系.

    为了实现这一点,您应该为所有请求和响应创建 DTO,将您的实体映射到 DTO 并共享 DTO 而不是实体。

    例如:您有一个 User 实体,其中包含一个名为 Name 的字符串变量。您有一个控制器将从use-cases 圈子中获取用户。

    解决方案:使用字符串变量创建一个名为UserDto 的DTO(您可以将其称为Name)。控制器知道UserDto 但不知道User entity

    【讨论】:

    • 是的,我已经有一个 DTO。但是控制器在第三圈中提到了 Laravel(通过使用一些 Illuminate 类),所以它是否违反了依赖规则?
    • 如果你在第二个循环中定义你的 DTO,你不会破坏任何依赖规则
    • @cokceken 抱歉,我知道是 4 年后,但是,从用户实体到用户 DTO 的映射应该在哪里发生?我相信你应该在用例中注入一个映射器,用例会返回一个 DTO,对吗?
    • 嘿@kibe :) 我认为所有事物的映射器或通用映射器类(例如使用反射来匹配名称)还包含少量关于您的业务的逻辑。所以它应该在用例圈中,并且应该对其进行一些单元测试。如果您决定将其放在用例圈中,则与在另一个业务逻辑类中使用“业务逻辑”类相同,如果您考虑单一职责,这应该没问题。
    猜你喜欢
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2017-10-03
    • 1970-01-01
    • 2014-06-22
    • 2021-06-17
    • 2021-02-12
    相关资源
    最近更新 更多