On Muted Methods, Fluent Interfaces, and Bar Game
One night a weekend back I went out to the local bar back home with my younger sister some of our friends. Back home means Rutherfordton, North Carolina. The kind of charming area that greets you at the county line with the road sign "Welcome to Rutherford County, Small Town Friendly". A friendly place, it is.
While sitting at the bar one of my sisters' friends drew a lot of attention from the gentlemen of Rutherford County. We'll call her Liz (gah, when does 30Rock start up again??). Some would come up and chat, others ask for a dance. The most peculiar case of them all was one who had been ordering drinks from across the bar and finally got up the courage to come over and, without a word, slip Liz a piece of paper with his phone number on it before disappearing into the night.
Yes, this post is about programming, bear with me.
Let's give this guy, say Dennis, the benefit of the doubt and assume that these tactics have worked before with success. On this particular night with a gorgeous girl from out of town: no dice. Dennis wouldn't get the callback.
Let's pseudo-code this scenario:
$liz = new AttractiveOutOfTownGirl(); $dennis = new SmallTownFriendlyYoungMan(); $liz->setDrink($dennis->buyDrink('Vodka Redbull')); $liz->setDrink($dennis->buyDrink('Sex on the Beach')); $liz->receiveNumber($dennis->getPagerNumber()); $dennis->disappearIntoTheNight();
Spot any patterns? Thrice Dennis has taken an action that results in some value: he's bought 2 drinks and retrieved his pager number. All of his methods have resulted in some value that is handed to Liz and he's getting no acknowledgement back. He interacted with muted methods. Dennis' shot at success depended on Liz having some internal, finite state machine that transitioned from "stranger" to "stranger willing to call a stranger" with every additional drink. How could this have gone better for Dennis?
Before we get there let's talk about muted methods. Procedures. Voids. Black holes in programs where input results in no output. Scary stuff! But why, what's so bad about muted functions? Let's nitpick our example. It is so choppy. Do you feel the choppiness?
Noun verb. Noun verb. Noun verb. Liz set drink. Liz set drink. Liz give number.
When your verb is muted, there's nothing more to be said. End of story. Next line. You've got nothing to play off of, no chance to converse. When you're working with muted functions you have no segue. You're giving without receiving.
If muted functions are the problem, how could this scene look a little less ugly? Perhaps Dennis could have conversed with Liz. Interacted with her. Made use of a more fluent interface...
$dennis->saysTo($liz, "Hey girl, from out of town?") // returns $liz ->saysTo($dennis, "Yes, how'd you know?") // returns $dennis ->saysTo($liz, "Never did seen you before!") // returns $liz ->isStillSmiling() ? // If she's smiling $liz->setDrink($dennis->buyDrink('Vodka Redbull')) // returns $liz ->saysTo($dennis, "Thanks, you're kind of cute.") ->saysTo($liz, "That's how we're grown here. Can I call you?") ->saysTo($dennis, "Sure, my name is Liz and the number is...") ->punchesInNumber("919-928-9090") // returns $dennis ->says("Great, call you tomorrow!") // returns $dennis ->disappearIntoTheNight() : // If she's frowning $dennis->movesAlong();
When you're not dealing with muted methods you give your code the chance to come to life in a more fluid, fluent way. There's only sentences here, it's just longer, richer, and more involved. There's magical, programmatic banter happening here!
This style of object-oriented interface, where method chaining and thoughtful return values enable a pseudo-domain specific language written entirely in a general purpose language, has been called a "Fluent Interface" by Martin Fowler and Eric Evans. It's an inspiring departure from the days of the void, black hole methods like setters.
So, next time you're writing an interface for some new class, or sitting at a bar wondering how best to approach that attractive member of the opposite sex, avoid muted methods at all costs. They're black holes. They're just awkward, feedbackless, and overall uncomfortable for everyone involved.
When your functions or methods don't return ask yourself "if I were to return something here what would be useful?" Most often, it's a reference to the object itself. Or an immutable clone.
"Oh, god no, not an immutable clone! I thought this article was about bar game?" Hmm... you're right. I'll save the immutable clone wars for another post. You should subscribe to this RSS feed if immutable clones pique your interest. Or nerdy bar game.