Do polymorphism or conditionals promote better design?(多态性或条件会促进更好的设计吗?)
问题描述
我最近偶然发现了 这篇文章在 google testing blog 中关于编写更多可测试代码的指南.在此之前我一直与作者达成一致:
I recently stumbled across this entry in the google testing blog about guidelines for writing more testable code. I was in agreement with the author until this point:
支持多态而不是条件:如果你看到一个 switch 语句,你应该考虑多态.如果您在课堂上的许多地方看到相同的 if 条件重复,您应该再次考虑多态性.多态性会将你的复杂类分解成几个更小的更简单的类,它们清楚地定义了哪些代码片段是相关的并一起执行.这有助于测试,因为更简单/更小的类更容易测试.
Favor polymorphism over conditionals: If you see a switch statement you should think polymorphisms. If you see the same if condition repeated in many places in your class you should again think polymorphism. Polymorphism will break your complex class into several smaller simpler classes which clearly define which pieces of the code are related and execute together. This helps testing since simpler/smaller class is easier to test.
我根本无法理解这一点.我可以理解使用多态性而不是 RTTI(或 DIY-RTTI,视情况而定),但这似乎是一个如此广泛的陈述,我无法想象它实际上在生产代码中被有效地使用.在我看来,为具有 switch 语句的方法添加额外的测试用例比将代码分解成几十个单独的类更容易.
I simply cannot wrap my head around that. I can understand using polymorphism instead of RTTI (or DIY-RTTI, as the case may be), but that seems like such a broad statement that I can't imagine it actually being used effectively in production code. It seems to me, rather, that it would be easier to add additional test cases for methods which have switch statements, rather than breaking down the code into dozens of separate classes.
另外,我的印象是多态性会导致各种其他微妙的错误和设计问题,所以我很想知道这里的权衡是否值得.有人可以向我解释一下这个测试指南的确切含义吗?
Also, I was under the impression that polymorphism can lead to all sorts of other subtle bugs and design issues, so I'm curious to know if the tradeoff here would be worth it. Can someone explain to me exactly what is meant by this testing guideline?
推荐答案
实际上这使得测试和代码更容易编写.
Actually this makes testing and code easier to write.
如果您有一个基于内部字段的 switch 语句,那么您可能在多个地方使用相同的 switch 执行稍有不同的操作.这会在您添加新案例时导致问题,因为您必须更新所有 switch 语句(如果您能找到它们).
If you have one switch statement based on an internal field you probably have the same switch in multiple places doing slightly different things. This causes problems when you add a new case as you have to update all the switch statements (if you can find them).
通过使用多态性,您可以使用虚函数来获得相同的功能,并且由于新案例是新类,您不必在代码中搜索需要检查的内容,因此每个类都是隔离的.
By using polymorphism you can use virtual functions to get the same functionality and because a new case is a new class you don't have to search your code for things that need to be checked it is all isolated for each class.
class Animal
{
public:
Noise warningNoise();
Noise pleasureNoise();
private:
AnimalType type;
};
Noise Animal::warningNoise()
{
switch(type)
{
case Cat: return Hiss;
case Dog: return Bark;
}
}
Noise Animal::pleasureNoise()
{
switch(type)
{
case Cat: return Purr;
case Dog: return Bark;
}
}
在这个简单的例子中,每个新的动物原因都需要更新两个 switch 语句.
你忘了一个?什么是默认值?砰!!
In this simple case every new animal causes requires both switch statements to be updated.
You forget one? What is the default? BANG!!
使用多态
class Animal
{
public:
virtual Noise warningNoise() = 0;
virtual Noise pleasureNoise() = 0;
};
class Cat: public Animal
{
// Compiler forces you to define both method.
// Otherwise you can't have a Cat object
// All code local to the cat belongs to the cat.
};
通过使用多态性,您可以测试 Animal 类.
然后分别测试每个派生类.
By using polymorphism you can test the Animal class.
Then test each of the derived classes separately.
这还允许您将 Animal 类(因更改而关闭)作为二进制库的一部分.但是人们仍然可以通过派生从 Animal 标头派生的新类来添加新的 Animals(Open for extension).如果所有这些功能都已在 Animal 类中捕获,那么所有动物都需要在发货前定义(已关闭/已关闭).
Also this allows you to ship the Animal class (Closed for alteration) as part of you binary library. But people can still add new Animals (Open for extension) by deriving new classes derived from the Animal header. If all this functionality had been captured inside the Animal class then all animals need to be defined before shipping (Closed/Closed).
这篇关于多态性或条件会促进更好的设计吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:多态性或条件会促进更好的设计吗?
基础教程推荐
- C++定义类对象 1970-01-01
- end() 能否成为 stl 容器的昂贵操作 2022-10-23
- 初始化变量和赋值运算符 1970-01-01
- 分别使用%o和%x以八进制或十六进制格式显示整 1970-01-01
- 使用scanf()读取字符串 1970-01-01
- C++输入/输出运算符重载 1970-01-01
- C++按值调用 1970-01-01
- C++ #define 1970-01-01
- C语言访问数组元素 1970-01-01
- 明确指定任何或所有枚举数的整数值 1970-01-01