The worst method naming convention Object-Oriented programming is set{Thing}()
. And no, C# doesn’t escape my ire for calling it Set{Thing}()
, nor does Smalltalk for calling it {thing}:
, though that does handily demonstrate how meaningless set
is.
OK, so set isn’t really meaningless. In fact, it’s got the opposite problem: entirely too many meanings. Luckily, when we use set in a programming context, we only mean exactly one of those definitions.
Oh wait, there’s that whole unordered collection thing, too. Two meanings.
And the electrical engineering definition of “making the voltage high”, so there’s three I suppose.
And the arrangement thing, like preferences (“settings”) or big scale configuration (“set up”). Four.
So, let’s all put on the blinkers of bean-fuelled tradition, and assume that when we see set
at the beginning of a method we refer to putting something into a specified state. Probably without that digression you would have thought a method starting with the word set
would do that anyway.
So far, so Kevlin Henney. “Set” really is a bad word to choose. But now let me ask two questions, which happen to be degenerate in verbal content: why am I setting this state?
Why am I setting this state?
Aren’t data hiding and encapsulation important principles in object-oriented programming? Why should you let me, an unrelated object, diddle with your state? Why not, you know, let me send you commands and queries?
Also, there’s the single responsibility principle. Why do I have information when you’re the one who needs it? Perhaps I should have asked you to work out the new thing rather than doing it myself and telling you my answer. Of course objects often do need to pass one another information: software systems wouldn’t be very interesting if data didn’t flow around them. This leads me on to the same question again:
Why am I setting this state?
As commands go, “set{Thing}()” really doesn’t document its purpose at all. “Here, have this thing”. Err, okay, but why do you want it? What will you use it for? Why should I care what your thing is? What use will I get out of giving you a different thing?
Here are some mutators with descriptive names:
label.setColor(red); //becomes
label.drawTextInThisColor(red);
aStreet name:'Sesame Street'. "becomes"
aStreet wasRenamedTo:'Sesame Street'.
[employee setSalary:@(75000)]; //becomes
[employee futurePayChecksShouldBeBasedOnNewSalary:@(75000)];
Notice that it’s now clearer why I’m setting these. It’s also evident that these changes tell us something about the evolution over time of the objects: the street had an earlier name, and now has this new name. The employee had a different salary for their previous pay check, and will have a new salary for their next pay check. Last month’s pay check should probably still be calculated with last month’s salary. But now the method also makes it clear that there’s a design problem anyway: why should the employee and not the payroll be where pay check information goes?
Soon after posting, the question was asked: isn’t drawTextInThisColor()
a bad name because the object might not immediately need to do any drawing? No; sending an object a message and leaving the implementation up to that object is how object-oriented programming works. If we really had to distinguish drawTextLater()
and drawTextNow()
then we’d not be doing any information hiding. Compare this with things like faults (an ORM claims that the database is in some state, when in fact it’s not yet), or even the way GUI libraries already work (you can tell a view it needs display, and the view can choose not to do anything because it’s off-screen). Object-Oriented Programming involves telling an object what you want from it and leaving the details up to that object. The set…()
convention doesn’t tell us what we want from an object.
Bonus question: Why am I setting this state?
Finally, I didn’t tell you what units the salary is in. Good catch. Give yourself a pat on the head, you’re a very special snowflake.