【问题标题】:Hexagonal architecture - a simple use case六边形架构 - 一个简单的用例
【发布时间】:2014-08-21 03:11:43
【问题描述】:

我已经阅读了很多关于六边形架构的文章,并且我确实了解了大部分概念(嗯,我希望我了解),但我没有找到该架构使用的任何 示例 -区分大小写。

假设我的应用领域模型是让人喝醉。整个业务逻辑包含在Person 类中,该类位于领域层中。

class Person
{
    private $name;
    private $age;

    function __construct($name, $age)
    {
        $this->age  = $age;
        $this->name = $name;
    }

    public function drink()
    {
        if ($this->age < 18) {
            echo $this->name . ' cant drink';
        }

        echo $this->name . ' drinks tequila';
    }
}

域层还包含一个PersonRepository

interface PersonRepository
{
    public function findPersonByName($name);
}

实施者:

class DoctrinePersonRepository implements PersonRepository
{
    public function findPersonByName($name)
    {
        // actual retrieving
    }
}

假设我想通过访问:GET /person/johnDoe/drink 让一个人喝醉。 我应该创建一个像这样的用例:

class MakePersonDrinkCase
{
    /**
     * @var PersonRepository
     */
    private $personRepository;

    function __construct(PersonRepository $personRepository)
    {
        $this->personRepository = $personRepository;
    }

    function makePersonDrunk($name)
    {
        $person = $this->personRepository->findPersonByName($name);

        if ($name) {
            throw new \Exception('Person not found');
        }

        $person->drink();
    }
}

并从控制器调用它?这个提到的案例应该驻留在领域层还是应用层?在这种情况下,什么是端口和适配器?如果我想有办法让这个人喝醉——一种来自 GET 请求,另一种来自php console person:drink John CLI 命令?我应该如何构建我的应用程序?

【问题讨论】:

  • 我想你快到了 - 关键是要认识到域逻辑(一个人应该不能喝酒,除非他们超过 18 岁)依赖于域模型而不是域之外模型。周围的基础设施只是为了使来自外部世界的命令适应您的域模型的命令而存在。
  • 喜欢你的例子:D 我最近写了一篇回答你的一些问题的帖子,你可能会觉得它很有用:jenko.me/ddd/2015/01/23/building-a-house-with-ddd
  • 另一篇在某种程度上解释它的文章:t.co/U7SZZcvevn

标签: architecture domain-driven-design n-tier-architecture hexagonal-architecture


【解决方案1】:

TL;DR:我认为从 DDD 的角度来看,您基本上是对的,但是为了成为六边形设计,您应该能够在您的主要端口中注册或公开您的用例:web , 控制台或 @chris-f-carroll 建议的“用法”。

我目前在一个大型 Java8 代码库项目中工作,我们按照清洁架构/垂直切片和 CQRS 的原则构建了我们的应用程序。我们有一个带有 6 个端口的 Hexagon:Web、控制台、数据库、调度、队列和电子邮件。

为了初始化我们的应用程序,我们创建了所有必需的适配器并使用它们来创建我们的应用程序实例。然后我们的应用程序模块在主端口适配器上显式注册它们的用例。最后我们启动我们的主端口适配器并且应用程序正在运行。

Alistair Cockburn tells 表示“端口标识了有目的的对话”。在我们的案例中,正如我们的设计所暗示的 CQRS,我们的应用程序和 HTTP 协议之间的有目的的对话是关于公开查询和命令(我们的用例)。

这就是为什么在我们的网络端口中使用expose(uri, query) 或expose(uri, command) 方法而不是get(uri, handler), post(uri, handler), put(uri, handler), delete (uri,处理程序)等。

如何公开这些查询和命令(即作为 HTTP GET 或 POST)是我的六边形不需要知道的 Web 端口适配器的实现细节。

【讨论】:

    【解决方案2】:

    是的,您所做的/建议是正确的。

    • 用例进入应用层。但请注意,这只是 DDD 的格言,与六边形架构无关。

    • 您的适配器是

      1. Web 服务器和您的控制器。
      2. Doctrine 与您的 DoctrinePersonRepository 一起使用。
      3. php 可执行文件+你的控制器再次(假设你的控制器在 CLI 应用程序中重复使用)
    • 您的端口:Cockburn 说“What exactly a port is and isn’t is largely a matter of taste." 我个人认为您有 2 个端口。我将其中一个命名为持久端口,您有 1 个适配器;我将命名另一个一个“使用”端口,您有 2 个适配器。

    六边形架构的一页纸当然是http://alistair.cockburn.us/Hexagonal+architecture

    【讨论】:

      猜你喜欢
      • 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
      相关资源
      最近更新 更多