可变价值对象/共享状态(和啤酒酿造!)

时间:2009-04-08 05:30:56

标签: reference mutable value-objects

我是一个生锈的程序员,试图再次在该领域学习。我已经巧妙地发现,我的自学和正规教育都会导致一些不良习惯。因此,我试图让我的思维围绕良好的设计模式,并且 - 通过扩展 - 当它们出错时。语言是Java,这是我的问题:

我正在尝试编写软件以协助啤酒酿造。在酿造过程中,有时你必须用特定种类的啤酒花代替食谱中的要求。例如,你可能有一个食谱要求'阿马里洛'啤酒花,但你可以得到的只是'级联',它具有类似的足够香气的替代品;啤酒花具有α酸量(每给定质量),两个啤酒花之间的比例是替代配方的一部分。我正试图在我的程序中对此进行建模(正确)。

我最初的目标是拥有两个物体。一个HopVariety,其中包含有关各种跃点的一般描述性信息,另一个HopIngredient,它是HopVariety的特定实例,还包括给定配方中使用的金额。 HopIngredient应该知道它的多样性,HopVariety应该知道什么可以用来代替它(并非所有的替换都是对称的)。这似乎是一个很好的OOP。

问题在于:我正在努力遵循良好做法并使我的价值对象不可变。 (在我的脑海中,我将HopVarietyHopIngredient分类为值对象,而不是'actor'。)但是,我需要用户能够使用新的可行替换来更新给定的HopVariety。如果我遵循不变性,这些变化将不会传播到个别成分。如果选择可变性,我可能会通过共享可变值对象来引入副作用,从而表现不好

因此,选项B:引入各种各样的VarietyCollection,并通过名称或唯一标识符松散地耦合成分和变体。然后是VarietySubstitutionManager,这样品种就不会引用其他品种,只能引用它们的ID。这与我想要要做的事情背道而驰,因为持有对变体对象的引用具有直观意义,现在我正在介绍过多的抽象层次,并将功能与数据分离。

那么,我如何在特定实例的数量之间正确地分享状态?什么是解决问题的正确或至少是最安全的方法?

3 个答案:

答案 0 :(得分:1)

您确定HopVariety应该是值对象吗?这听起来像一个实体 - “阿马里洛”跳跃品种是唯一的,所以它应该是一个唯一可识别的对象。就像“托尼伍斯特”只有一个(不完全一样,但你得到了重点;)

我建议阅读Domain Driven Design以及实体和值对象之间的差异。

BTW:DDD book有很多像你的情况以及如何处理它们的例子。

答案 1 :(得分:0)

我认为您的选择要么

  • 使用'更新品种'功能走现有的对象图并创建一个新的成分,更新所有成分,或
  • 继续使用可变性

根据手边的信息,我不清楚哪种情况对你的情况有好处。

答案 2 :(得分:0)

您希望避免多个引用的对象变异有多么糟糕?

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

的末尾,道路就是I / O monad。你想走多远这个方向?

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