DDD:领域模型命名空间约定

11

我正在用PHP编写一个带有领域模型的应用程序,想知道应该采用哪种命名规范。

假设我有一个Customer,其聚合根内有一个Address
我还有一个Product,其聚合根内有一个Option

我有两个选择:

  1. 将聚合根保留在领域模型的根目录中:

    Customer
    Customer\Address
    Product
    Product\Option
    

    优点: 我可以在同一个命名空间中使用CustomerProduct


    缺点: Customer必须将自己的Address引用为Customer\Address
  2. 将所有聚合类都分组放在同一个命名空间中,包括聚合根:

  3. Customer\Customer
    Customer\Address
    Product\Product
    Product\Option
    

    优点: Customer可以将其地址引用为Address
    缺点: 我必须从我的根域命名空间引用:

    • Customer作为Customer\Customer
    • Product作为Product\Product

这是一个有趣的问题。很想听听其他人是如何解决的。希望我们很快能看到一些答案,Benjamin :-) - Tommy Jakobsen
开始悬赏,希望能获得更多关于这个主题的资源! :-) - BenMorel
有一件事闪过我的脑海(也许与主题无关):当项目规模庞大或者有很多人参与开发/维护时,命名空间特别有用。DDD的基本原则是保持简单和条理,这意味着应用程序内几乎不会存在任何类型的冲突。那么,在这种情况下,命名空间真的必要吗? - yoda
@yoda:这是一个好问题,但是我们正在开发的应用程序目前由几十个类组成,因此,我们非常高兴有命名空间来组织代码! - BenMorel
1个回答

5
我之前写了一个小框架,选择使用你提出的第一种解决方案。

将聚合根保留在领域模型的根目录下:

为什么?
实际上,我曾经问过自己今天你正在问的同样的问题,在与我的团队成员讨论后,我们一致认为不在命名空间中重复类名更加合理。

让我们看看如何使用解决方案2实例化您的类

Customer\Customer
Customer\Address

你将不得不编写:

$customer = new Customer\Customer();
$address = new Customer\Address();

你能看到重复了吗?在我看来,这有点不太对劲。就像写

一样。
$customer->getCustomerId();

为什么在方法名中重复使用Customer? 我们知道这是客户的ID,因为我们正在使用一个Customer对象。

这个模型的另一个“坏处”是无法使用保留关键字作为类名。

例如,使用pear约定,您可以有以下类:

Customer_Abstract

位于Customer/Abstract.php,这对我来说是可以的,但如果您尝试使用命名空间进行翻译,则会遇到问题。
namespace Customer;

class Abstract {}

这会导致致命错误。因此,您需要在类名中再次重复域名:
namespace Customer;

class AbstractCustomer {}

$customer = new Customer\AbstractCustomer();

现在让我们看看如何使用解决方案1实例化您的类。
Customer
Customer\Address

你将编写:

$customer = new Customer();
$address = new Customer\Address();

我们不再需要重复两次客户名称来实例化客户类了。然而,地址与客户仍然有关联。
这就是我选择使用这个模型的原因。
编辑:Zend Framework 2也使用这种约定。

感谢您的回答。然而,看起来ZF2实际上采用了完全相反的方法:Zend\Form\FormZend\Mail\Mail等。它们旨在将每个组件打包到单个目录中。 - BenMorel
你说得对。我没有看完整段代码。我只看到了Zend\Controller\Router、Zend\Controller\Router\Route,然后就没有再往下看了。我的错。 - Alfwed
好的,我原以为对于这个问题我们会有更多的阅读材料,但这可能意味着这只是个人偏好的问题,而不是"最佳实践"。我们最终将只在域模型命名空间的根节点处放置聚合根,并将所有它们的子实体放置在相应名称的命名空间中。如果聚合根是一个抽象类,则其具体子类也将在子命名空间中。 - BenMorel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接