1

我是一个生疏的程序员,试图再次在该领域学习。我断断续续地发现,我的自学和正规教育都导致了一些坏习惯。因此,我试图让我的思想围绕良好的设计模式,以及——通过扩展——当它们是错误的。语言是 Java,这是我的问题:

我正在尝试编写软件来协助啤酒酿造。在酿造过程中,有时您必须用特定种类的啤酒花代替配方中要求的啤酒花。例如,您可能有一个需要“阿马里洛”啤酒花的配方,但您只能得到“Cascade”,它具有足够相似的香气,可以替代;啤酒花具有一定量的 Alpha 酸(每给定质量),两种啤酒花之间的比率是替代公式的一部分。我正在尝试在我的程序中(正确地)对此进行建模。

我最初的目标是拥有两个对象。一个 a HopVariety,它具有关于各种啤酒花的一般描述信息,一个 a HopIngredient,它是 a 的特定实例,HopVariety还包括给定配方中使用的量。HopIngredient应该知道它的多样性,并且HopVariety应该知道什么可以用作它的替代品(并非所有替代品都是对称的)。这似乎是好的 OOP。

问题是这样的:我正在尝试遵循良好的做法并使我的价值对象不可变。(在我的脑海中,我将其归类HopVarietyHopIngredient价值对象,而不是“演员”。)但是,我需要用户能够使用新的可行替换来更新给定的 HopVariety。如果我遵循不变性,这些更改将不会传播到单个成分。如果选择可变性,我会通过共享可变值对象潜在地引入副作用而表现不佳。

因此,选项 B:引入各种类型的 VarietyCollection,并通过名称或唯一标识符松散地耦合成分和品种。然后是 VarietySubstitutionManager,这样品种就不会引用其他品种,而只会引用它们的 id。这与我想要做的背道而驰,因为持有对品种对象的引用具有直观意义,现在我要介绍感觉像是过度抽象的东西,并将函数与数据分开。

那么,我如何在特定实例之间正确共享状态?解决问题的正确或至少最明智的方法是什么?

4

3 回答 3

1

你确定HopVariety应该是一个值对象吗?在我看来,这听起来像是一个实体——“阿马里洛”啤酒花品种是唯一的,所以它应该是一个唯一可识别的对象。就像“托尼伍斯特”只是一个(不完全是,但你明白了;))

我推荐阅读领域驱动设计以及实体和值对象之间的差异。

顺便说一句:DDD 书中有很多像你这样的情况以及如何处理它们的例子。

于 2009-04-08T05:48:10.477 回答
0

我认为您的选择是

  • 让“更新品种”功能遍历现有的对象图并创建一个更新了所有成分的新对象图,或者
  • 继续使用可变性

根据手头的信息,我不清楚哪个更适合您的情况。

于 2009-04-08T05:38:45.447 回答
0

您希望避免具有多个引用的对象突变有多严重?

如果您希望配方集合反映用户对品种集的更新,并且您希望避免对象中的可变字段,那么您将强迫自己使用功能对象更新来处理用户输入。

条路的尽头是 I/O monad。你想朝那个方向走多远?

使用允许变异副作用的函数式语言,例如 S/ML 等,您可能会选择保持品种和成分对象的纯净,并存储从存储在单个可变对象中的最新品种集合返回当前品种对象的函数参考细胞。这似乎是一种合理的分割差异的方法。

于 2009-05-26T22:12:32.170 回答