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.
- 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.
- 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.
- I commit, merge and push my code frequently. I am part of the teams’ build cycle, and on the same branch.
- 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.