[Tutor] code smells: Object-orientation Abusers: switch statements

Danny Yoo dyoo at hashcollision.org
Sun Jan 5 04:19:13 CET 2014


Compare:

###############################################
class Dog(object): pass
class Cat(object): pass
class Cow(object): pass

def sayHi(animal):
    if isinstance(animal, Dog):
        print("Woof")
    elif isinstance(animal, Cat):
        print("Meow")
    elif isinstance(animal, Cow):
        print("Moo")
    else:
        raise ValueError("animal doesn't know how to greet")

sayHi(Dog())
sayHi(Cat())
sayHi(Cow())
###############################################


where there are explicit type tests.  The decision-making here, the
flow of control, is explicit in the structure of the sayHi() function.


Now compare that versus the following:

###############################################
class Dog(object):
    def getGreeting(self): return "Woof"

class Cat(object):
    def getGreeting(self): return "Meow"

class Cow(object):
    def getGreeting(self): return "Moo"

def sayHi(animal):
    print(animal.getGreeting())

sayHi(Dog())
sayHi(Cat())
sayHi(Cow())
###############################################

You should see similar behavior.

But the control flow here is more implicit: it's not all apparent from
the structure of sayHi(): sayHi() looks like straight-line code.  The
decision-making hides in the type of the animal.  The flow of control
jumps from sayHi() to the getGreeting() of the particular animal, and
then finally back to sayHi() to do the printing of the greeting.


One of the values of this latter approach is that it's easier to add
more animals without having to rewrite sayHi().  For example, we can
introduce a Crow:

################################
class Crow(object):
    def getGreeting(self): return "Kaaa"

sayHi(Crow())
################################

and sayHi() can deal with it just fine.  In the first approach with
the explicit type tests, we'd have to modify sayHi() to let it handle
Crows.


More information about the Tutor mailing list