Objection

RSS

Programming like a pirate (Alt + Shift + M)

Have you seen uncle Bob do his thing? I’ve just been watching a couple of episodes of CleanCoders. Great entertainment and so many good points.  Well worth it.  I really like uncle Bob.  What a guy.  The world of software development really wouldn’t be the same without him.  Those who know me know where this is headed already, don’t you - there is a big ‘BUT’ coming up.  You’re right.  

I was properly introduced to his coding style ideas at a TDD and refactoring course several years ago.  2007 or 2008 maybe? And like the conscientious craftswoman I try to be, I really have done my best to follow his advice.  Because I believed in it, not because I was forced to. Small readable functions. No more than 4-5 lines long.  Extract til you drop.  And after a few years of doing this I still agree that 

if (isTestPage())

  surroundPageWithSetupsAndTeardowns()

is easy to read.  The intent is indeed clear.  But while it may be readable, it’s not readable code - because there is no code there. The person who is satisfied with reading that, has no reason to be looking at it in the first place.  Surely code should give you more than what the post-it note on your scrum board said you should be doing. 

When I’m looking over a class to see if it might be useful, then I look at the public methods, their names, input parameters, return values and maybe their javadoc comments if there are any.  These names had better display the intent.  Here I fully agree with uncle Bob.  Having to look inside a method to see what it does, is in many cases a failure of method naming. BUT - once I’m having a look, to see how it is implemented, then that’s exactly what I want to see; how it is implemented.  Think about this, in your experience - why do go have a look at the implementation of a method? Either you need to change it somehow, or it isn’t behaving as you thought it would.  Maybe your input parameters aren’t right, maybe there is a bug somewhere, in any case you need to figure out what this method does.  In this scenario, there is nothing more annoying than a 4 line method that simply delegates on to 3 other methods, classes or worse; interfaces.  Now, instead of looking in one method, there are 3 other places to look. And each of those places delegates on to three more - and so it goes ad nauseum.  It’s like treasure map written by a malevolent pirate with ADHD.  Instead of having one 40-line method to look through, you have to search through 40 classes and 60 methods.  And by the time you’ve come to the end of one search branch, you’re way down in someone else´s framework code and have trouble remembering what brought you there in the first place.

Uncle Bob talks about how code should read like well written prose.  Sure.  But this 4-line method nonsense reads nothing like well written prose. It reads like endless tables of contents.  And while there is nothing wrong with tables of contents,  you don’t want your book to be full of nothing else! When you look at the table of contents and think chapter 5 looks interesting, you don’t want chapter 5 to simply be another table of contents - which in turn links to a third table of contents etc.  That’s not well written prose. That’s a manifestation of some weird form of obsessive compulsive disorder.  No one would say that a book like that was very readable.  

Let’s take a look at some well written prose then, a random Shakespeare quote:

  My crown is in my heart, not on my head, 

  Nor decked with diamonds and Indian stones, 

  Nor to be seen: My crown is called content:

  A crown it is, that seldom kings enjoy.

What? Crowns in your heart? Ouch! Why would a king, any king enjoy that?   And why have you given it a name? What a looser!  He’s speaking figuratively? What is that - like a dialect or something? Look I speak plain English - OK? Speak your ‘figuratively’ to someone else.

That there is what we call sarcasm.  It’s one of the things we learn about in English class.  You see, in school we’re taught how to read.  We are given loads of different texts from different eras, different authors with different styles of writing.  We’re taught how to interpret the texts and how to understand and appreciate them.   If you don’t understand Shakespeare, it’s not because his writing is bad.  It’s because your education is lacking.  You don’t have to like every writing style, but at least after a university degree in literature, you should be able to understand them.

Did you ever learn how to read code at university? Were you shown loads of different code, in different languages and different styles, and then asked to explain what the code did? I don’t think code comprehension is a normal part of the curriculum for computing science classes. We’re taught how to write, not how to read. Maybe that’s a mistake.  

Back in the old days newbies would be embarrassed to admit that they didn’t quite understand the implementation of a method.  Nowadays, it’s not their fault - it’s the person who wrote the code who’s to blame.  Always.  Today code should be written for people who don’t know how to read.  The best programmers are the ones who can turn this:

  “Get order history for a customer”

into this:

  List<Order> getOrderHistoryForACustomer()

Only a true software professional could write something that brilliant.  Who cares how it is implemented, after all, the most important thing is that people who don’t understand code should understand it.  Right? 

Look, I’m not saying code should be hard to read.  I commend uncle Bob and the rest for getting us to work on our writing skills, but writing well is only half the solution towards readability. We need to work on our reading skills as well. And frankly I don’t think they are as bad as Bob would have us believe.  What programmer could fail to understand the intent behind this if statement (from one of his CleanCoders videos):

  if (page.hasAttribute(“Test”)) {…

It’s obvious that we’re checking whether or not the page is a test page.  Refactoring it into 

  if (isTestPage()) { …

is ridiculous and condescending.  Who does he think his audience is? I know we’re known as code monkeys, but come on!  I’m offended.  If isTestPage() is a public method, then it’s ok, but not otherwise.  page.hasAttribute(“Test”) not only shows you the intent, it also shows you the implementation.  This is a good thing!  If the predicates get more complicated than this, then I agree that extracting them is a good idea. But into a local variable, not a separate method.  This way the intent (variable name) and the implementation are right there, in line, you don’t have to context switch out to a separate method to find out how the boolean expression is evaluated. 

Another problem I’ve noticed with this extract til you drop programming is that people stop cleaning up their code.  If something looks complicated, the complexity gets “solved” by extracting the various parts out into separate methods. Except that extracting into separate methods doesn’t solve anything. It simply hides the ugliness.  It’s like throwing a pretty rug on top of that slice of pizza on the floor.  Less work than cleaning, looks just as good. Your guests think they are entering a nicely kept house, but all the while they are stepping on old pizza and ice cream.  Before long the house is infested with rats and the stench becomes unbearable.  But you didn’t see it coming, because those rugs were so pretty.  

I’ve had quite a lot of fun recently, inlining methods and seeing the resulting code.  Sometimes it’s a LOT easier to read, no more context switching- you read the code from top to bottom as it will be executed.  Sometimes it is a big eye-opener, the same thing is done over and over again, but you never noticed before as it was done in so many different places. Sometimes it makes you want to cry, as the code is so embarrassingly bad.  I recommend you give it a try.  If a method is only called from one place - I’d say it’s worth looking into inlining it.

Oh, but what about the my tests for all of those methods? you ask.  Delete them, I say. You don’t need a unit test for every thinkable unit of your code. You need to test the functionality that matters. Read this if you’re not convinced.

"Make things as simple as possible, but not simpler" a wise man once said.  Some things just aren’t as simple as we’d like them to be.  A 4-line method is always easy to read.  But not all problems can be solved in 4 lines of code. Most problems require quite a bit more, and seeing a bit more of the full picture at a time can actually make that problem easier to solve and understand.  Puzzles get harder and harder, the more pieces they contain.  Same goes for code.  

Why don’t you give it a try - dare to enlarge your methods a bit.  Dare to show some code in your code.  You might like the results.