Stop class oriented programming

Hi folks,

It has been a long time without writing anything here, so I thought it was about time say hi by sharing my views on something I've been "fighting with" lately.

This article is about a very dangerous but common "pattern" I've seen many times around TAs/TDs using classes as containers/namespaces for the code at hand (why not functions? I have no idea). So instead of have handy classes defining behavior, you can see plenty of code implementing the entire thing directly on an uniquely instanced class, prefixing everything with self without even noticing what are we pushing to the next guy consuming our code.

Let's be clear about this, the whole idea behind Object Oriented programming (like it or not) is based on the state (a.k.a. data) belonging to the instance while the behaviour (a.k.a. methods) being defined in the class.

That's object oriented in a nutshell, you define a type implementing certain behaviour (like a builtin str or list does!) and then create multiple instances storing different states. You rarelly save the state at a class level unless you really have a good reason to do it (yeah... there are plenty of valid reasons to do it, but you know what I mean).

But Cesar, everybody knows that...

Are you sure?

Take an honest look at your GUI code (qt, anyone?)... if you are like the average TD out there, I bet you are subclassing a mainWindow/dialog to add widgets AND set its state inside the class instead of creating "templates" to be used outside your "container".

What about your rigging system? anim tools? (or whatever you develop in your field).

Fair enough... but what's wrong about using classes as containers?

There's absolutely nothing wrong with it as long as you know what you're doing!

Think about what happen to the next guy trying to reuse your code, are there ways to redefine simple things without subclassing?

Do you imagine if the only way to create a str were via subclassing?

class HelloWorld(str):
    def __str__(self):
        return "Hello world!"

print(HelloWorld())


# oh, do you want to change it? sure!
class HelloCesar(HelloWorld):
    def __str__(self):
        return "Hello Cesar!"

print(HelloCesar())

# I would rather prefer this version
print("Hello world!")

That's exactly what happens when we create classes as containers without providing proper interfaces or thinking much about making it generic!

If anything, I think it's fair to say it's not a good default as it leads to extremelly specific classes and lack of a proper interfaces to consume your code. It also leads to tons of boiler plate, as the keyword class somehow loss its value and people stop thinking about being generic, at the end of the day you force everyone wanting to reuse your code to sublclass and overload/extend most of the methods.

I'm not saying you shouldn't be using classes, classes are a powerful tool, but be aware that each time you type class you're defining a new type! it's a very powerful tool that need to be used wisely.

So, what about you?

Have you seen this kinda code before? (unittest!?) What do you think about it? Am I the only one seeing it as a problem?

I would love to read your thoughts on the comments below... don't be shy! :)

Cesar


Questions? Comments?

Please feel free to ping me on twitter or send me an email, I would love to hear from you!