域驱动设计可以用例驱动吗?

时间:2018-02-28 23:53:22

标签: process domain-driven-design use-case

也许这个问题是矛盾的,但DDD从用例开始开发是否正确,然后你开发了支持这些服务的域模型?

如果设计是由域驱动的(如DDD所说),则假设您首先开发域模型(通过了解问题域并使用泛在语言),然后开发应用层(用例) )将使用域。

然而,似乎在DDD中,您首先从用例(或用户故事)开始,然后开发域模型。

4 个答案:

答案 0 :(得分:1)

  

如果设计是由域驱动的(如DDD所说),那就是假设   您首先开发域模型(通过了解问题   域和使用泛在语言),然后你开发   将使用域的应用程序层(用例)。

     

然而,似乎在DDD中你从用例(或用户)开始   故事)首先,然后你开发领域模型。

这些陈述都不准确。 DDD的 -driven 部分并不意味着系统实现中的特定顺序。它只是说整个设计和编码工作应主要围绕域及其语言。

您可以先选择首先将应用层实现为域层。无论如何,在开始实施之前,域的逻辑模型都需要存在。用例与域模型使用相同的语言 - 如果没有至少一个定义明确的无处不在的语言和草图模型,开发应用程序层是没有意义的。

答案 1 :(得分:0)

正如名称​​域驱动设计所暗示的那样,位于中心位置。所以你先建模域名。

因此,您需要与域专家交谈,并且需要为interdisciplinary team中的每个人建立对该域的良好理解。其中一部分是找到/创建无所不在的语言,确保每个人用相同的词语表示相同的事物,因此您的目标是消除基于不明确的术语的冗余和误解。

我已在DDD and co.撰写了一篇博文系列,您可能对此感兴趣。另外,我在Auth0博客上写了this blog post,其中介绍了如何使用DDD,事件源和CQRS以及wolkenkit从头开始建模和构建软件,这是一个开源的CQRS和事件 - JavaScript和Node.js的采购框架。

拥有域模型和无处不在的语言后,您就可以开始定义用户故事了。实际上,一旦你为你的域建模,这是一个非常简单的任务。

答案 2 :(得分:0)

根据我的经验,我建议从用例(应用层)开始实现。这里有一些原因:

  • 用户故事以用例的形式出现:“注册用户”,“下订单”等等。所以对我来说从那里开始编码更自然。
  • 由于用例的输出是通过从域返回/发布一些事件的状态转换,我使用它们首先创建测试,如下所示:

given(new User("an id", "inactive_email@example.com"))
.when(new ActivateUserEmailCommand(input))
.then(new EmailUserWasActivated())
  • 一旦我为每个不同的场景实施了测试,我的用例可以通过我甚至可以将测试类传递给另一个人(可能是经验较少的人)并让他实现它,因为大多数UL已在测试中定义。

  • 我看到的一个好处是,您只需实施最少量的代码即可使用例正常运行。这样您就可以避免预先确定Aggregate Root需要哪些属性,而只关注特定用例所需的属性。

  • 通过仅实现用例(以及测试和域),您的PR将更容易被审查,因为审阅者只看到使用的内容,并且他们不应该找到不是的属性/参数之所以使用,是因为他们更难理解添加它们的原因是什么。

答案 3 :(得分:0)

DDD并不意味着实施中的任何“订单” 但是,它在理解域名方面付出了很多努力,并且尽可能地使其成为明确的
根据项目的不同,可能需要数月才能充分了解域名,我认为软件应该随着域名的团队知识而发展。

所以,我认为从用例开始(以非常敏捷的心情),编写测试,实现/演化域,完成用例,让测试通过,确保一切没关系,继续使用下一个用例。

因此,您的应用程序中的域图层将不断发展,并且随着您获得更多有关它的知识,将通过新概念和对您的域的理解进行改进。

<强>更新
这种方法的难点在于保持用例的快速开发,因此可以轻松地重构模型。要做到这一点,所有干净的代码,设计模式以及发现的所有技巧都能帮助您做出“好”的代码 可能很难重构的可能是持久化数据。拥有持久化数据的数据结构重构可能会非常痛苦,因此事件采购技术与DDD有很多关联。 (以简单的方式)它以存储不可变数据结构为中心,您的“域模型”只是这些数据的内存投影,因此您可以重构模型而无需重构持久数据。