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:moss@makingcodespeak.com>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', 'moss@makingcodespeak.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('moss@makingcodespeak.com')
# 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('moss@makingcodespeak.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.