Alex Rivera | Logout

Do polymorphism or conditionals promote better design?

Asked 2008-10-24T17:19:46.617
42

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?

Edit
Report

3 Answers

26

Do not fear...

I guess your problem lies with familiarity, not technology. Familiarize yourself with C++ OOP.

C++ is an OOP language

Among its multiple paradigms, it has OOP features and is more than able to support comparison with most pure OO language.

Don't let the "C part inside C++" make you believe C++ can't deal with other paradigms. C++ can handle a lot of programming paradigms quite graciously. And among them, OOP C++ is the most mature of C++ paradigms after procedural paradigm (i.e. the aforementioned "C part").

Polymorphism is Ok for production

There is no "subtle bugs" or "not suitable for production code" thing. There are developers who remain set in their ways, and developers who'll learn how to use tools and use the best tools for each task.

switch and polymorphism are [almost] similar...

... But polymorphism removed most errors.

The difference is that you must handle the switches manually, whereas polymorphism is more natural, once you get used with inheritance method overriding.

With switches, you'll have to compare a type variable with different types, and handle the differences. With polymorphism, the variable itself knows how to behave. You only have to organize the variables in logical ways, and override the right methods.

But in the end, if you forget to handle a case in switch, the compiler won't tell you, whereas you'll be told if you derive from a class without overriding its pure virtual methods. Thus most switch-errors are avoided.

All in all, the two features are about making choices. But Polymorphism enable you to make more complex and in the same time more natural and thus easier choices.

Avoid using RTTI to find an object's type

RTTI is an interesting concept, and can be useful. But most of the time (i.e. 95% of the time), method overriding and inheritance will be more than enough, and

answered 2008-10-24T19:48:49.313
1

This is mainly to do with encapsulation of knowledge. Let's start with a really obvious example - toString(). This is Java, but easily transfers to C++. Suppose you want to print a human friendly version of an object for debugging purposes. You could do:

switch(obj.type): {
case 1: cout << "Type 1" << obj.foo <<...; break;   
case 2: cout << "Type 2" << ...

This would however clearly be silly. Why should one method somewhere know how to print everything. It will often be better for the object itself to know how to print itself, eg:

cout << object.toString();

That way the toString() can access member fields without needing casts. They can be tested independently. They can be changed easily.

You could argue however, that how an object prints shouldn't be associated with an object, it should be associated with the print method. In this case, another design pattern comes in helpful, which is the Visitor pattern, used to fake Double Dispatch. Describing it fully is too long for this answer, but you can read a good description here.

answered 2008-10-24T17:39:45.267
0

If you are using switch statements everywhere you run into the possibility that when upgrading you miss one place thats needs an update.

answered 2008-12-13T19:26:21.193

Your Answer