如何应对DDD中的可变性挑战

时间:2012-05-30 11:02:23

标签: architecture domain-driven-design immutability

在大学的SE课程中,我们学习了OOAD和DDD(使用Java)并鼓励在我们的项目中使用它。不幸的是,没有讨论由实体的可变性引起的许多挑战:

  • 多线程应用程序不适合
  • 它打破了依赖equals(),hashCode()或compareTo()(*)
  • 的数据结构
  • 这使得很难推断出实体的状态

这些问题让我很难使用DDD,虽然我喜欢它背后的想法和许多库和框架(如ORM,序列化库 - 基本上所有使用Java Bean的东西)都依赖于实体的可变性。结果是,无论我做什么,我在做出架构决策时都会产生怀疑,对结果也不满意。要么我得到一些弗兰肯斯坦的怪物应用程序,我有实体不可变,但很多可变的胶水使其工作(生成器,可变的DAO / DTO),或者我有一个完全可变的应用程序充满WTF(如每次排序列表我使用它而不是使用已排序的数据结构,因为实体可能已被更改,因为它已添加到列表中。)

你如何处理这些问题?怎么走?是否有不需要可变性的DDD替代品?

我个人更喜欢完全不可变,但这会使得使用一些需要Java Bean的库非常困难甚至不可能。当然我可以切换到函数式编程,但我不确定它是否可以替代使用DDD的典型项目。

(*)好吧,只有你覆盖它们。但是,如果不这样做,那么使用集合的重点是什么?

2 个答案:

答案 0 :(得分:2)

我不确定“不可变实体”是什么意思,但这听起来像是对我的矛盾。实体是关于身份的,你应该能够在它们的整个生命周期中识别和跟踪它们,当它们被创建,修改,持久化,再水合时...你可以确定跟踪和持久的东西永远不会改变,但我没有看到兴趣 - 存在身份的基本原因恰恰是在一些变化的东西上加上一个固定的标签。

有些域对象实际上适用于不变性,但不适用于实体,而不是值对象,其身份无关紧要的对象。您可以轻松地将值对象实例替换为另一个,等于没有后果的实例。

如果你要做的是让每个域对象都成为一个不可变的值对象,那么这肯定不再是DDD了。 DDD是关于面向对象的,而不是纯粹的函数式编程:)

答案 1 :(得分:0)

这些是常见问题。我假设您考虑以下情况:

  • 从持久数据构建'Order'对象
  • 对“订单”进行一些更改
  • 坚持改变。

如果在同一场景中有两个同时发出的请求,则:

  • 多线程应用程序不适用:首先,您有两个不同的实例,第二,您在保存数据时使用乐观/通过锁定。
  • 它破坏了依赖于equals(),hashCode()或compareTo()的数据结构 - 如果它们的标识符相等,则两个域实体是相等的(否则你的值类型是不可变的定义)。
  • 这使得很难推断实体的状态 - 不确定为什么需要它。 O / RM跟踪自动进行数据更新,DDD是存储不知道的。如果更改跟踪是业务逻辑的一部分,那么就需要实现,是的。