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

Reference 可变值对象/共享状态(和啤酒酿造!),reference,mutable,value-objects,Reference,Mutable,Value Objects,我是一个生疏的程序员,试图再次在这个领域学习。我断断续续地发现,我的自学和正规教育都导致了一些坏习惯。因此,我试图让我的思想围绕着好的设计模式,并且——通过扩展——当它们错了的时候。语言是Java,我的问题是: 我正在尝试编写软件来帮助啤酒酿造。在酿造过程中,有时你必须用特定种类的啤酒花来代替配方中所要求的啤酒花。例如,你可能有一个食谱,要求'阿马里洛'啤酒花,但你可以得到的是'级联',它有一个类似的足够替代香气;啤酒花有一个α酸量(每给定质量),两个啤酒花之间的比率是替代公式的一部分。我正试图

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

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

我最初的目标是有两个对象。一个是a
HopVariety
,它具有关于各种hop的一般描述信息,另一个是a
HopComponent
,它是一个
HopVariety
的特定实例,还包括给定配方中使用的量
HopComponent
应该知道它的种类,而
HopVarity
应该知道可以用什么替代它(并非所有替代都是对称的)。这似乎是一个很好的OOP

问题是:我试图遵循良好的实践,使我的值对象不可变。(在我的头脑中,我将
HopVariety
hopComponent
分类为价值对象,而不是“参与者”)。然而,我需要用户能够使用新的可行替代来更新给定的HopVariety。如果我遵循不变性,这些变化将不会传播到单个成分。如果选择可变性,我的行为很糟糕,因为共享一个可变值对象可能会带来副作用

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


那么,我如何在相当于特定实例的情况下正确地共享状态呢?解决这个问题的正确方法是什么,或者至少是最明智的方法是什么?

我认为你的选择是

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

有了这些信息,我不清楚哪一个更适合你的情况。

我认为你的选择是

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

有了这些信息,我不清楚哪一个更适合您的情况。

您确定
HopVariety
应该是一个值对象吗?对我来说,它听起来像一个实体——“Amarillo”是唯一的一个,所以它应该是唯一可识别的对象。就像“Tony Wooster”只是一个(不完全是,但你明白了;)

我建议您阅读实体和值对象之间的区别


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

你确定
应该是一个值对象吗?对我来说,它听起来像一个实体——“Amarillo”是唯一的一个,所以它应该是唯一可识别的对象。就像“Tony Wooster”只是一个(不完全是,但你明白了;)

我建议您阅读实体和值对象之间的区别


顺便说一句:有很多类似于您的情况的例子,以及如何处理它们。

您有多希望避免使用多个引用的对象发生变异

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

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


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

您有多希望避免具有多个引用的对象发生突变

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

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

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