多态性还是条件性促进更好的设计? [英] Do polymorphism or conditionals promote better design?

查看:117
本文介绍了多态性还是条件性促进更好的设计?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近偶然发现了 google测试博客中的此条目关于编写更多可测试代码的准则。我同意作者,直到这一点:


在条件语句中使用多态性:如果你看到switch语句,你应该考虑多态性。如果你看到同样的if条件在你的类中的很多地方重复,你应该再次考虑多态性。多态性将把你的复杂类打破成几个更小的更简单的类,它清楚地定义了哪些代码段是相关的并且一起执行的。这有助于测试,因为更简单/更小的类更容易测试。


我可以理解使用多态而不是RTTI(或DIY-RTTI,视情况而定),但这似乎是一个广泛的声明,我不能想象它实际上被有效地用于生产代码。在我看来,更容易为有switch语句的方法添加额外的测试用例,而不是将代码分解成几十个单独的类。



另外,我的印象是,多态性可能导致各种其他微妙的错误和设计问题,所以我很想知道这里的权衡是否值得。

解决方案

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

如果你有一个基于内部字段的switch语句,你可能在多个地方有同样的开关做一些不同的事情。这会导致问题,当你添加一个新的案例,因为你必须更新所有的switch语句(如果你可以找到它们)。



通过使用多态,你可以使用虚函数得到相同的功能,并且因为一个新的案例是一个新的类,你不必搜索你需要检查的东西,它是每个类都孤立的代码。

  class Animal 
{
public:
Noise warningNoise();
Noise pleasureNoise();
private:
AnimalType类型;
};

Noise Animal :: warningNoise()
{
switch(type)
{
case Cat:return Hiss;
case狗:return Bark;
}
}
Noise Animal :: pleasureNoise()
{
switch(type)
{
case Cat:return Purr;
case狗:return Bark;
}
}

在这种简单的情况下,要更新的语句。

您忘记了一个语句?什么是默认值? BANG !!



使用多态性

  class Animal 
{
public:
virtual Noise warningNoise()= 0;
virtual Noise pleasureNoise()= 0;
};

class Cat:public Animal
{
//编译器强制您定义两个方法。
//否则你不能有一个Cat对象

//所有本地的代码都属于cat。

};



通过使用多态可以测试Animal类。

然后测试每个



这也允许你发送Animal类( Closed for alteration )作为二进制库的一部分。但是人们仍然可以通过派生自Animal标题的新类来添加新动物(打开以供扩展)。如果所有这些功能都在Animal类中被捕获,那么所有的动物都需要在发货前定义(关闭/关闭)。


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:

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.

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.

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;
    }
}

In this simple case every new animal causes requires both switch statements to be updated.
You forget one? What is the default? BANG!!

Using polymorphism

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.

};

By using polymorphism you can test the Animal class.
Then test each of the derived classes separately.

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).

这篇关于多态性还是条件性促进更好的设计?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆