什么是“功能嫉妒”代码,为什么将其视为代码气味?


52

关于SO的这个问题是关于纠正OP认为是功能嫉妒代码的问题。我看到这个漂亮短语被引用的另一个示例是在developer.SE中最近给出的答案中。尽管我确实在该答案的注释中要求提供信息,但我认为这对遵循Q&A的程序员理解“ 特性嫉妒 ”一词有帮助。如果您认为合适,请随时编辑其他标签。


Answers:


87

特征嫉妒是一个术语,用于描述一种情况,在这种情况下,一个对象到达另一个对象的字段以执行某种计算或做出决定,而不是要求对象自己进行计算。

作为一个简单的例子,考虑一个代表矩形的类。矩形的用户可能需要知道其面积。程序员可以公开widthheight字段,然后在Rectangle类之外进行计算。或者,Rectangle可以将widthheight字段设为私有并提供一种getArea方法。可以说这是一种更好的方法。

第一种情况的问题以及将其视为代码异味的原因是因为它破坏了封装。

根据经验,每当您发现自己广泛使用另一个类的字段来执行任何类型的逻辑或计算时,请考虑将该逻辑移至类本身的方法上。


7
+1,尽管您的示例不现实,因为有用的Rectangle类通常会公开width和height字段。
Doc Brown

2
尽管封装的破坏可能与“特征环境主义”一起发生,但到目前为止,在大多数实际示例中,我看到的情况可能并非如此。这种情况在“嘿,我只需要使用该对象在代码中计算一些东西,而我不确定是否可以触摸该对象的实现/是否应该让该对象负责该计算”的情况下发生。然后,人们使用已经公开的字段实现计算(尽管在对象内可能会实现更简洁的实现)。
布朗

2
@DocBrown想象在圆环,圆锥或球体的表面上绘制一个矩形。如果我的图形库生成的对象能够在这种情况下产生正确的结果,那么您不理会在任何情况下都不让它们来计算自己的面积是很愚蠢的。
itsbruce

1
@OskarN:根据定义,我们谈论的是功能需要。如果其他类一遍又一遍地重新实现它们,则显然需要它们。
Aaronaught

1
@OskarN .:取决于;有时,决定是明确的,有时是出于品味,而通常是出于经验。在您的文章中,斯科特·迈耶斯(Scott Meyers)撰写“ 有时少即是多”的理由很充分,并且他花了很多年的时间才知道何时应用他的“决定何时使成员函数起作用的算法”。
布朗

1

可以广泛使用其他类/结构方法的情况是可能的-当您的类/结构是数据的容器时。通常,您可以在没有外部上下文的情况下使用此数据。

这样的类仍然可以保留一些内部逻辑,但是更多时候将它们用作容器:

class YourUid {
 public:
  YourUid(int id_in_workplace_, int id_in_living_place_, DB* FBI_database, int id_in_FBI_database);
  bool IsInvalidWorker() const { return id_in_workplace == consts::invalid_id_in_workplace; }
  bool CanMessWith() const { return !FBI_database_.is_cool(id_in_FBI_database_); }
  int id_in_workplace;
  int id_in_living_place;
 private:
  int id_in_FBI_database_;
  const DB* FBI_database_;
};

@jhewlett在他的回答中引用了本文,以证明您不应该广泛使用其他类成员,但是其中的另一种代码气味情况与倡导者我的示例相同:

长参数列表。限制给定方法中需要的参数数量,或使用对象组合参数。


1
这如何回答所提问题?
gnat 2013年

@gnat Q是关于为什么将其视为“代码异味”。jhewlett给A提供了一些过于笼统的假设,并在评论中提出了疑问。我的回答是2美分,以区分“代码气味”和正常做法。
里加
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.