c++ - 多态性或条件会促进更好的设计吗?

标签 c++ oop tdd polymorphism

我最近偶然发现了 this entry in the google testing blog关于编写更多可测试代码的指南。在此之前我一直与作者达成一致:

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 语句的方法添加额外的测试用例比将代码分解成几十个单独的类更容易。

另外,我的印象是多态性会导致各种其他微妙的错误和设计问题,所以我很想知道这里的权衡是否值得。有人可以向我解释一下这个测试指南的确切含义吗?

最佳答案

实际上这使得测试和代码更容易编写。

如果您有一个基于内部字段的 switch 语句,那么您可能在多个地方使用相同的 switch 执行稍有不同的操作。这会在您添加新案例时导致问题,因为您必须更新所有 switch 语句(如果您能找到它们)。

通过使用多态性,您可以使用虚函数来获得相同的功能,并且由于新案例是新类,您不必在代码中搜索需要检查的内容,因此每个类都是隔离的。

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 语句。
你忘了一个?什么是默认值?砰!!

使用多态

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 类。
然后分别测试每个派生类。

这还允许您将 Animal 类(因更改而关闭)作为二进制库的一部分。但是人们仍然可以通过派生从 Animal header 派生的新类来添加新的 Animals(Open for extension)。如果所有这些功能都已在 Animal 类中捕获,那么所有动物都需要在发货前定义(已关闭/已关闭)。

关于c++ - 多态性或条件会促进更好的设计吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/234458/

相关文章:

C++ 随机数生成 : Generate cos squared function

javascript - 在控制台中定义一个 JavaScript 对象

python - fatal error : pathspec did not match any files using git rm to remove the pyc file

c++ - 保存更改后,如何使 XCode 4 自动构建和运行代码?

c++ - dijkstra 实现给出了错误的输出

c++ - 为什么在比较 time_t 值时我的 While-Loop 不停止?

c++ - 读写二进制文件

python - 最佳实践 : update/extend subclass class attribute

c# - C# 中静态构造函数不能有返回类型,但静态方法必须有返回类型

c# - 在 TDD (MOQ) 中使用模拟的最佳实践