0

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

  • 不适合多线程应用程序
  • 它破坏了依赖 equals()、hashCode() 或 compareTo() 的数据结构 (*)
  • 很难对实体的状态进行推理

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

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

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

(*) 好吧,只有当你覆盖它们时。但是,如果你不这样做,那么使用集合又有什么意义呢?

4

2 回答 2

2

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

一些领域对象实际上适合不变性,但不是实体,而是值对象,身份无关紧要的对象。您可以轻松地将值对象实例替换为另一个值对象实例,而不会产生任何后果。

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

于 2012-05-30T15:37:46.027 回答
0

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

  • 从持久数据构造“订单”对象
  • 对“订单”进行一些更改
  • 坚持所做的更改。

如果有两个同时请求遍历同一场景,则:

  • 不适合多线程应用程序:首先,您有两个不同的实例,其次,您在保存数据时会使用乐观/被动锁。
  • 它破坏了依赖于 equals()、hashCode() 或 compareTo() 的数据结构——如果两个域实体的标识符相等,则它们是相等的(否则你的值类型根据定义是不可变的)。
  • 这使得很难推断实体的状态- 不知道为什么需要这个。O/RM 自动跟踪数据更新目的,DDD 是存储不感知的。如果更改跟踪是业务逻辑的一部分,那么就需要实施,是的。
于 2012-05-31T11:10:24.373 回答