【问题标题】:DDD and Hexagonal architecture - ServicesDDD 和六边形架构 - 服务
【发布时间】:2015-11-06 13:40:41
【问题描述】:

自从我开始构建我的 DDD/Hexagonal 架构应用程序以来已经有一段时间了,我对与它们相关的大量概念感到不知所措。

尽管当我发现有必要时,我开始稍微尝试并尝试应用概念。我发现仍然有很多我不能甚至不想应用到我的应用程序中,其中一些是:适配器、命令(CQRS?)、事件..

除此之外,我对与 Hexagonal Architecture 相关的一些事情有些困惑。 我正在尝试应用外部行为的定义应该依赖于内部,所以 Infrastructure Layer -> Application Layer -> Domain Layer

在我的例子中,我在 Application Layer 中定义了 Services 作为 LoginService 的示例:

class LoginUserService implements ApplicationServiceInterface
{
private $userRepository;
private $session;

public function __construct(UserRepositoryInterface $userRepository, Session $session)
{
    $this->userRepository = $userRepository;
    $this->session = $session;
}

public function execute($request = null)
{
    // TODO: Implement execute() method.
    $userName = $request->get('user');
    $password = $request->get('password');
    $user = $this->userRepository->findByUsername($userName);
    if (!empty($user) && $user->validate($password)) {

        $this->session->start();
        $this->session->set('user', array('id' => $user->getUserId(), 'username' => $user->getName(), 'email' => $user->getEmail()));
        return true;
    } else {
        return false;
    }
}
}

但是,我很确定我在吹嘘 hexagonal architecture 所代表的依赖声明。因为我的应用层依赖于基础设施层。 (在这种情况下,$this->userRepository->findByUsername($userName); 是注入到应用程序的 serviceContainer 中的 DoctrineUserRepository 的一部分)

我的 repo 在 github 上完全可用:Malendar Repository

如何处理这个依赖于数据库输出的服务案例? 另外,我跳过哪些概念会很好用?

先谢谢你=D

【问题讨论】:

  • 你应该在Codereview site问这个问题。
  • 谢谢@mTorres 下次我知道该去哪里了:)

标签: php domain-driven-design silex hexagonal-architecture


【解决方案1】:

UserRepositoryInterface 应该在域层中定义。如果它在基础设施层,你应该把它移到领域层。

当您创建 UserRepositoryInterface 时,您创建了一个所有基础设施层实现都必须履行的合同。这是Dependency Inversion principle 的教科书示例。

您可以放心地假设实现履行了合同。这个假设不会创建对基础设施层的依赖。

所以,LoginUserService 只依赖于UserRepositoryInterface(应该是域层的一部分)和Session。

我会更担心Session 依赖和$request 参数。我不知道 PHP 和您使用的框架,但在 MVC 模式中,我宁愿将两者都保留在控制器中,将逻辑委托给应用程序层。经验法则是应用层不应该负责处理任何特定于 HTTP 的问题。我会让LoginUserService.execute 方法接受$userName 和$password 参数并返回登录用户的详细信息。

它当然会破坏implements ApplicationServiceInterface 部分,但无论如何都应该删除这个接口。应用层方法会有不同的参数和返回类型。

【讨论】:

  • 如果您有域,则应在域层中创建UserRepositoryInterface。
  • 感谢 Jakub 的回复,尽管我认为存储库接口必须在域层中定义。我在这方面所做的方法仍然与您提到的基础架构层和 HTTP 特定问题相结合,所以我遇到了命令和命令处理程序,我正在尝试采用另一种方法来正确构建它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多