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
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
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! :)