不可变对象的约定

时间:2009-04-01 16:46:55

标签: .net naming-conventions immutability

当您设计不可变类时,您更喜欢:

Layer.ColorCorrect ( layer )

layer.ColorCorrect ( )

对我来说#1看起来更直观,而不是#2,看起来它修改了被引用的对象,因为它是一个实例方法,它也可以改变内部,对吧?

6 个答案:

答案 0 :(得分:8)

我更喜欢使用实例方法,但选择名称以反映它不会更改现有实例的事实。例如:

layer.AfterColorCorrection()

layer.WithCorrectedColors()

使用静态方法很快就会变得很烦人。此外,如果您向用户明确说明类型是不可变的,那么他们应该很快就能掌握它。每个人都被String.Replace绊倒并没有实际取代目标中的任何东西 - 但他们并没有犯同样的错误。使用更好的名称​​以及你应该没问题。

我问related question关于“添加”到不可变列表 - 这是IMO使用“Plus”而不是“Add”的最佳解决方案;再次,它并不意味着原始值发生了变化。您可能会发现该问题的其他答案很有用。

答案 1 :(得分:5)

我个人的偏好是专注于让类型不可变的可见。例如,我将它称为ImmutableLayer vs. Layer。或者,如果由于某种原因,Immutable不是一个好名词,我将在该类中添加一个属性,表明它是不可变的(在两种情况下都添加了属性)。

这有它的起伏。它是一个中心位置,以检查immutabliity。只需快速浏览一下,你就可以了。无需学习新的方法名称或约定。该方法的缺点是,在某些类型的推断场景中,您无法判断该值是不可变的。例如,此代码适用于ImmutableCollection和普通List

var col = GetTheCollection();
col.Add(42);

但是,我不想更改方法名称以适应不变性。原因是它是一个问题,你必须反复解决。命名事情应该很容易,但有时候难以置信。想想你曾经想做的所有类型都是不可变的。想象一下,必须为这些类型的每个变异方法找到新的名称或约定。这是一项非常重要的任务,您将花费大量时间教育用户了解这些新惯例。

我的梦想场景是找到一种方法来增加不可变类型的可见性。因为这是真正的问题,不知道类型是不可变的。目前没有好方法可以在所有场景中执行此操作,但我希望下一版本的语言/ IDE。

答案 2 :(得分:3)

@JaredPar有最好的答案,IMO,但没有一个答案是伟大的,因为今天没有任何“伟大”的解决方案。我们需要更好的工具,以及与工具协同发展的设计指南,以更好地应对不可变对象的日益普及。

@ JonSkeet的答案在API上下文中运行良好,其中几乎所有内容都是可变的,但随着不可变对象成为常态(因为所有方法都有很长的名字),它会失败。

“最佳”名称取决于您所包围的代码上下文。我认为在“大多数可变”到“大多数不可变”的上下文中可行的唯一策略是Jared提到的,其中工具使得给定对象是否是不可变的显而易见,然后每个方法都具有“命令性” name(egoAdd),它对接收器对象产生副作用(如果它是可变的)或返回一个新对象(如果它是不可变的)。

(旁白:遗憾的是,像“StringBuilder”这样的“流畅”效果API意味着你不能只看方法签名来决定接收者对象是否不可变,因为这样的例子'返回这个'是流利的,给予与“返回副本”相同的签名。)

答案 3 :(得分:1)

通常你有类似的东西:

layer = layer.ColorCorrect([required parameters here]);

这与

类似
mystring = mystring.Substring(1, 2);

创建一个新字符串,它是第一个字符串的子字符串。

答案 4 :(得分:0)

它完全反对OOPS原则来编写静态方法,传递一个实例并使它看起来像程序编程,如“C”。同样在第一种方法中,你输入的是Layer两次,这种方式使读者不明确。

答案 5 :(得分:0)

使用静态方法将那种规则排除在外,不是吗?这似乎是一个非常重要的限制。