将空的 class 作为基础 class 并期望 class 将来可能有成员是一种不好的做法吗?
Is it bad practice to have an empty class as a base class, with the expectation that the class may have members in the future?
简单示例:
public class Food
{
public virtual void Eat()
{
StuffInMouth();
}
}
public class Fruit : Food
{
// Nothing here yet, but likely could be in the future
// Is this bad from a .NET/C# style guidelines perspective?
}
public class Apple : Fruit
{
public virtual void Eat()
{
Clean();
base.Eat();
}
}
public class Orange : Fruit
{
public virtual void Eat()
{
Peel();
base.Eat();
}
}
我说得再简单点,就叫Speculative Generality.
问题原因: 有时会创建代码 "just in case" 以支持从未实现的预期未来功能。结果,代码变得难以理解和支持。
正如 Steve McConnell 在 Code Complete - 2 中指出的那样,
Programmers are notoriously bad at guessing what functionality might be needed someday.
1.需求未知,因此程序员必须猜测: 错误的猜测将意味着必须丢弃代码。
2.即使是接近的猜测也会对细节有误:这些错综复杂的事情会破坏程序员的假设——代码必须(或应该)被丢弃。
3. Other/future 程序员可能认为推测代码比实际情况更好或更有必要: 他们在推测代码的基础上构建代码,当必须删除或更改推测代码时会增加成本。
4.推测性的普遍性增加了复杂性并需要更多的测试和维护:这会增加成本并减慢整个项目的速度。
致谢:代码完成 - 2 | Pluralsight course on refactoring.
恕我直言,这是一个没有附加值的额外抽象层。
它增加了不必要的复杂性,所以在我看来这是不好的做法,也是 YAGNI 的一个例子。
是的,重要的是要认识到,虽然这样做可以节省时间(如果使用的话),但通常最好为不久的将来编写代码,或者至少了解何时编写代码永远不会到来的未来。
太早实施也会带来维护开销。
没有人说 class 必须有任何成员。 class 代表一类对象,因此如果它们没有有用的属性(不是语言的意思),将它留空是完全可以的。因此,重要的是 class 是否代表您的代码需要处理的有意义的对象类别。
在您的情况下,如果您的代码通常对食物进行操作,那么拥有一个共同的 Food
祖先是有道理的。 但是,一个更好的概念可能是引入一个 IFood
接口,有效地将食物契约与实际的继承层次结构分离。例如,有意义的层次结构可能以 Animal
class 开头,但并非所有动物都被视为食物(免责声明:这是粗略的示例)。
简单示例:
public class Food
{
public virtual void Eat()
{
StuffInMouth();
}
}
public class Fruit : Food
{
// Nothing here yet, but likely could be in the future
// Is this bad from a .NET/C# style guidelines perspective?
}
public class Apple : Fruit
{
public virtual void Eat()
{
Clean();
base.Eat();
}
}
public class Orange : Fruit
{
public virtual void Eat()
{
Peel();
base.Eat();
}
}
我说得再简单点,就叫Speculative Generality.
问题原因: 有时会创建代码 "just in case" 以支持从未实现的预期未来功能。结果,代码变得难以理解和支持。
正如 Steve McConnell 在 Code Complete - 2 中指出的那样,
Programmers are notoriously bad at guessing what functionality might be needed someday.
1.需求未知,因此程序员必须猜测: 错误的猜测将意味着必须丢弃代码。
2.即使是接近的猜测也会对细节有误:这些错综复杂的事情会破坏程序员的假设——代码必须(或应该)被丢弃。
3. Other/future 程序员可能认为推测代码比实际情况更好或更有必要: 他们在推测代码的基础上构建代码,当必须删除或更改推测代码时会增加成本。
4.推测性的普遍性增加了复杂性并需要更多的测试和维护:这会增加成本并减慢整个项目的速度。
致谢:代码完成 - 2 | Pluralsight course on refactoring.
恕我直言,这是一个没有附加值的额外抽象层。 它增加了不必要的复杂性,所以在我看来这是不好的做法,也是 YAGNI 的一个例子。
是的,重要的是要认识到,虽然这样做可以节省时间(如果使用的话),但通常最好为不久的将来编写代码,或者至少了解何时编写代码永远不会到来的未来。
太早实施也会带来维护开销。
没有人说 class 必须有任何成员。 class 代表一类对象,因此如果它们没有有用的属性(不是语言的意思),将它留空是完全可以的。因此,重要的是 class 是否代表您的代码需要处理的有意义的对象类别。
在您的情况下,如果您的代码通常对食物进行操作,那么拥有一个共同的 Food
祖先是有道理的。 但是,一个更好的概念可能是引入一个 IFood
接口,有效地将食物契约与实际的继承层次结构分离。例如,有意义的层次结构可能以 Animal
class 开头,但并非所有动物都被视为食物(免责声明:这是粗略的示例)。