设计域模型的类图

时间:2016-01-28 17:03:45

标签: uml domain-driven-design class-diagram

首先,不要以为我试图让其他人完成工作,但是我试图为域模型设计一个类图,我做的事情可能是错的,因为我被卡住了,所以我只是希望得到关于我没有正确继续做什么的提示......

例如,用户需要按产品列表中的类别搜索产品。每个类别可能有子类别,可能有子类别等。

我制作的第一张图是(简化): enter image description here

用户还需要获取类别的树列表,其中包含至少一个产品。 例如,如果这是所有类别树:

  • 乐器
    • 字符串
      • 吉他
      • 小提琴
    • 打击乐
  • 书籍
    • 漫画
    • 小说
    • 约会

我无法返回类别的树,其中至少有一个产品,因为我也会获得所有子类别,但不是每个子类别都有与之关联的产品。

我也无法从Category.subCategories集合中删除项目,只保留具有相关产品的项目,因为它会改变可能在其他地方共享的类别实体,这不是我想要的。

我想过做一个副本,但是我会在同一个环境中得到同一个实体的两个不同的实例,这不是一件坏事吗?

所以我重新设计了这个: enter image description here

现在我没有收到每个类别我不想要的子类别集合,我只知道它的父类别,这没关系。

但是,这会创建一个只能从底部到顶部导航的类别树,对于总是需要顶部的> ProductList的客户端来说没有任何意义。类别的底部导航。

作为一种解决方案,我想到了下面的图表,但是我不确定它是否非常好,因为它有点愚蠢,而且RegionTreeItem在域语言中似乎没有什么意义。 enter image description here

我做错了什么?

3 个答案:

答案 0 :(得分:3)

这取决于图表的目的。您是否应用某种软件开发方法来定义此图表在特定上下文中的用途以及目标读者?

因为你谈到'领域模型',我想你的目标是提供一种概念模型,即将应用程序的功能传达给最终用户,测试人员等所需概念的模型。在这种情况下,第一个和第二个图都是有效的,但没有操作(FilterByCategory和GetCategories),因为这些与该受众无关。 GUI仅显示完整类别树的子集这一事实通常不以UML图表表示,而是以纯文本表示。

另一方面,如果您的目的是为开发人员提供技术设计,那么第三个图表是有效的。开发人员可能需要一个类来持久化数据库中的类别('Category')和一个单独的类来为GUI提供类别('CategoryTreeItem')。你是对的,这种区别在领域语言中没有意义,但在技术设计中,通常会有这样的附加类。如果您的模型与他们使用的编程语言和库/框架兼容,请与开发人员联系。

最后一句话: 在第一个图中,您在父端指定了multiplicity = 1。这意味着每个类别都有一个父级,这显然不是真的。第二个图具有正确的多重性:0..1。第三个图对CategoryTreeItem的组成有一个不正确的multiplicity = 1。

答案 1 :(得分:3)

这是一个算法问题,而不是模型问题。你的第一种方法是完全没问题,除非你对约束保持沉默。因此,您可以为任何产品分配类别或子类别。如果您指定子类别,则表示根据此模型,产品也将具有父类别。为了说清楚,我会附加一个约束,告诉我们需要将产品分配给最精细的已知类别谷物。例如。吉他产品将被分配到Guitar类别。因为像Stick这样更奇怪的乐器会得到Strings类别(这并不意味着它是一把吉他一把小提琴,而只是在更高的类别中。

现在,当您实施Category时,您可能会想到一个方法来返回assignedInstruments()的集合,Guitar将返回FenderAlhambra,您可以扩充此assignedInstruments(levelUp:BOOL)以获得上述类别的那些工具。

一般来说,您必须明确类别分配的基本含义。如果您更改了分配,则产品将以另一个列表结束。

答案 2 :(得分:0)

从我的角度来看,你的设计过于复杂。

围绕查询需求制定域模型通常是错误的方法。域模型对表达域行为最有用。换句话说,处理命令并保护正确边界内的不变量。

如果您的Product聚合根(AR)通过id引用Category AR,并且此关系存储在关系数据库中,那么您可以使用简单数据库轻松实现任何提及的查询用例查询。您首先要收集树的平面表示,然后可以使用它来构建内存中的树。

这些查询可以通过作为应用程序层一部分的ProductQueryService公开,而不是域,因为它们不用于强制执行域规则或不变量:我认为它们用于完整报告或UI显示需求。在那里你可以有一个概念,例如ProductCategoryTreeItemDTO用于内存中表示。

根据图表中的DDD战术模式,你也使用了错误的术语,这是非常误导的。 AR是实体,但实体不一定是AR。实体术语主要用于指代仅在其AR的边界内唯一标识的概念,但不是全局的。