I recently tried to tweet about an idea that doesn’t remotely fit into 140 characters.
Becoming convinced that the wordiness of class definitions in most languages is a major force working against good object-oriented design.— Moss Collum (@moss) January 9, 2014
I’d like to expand on that.
First, consider the old saying “objects are merely a poor man’s closures”, or, “closures are merely a poor man’s object”. Closures and objects are both part of an evolutionary sequence that code can take:
- First, I have a value that doesn’t change, so I simply assign it to a name.
- Then, I discover that it may change based on certain conditions, so I create a function.
- Then, I discover that some of the parameters of the function are available independently of others, so I partially apply the function and return a closure.
- Then, I discover that there are different things I might want to do to the initial bundle of data, so I replace the closure with an object.
Conceptually, each of these steps is very small. But in every language I know, the last step adds more code than any of the others, and with it more mental overhead and more maintenance burden. Consider Python:
# assignment email_link = '<a href="mailto:firstname.lastname@example.org>Moss Collum</a>' # function def make_email_link(first_name, last_name, email): '<a href="mailto:%s">%s %s</a>' % (email, first_name, last_name) email_link = make_email_link('Moss', 'Collum', 'email@example.com') # closure (though briefer alternatives are available) def linkable_name(first_name, last_name): def make_email_link(email): '<a href="mailto:%s">%s %s</a>' % (email, first_name, last_name) return make_email_link make_my_email_link = linkable_name('Moss', 'Collum') email_link = make_my_email_link('firstname.lastname@example.org') # but object... class LinkableName: def __init__(first_name, last_name): self.first_name = first_name self.last_name = last_name def make_email_link(email): '<a href="mailto:%s">%s %s</a>' % (email, self.first_name, self.last_name) my_name = LinkableName('Moss', 'Collum') email_link = my_name.make_email_link('email@example.com')
Is all this extra visual noise really worth the flexibility we get for it? Why not drop the constructor, and instead explicitly make a class conceptually more like a closure?
# syntax from some hypothetical future language -- do not attempt class LinkableName(first_name, last_name): def make_email_link(email): '<a href="mailto:%s">%s %s</a>' % (email, first_name, last_name)
Besides being shorter, this is more readable (to my eye, at least), and also closer to the earlier stages in its evolution, making it a more natural jump for somebody who’s trying to decide how to refactor their code.
So, is there something big that I’m missing? Why don’t more languages have a syntax like this for defining classes? If you’ve got any thoughts, perhaps you can guess where to email me.