I have seen posts on hackernews on the topic that Object Oriented Programming (OOP) sux. These are stratospheric considerations. OOP does not sux on a theoretical point of view it sux in real life.
Guh! Don't I like python? Yes I do. But what I hate is not really OOP. It is monkey developers that care about OOP and not about coding.
Coding is like kicking a problem in the nuts. Some problems get kicked in the nuts by OOP, some don't. People that don't understand deserve a slow and painful death by enucleation with a plastic spoon.
To make myself clear:
- I am gonna make a short theoretical statement about what is wrong with some devs;
- a short practical code review of a code that pisses me off.
OOP sux as much as developers that don't know how to code.
It is indeed true that I am old school. The data structure is more important for me than the workflow or algorithms. And I do hate OOP for mixing both when it's done poorly.
A good object is for me data with multiple views.
And there is a signature for poor OOP:
- code that should be better written as a script;
- code that has strong coupling;
My code sux!
Sometimes I am too lazy to write code, so all permissions granted I reuse other's code. Pypi-stat (a package of mine) and I suffered my laziness.
Rule 1: all code that could be written as a function should be written as such
If you watch https://github.com/jul/pypi-stat/blob/master/pypi_get_stat.py#L206 you'll notice that the borrowed code is called this way:
When you see this, don't think: this a script disguised as an object.
By the way, what is the problem to solve? Given a package name, I want all the stats given by an RPC call to pypi in the form of a dict.
Basically I want to :
- fetch the stats;
- transform them;
__init__ -the constructor- is stragthforward, it is initialisation. So you expect stats to be easy too.
Well, cry with me lads and wenches.
def stats(self): """Prints a nicely formatted list of statistics about the package""" self.downloads # explicitly call, so we have first/last upload data ...Wut?!
Rule 2: when you need to call methods or properties in a defined order so that it works, you have a coupling problem
Why do I ask a property I don't use at your opinion?
Because, the property is processing hidden states and coupling are on their way.
@property def downloads(self, force=False): """Calculate the total number of downloads for the package""" if len(self._downloads) == 0 or force: for release in self.releases: urls = self.proxy.release_urls(self.package_name, release) self._downloads[release] = 0 for url in urls: # upload times uptime = datetime.strptime(url['upload_time'].value, "%Y%m%dT%H:%M:%S") if self.first_upload is None or uptime < self.first_upload: self.first_upload = uptime self.first_upload_rel = release if self.last_upload is None or uptime > self.last_upload: self.last_upload = uptime self.last_upload_rel = release self._downloads[release] += url['downloads'] return self._downloads
downloads is not a property, it is a method doing processing and setting internal properties on the way. So is releases. This stuff that by conventions are stateless (properties) do modify the state of the freaking object. Thank you man! When reading this kind of code where inert stuffs (properties) is active I feel like a rabbit trapped in a dense mine field.
What the heck?
So at one point, I decided I was not reading or improving this «easy» code. I just put a rant in the comments about how much I hate stupid OOP developers.
This very straight forward code has therefore a coupling (you can't call stats without accessing the downloads property because it silently mixes up code and processing, with some states logics).
That's what make script coders like I hate OOP.
The workflow is not sequential (it jumps from part of the code forward and backward), and data are not processed sequentially. It is not code, it is Snakes and Ladders.
That is the reason I hooked my save method on stats: this code was a maze and I knew the entry point was the constructor and the end point was the stats method. I am weak, I know.
OOP is not bad if you fear Alzeihmer and want to train your brain to most astonishing logics.
With poor coders object oriented programming is like taking acids with the mad hatter. Pretty intellectually stimulating, but not very efficient.
Still I think that whatever the paradigm used, this coder would have done code «looking» academically nice, but definitively wrong. Coding is not about following what is written in a book about OOP or functional or imperative programming.
It is about making a complex problem look simple, not the opposite.
EDIT: Very good Pycon talk on the topic