Our Blog

Warning! Coderoaches!

Imagine a cool startup place. It has top notch working stations, huge monitors, the latest keyboards. Programmers have open cheques to choose their workstations: Mac Pro, Symphonia, ThinkStation – you name it, you got it. Vintage Pinball and Pacman machines alongside Xbox One and PS4 Pro. You know, The Works.

You also see pizza trays and noodle boxes laying around. Some of them two weeks old. A bit of mold here and there. There are marshmallows and jelly beans on the floor, clearly walked over numerous times, scores of ants are nibbling at them. Well, you get the picture. It’s a cool startup, but also dirty and in great neglect.

Rarely a startup’s physical environment looks like that. But all too often the codebase does. In startups, in medium sized companies, and most notably in mature, well established products, typically in large organizations.

It’s kind of funny that when I meet highly skilled programmers, exhibiting clean coding, they tend to say that they “get their hands dirty”. Well, I guess that is also the case when you clean your home you wash your hands once you are done, don’t you?
As for the not-clean-coders, it’s not that they intend to write bad code. Nor do they like bad code. It’s just that they don’t have the habit of writing code hygienically. Like the pizza trays in the office, they either expect someone else to take care of it, or they just don’t notice that it’s there.

Here’s an example of hygienic coding habit. It’s not the only way, just one possible example. Let’s say that I picked a task to complete: Enhance Foo.Bar(pub) to validate that pub is a good bar for foo to go into.
I would:

  1. Inherit FooSub from Foo, and do all my changes on it, until it’s safe to merge back into Foo. Meanwhile, all existing tests pass and all my teammates can safely work on their code.
    I write my tests on FooSub so long as I am in my development cycle.
  2. I override Bar() in FooSub, so I can try out my changes. When I fail my tests, I undo my bad changes. When my tests pass, I continue to making my next test pass.
  3. I commit, merge and push my code frequently. I am part of the teams’ build cycle, and on the same branch.
  4. Once I am happy that the task is complete, I merge my changes in Bar() into Foo. Again, if I merged correctly, all tests pass. Otherwise, I undo last change and retry.

Michael Feathers has a nice example for this in Working Effectively With Legacy Code, chapter 8, “How Do I Add a Feature?”
This book, by the way, is a must for clean coders that want to disinfect their code from coderoaches.

Seem like a lot of extra motions for just a few code changes, doesn’t it?
Yes, it does. So is washing your hands after you visit the loo, or adjusting your seat and mirrors as you enter your car, or bringing all the right tools before you change a fly-net on your window. You can do without these steps, and, in most cases, you might come out OK. But the once-in-a-while dissenteria, car crash or ruined fly-net frame is so costly that you dare not skip the mundane “overheads”.

Also, the more complex and the more error-prone the domain, the more you should practice safety measures as you progress.
Take medicine, for example. Would you trust a doctor who doesn’t wash her hands? A nurse who’s careless with his sterile tools? Of course not!

In The Checklist Manifesto, Atul Gawande distinguishes between two types of errors we make:
Errors of ignorance – mistakes we do because we don’t know enough, and errors of ineptitude – mistakes we do because we fail to do what we know.

Heck, if you read text messages while you drive – you are a bad driver – you exhibit ineptitude – you ignore available knowledge suggesting that you are a danger to yourself and to fellow drivers. Needless to say you are much worse if you’re also typing text messages while driving.

In the same token – you exhibit ineptitude as a programmer if you do not: refactor frequently, cover your code with high percentage of unit tests, build frequently (including tests, of course), and measure your code with static code analysis.
I can’t stress enough how important is learning (for example from books like Working Effectively With Legacy Code) for programmers to develop their own competence.

If you don’t, you probably have all kinds of old pizza trays and sticky marshmallows in your code. The kind that attract coderoaches. The kind that, eventually, you might need to call in pest control and a cleaning agency, shut down your code scene for a while until you get rid of some coderoaches, and only then get back to the now clean code.
And hopefully keep it clean and hygienic with tests and all.

Image source:
Cockroach and Binary code

  • James Coplien

    Ne quin nimis. This is all true in degree. If I go into a company with a clean desk policy and the offices and hallways are devoid of decoration, family pictures, and Dilbert cutouts, I know I would never want to work or consult there. If a company enforces rigorous standards for variable naming, for code comments, and the like, it raises a red flag that the broader workflow constrains the developer.

    It also depends on context. In some cases software is actually soft. If a company has the discipline to throw away prototypes, it can be a waste of time being overly strict on the cleanliness of one’s code. Steve Johnson in his book “Where Good Ideas Come From” notes that a messy, noisy environment is not just a sign of innovation, but is one of its major enablers. So if I see a bit of messiness I get this feeling of a relaxed, informal, effective environment. If everything is squeaky clean, I feel rigor and even fear that limit innovation. Sometimes it *does* make sense to inherit FooSub from Foo if the alternative is even more onerous.

    Leonard Cohen says, “There is a crack in everything / That’s how the light gets in.” There is something very deep going on here and there lies a trap in preoccupation with form over function. By way of playful analogy, Michael Lev in “A Pathwork of Time” (Chidushei Torah, NDS, June, 2003) notes a deep interplay between “wholeness” and “perfection” and notes that the two are not the same: “… we must first examine the Torah’s understanding of `wholeness.’ Does wholeness always imply one hundred percent perfection, or perhaps ninety-eight percent can be called `whole,’ if no other choices are available. Or, perhaps, one hundred percent, minus a little, can be called ‘whole,’ even in an ideal situation?” He gives several examples from Torah. We find similar notions in other belief systems, in formal physics, in architecture, and in life.

    So while I’m an advocate of clean code — I wrote the foreword to the book — I can see where someone reading this article with the wrong eyes could easily be led to do the wrong thing. As the research shows, being overly focused on order kills innovation.

    • Ilan Kirschenbaum

      Great feedback, thanks!. Yes, I can see how one can misread the article as code should be like a clean-room. While writing the post I saw in my mind the overly neglected code that we meet all too often – the equivalent of the stale pizza trays mentioned in the opening.
      I agree that some untidiness is a good sign that people are actually alive, and not just code-robots. The being over meticulous with practices can become a kind of a “fetish” in itself, instead of producing software that solves real problems.
      I long for the day that these will be our problems 🙂

    • Itsik Saban

      Great point.

      My moto is: aim for perfection, but don’t expect to hit it.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 4 other subscribers

Comments