TDD is Debugging Features Into Existence

Two books I’ve read recently, Making Software and Beyond Legacy Code, have touched on Test Driven Development and made some interesting points I hadn’t thought of before. In Making Software they bring up addictiveness:

Could it be addictive? Personal communications with TDD developers suggest that it is an addictive practice. It changes the way people think and their approach to coding in a way that is difficult to roll back. Therefore, leaving TDD practices may be as difficult as adopting them.

Oram, Andy; Greg Wilson (2010-10-14). Making Software: What Really Works, and Why We Believe It (p. 215). O’Reilly Media. Kindle Edition.

From my personal experience and the people I’ve talked to, TDD/BDD is absolutely addictive. I’ve been lucky to experience working professionally in two completely different environments in respect to testing. For the first programming job of my career, I knew of tests and what little I wrote, I wrote in a test-after fashion. The process there was your typical: think about a problem, come up with some solution, type it in, run it, see what doesn’t work, fix that, and repeat. As you can imagine, I got very good at debugging there since that was what I spent most of my day doing.

At my next job as the second engineer at SideTour, though, the entire app had been test driven from day one. I was even able to pair full time with the CTO and learned how to do it effectively. I picked it up quickly and was immediately hooked to the point that I test drive all of my side projects as well.

Bugs Are Missing Tests

I’ve wondered for a while now how I picked up such a different process so quickly, and it wasn’t until I came across Beyond Legacy Code that it really started coming together. In the chapter “Bugs Are Missing Tests”, David Bernstein says:

Every bug exists because of a missing test in a system. The way to fix bugs using TDD is first write a failing test that represents the bug and then fix the bug and watch the failing test turn green.

Most of the writing I’ve seen around TDD and BDD explains it from a feature perspective first, but if you look at it from a bugs perspective you can easily reframe features as debugging them into existence. Once I started thinking about it like this, it makes a lot of sense why I got so hooked. Being someone that enjoys and is pretty good at debugging, it is obvious that a process which turns programming into a constant debugging session would click. It is a bug that the feature doesn’t exist, so you need to write a failing test that exposes that bug.

What Your Text Editor Can Say About You

In my role as a manager on a growing engineering team, a lot of my time lately is spent reviewing resumes and conducting phone interviews. Resumes and LinkedIn profiles leave a lot to be desired when trying to evaluate applicants, but unfortunately they’re the only things we have. It is incredibly hard to gauge where a person is in their personal development as a software engineer just from reading a one or two page document and talking for an hour over the phone. Fortunately, one strong signal I’ve found is if the candidate has Vim or Emacs listed on their resume.

An important step in your personal development as a software engineer is the realization that you need to invest time in mastering your tools. In a similar vein to Steve Yegge writing about programmers needing to know how to type, programmers also need to put the time in toward mastery of their text editor. What makes Vim and Emacs such a strong signal is that to be able to be productive in them, you have to have made the decision that you’re going to spend at least some time learning how to use them. They both have steep learning curves and could even be said to be hostile to beginners, but investing the time to completely grok one or both of them shows that you have grasped the value of learning a tool will pay itself back over your entire career.

Now I’m not saying that people who use different text editors haven’t put time in to mastering them, just that having them on your resume gives very little if any signal. When you’re applying to jobs with a resume, the person screening the resumes is likely seeing many resumes a week on top of their standard day-to-day work, and is always looking something in the resume that jumps out to them and suggests a deeper investigation.

Optimize for Debugging Speed

“If debugging is the process of removing software bugs, then programming must be the process of putting them in. ” – Edsger Dijkstra

As close as you can get to a guarantee in programming is that if you’re building a program of any kind of complexity, you’re going to be spending a lot of time debugging it. Taking Eagleson’s Law* into account, the situation is even more dire – you’re almost always debugging code that might as well have been written by someone else. How would you prefer past-you to have written code so that current-you has an easy time fixing anything that comes up? Besides writing tests, of course, you would prefer that they wrote the code to make the process of debugging as easy and fast as possible.

“ Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. ” – Brian Kernighan

The code needs to be simple and easy to understand. You can get some of the way there with tools like Code Climate, but the simplicity I’m talking about here goes beyond what static analysis can really quantify. Not only do you need to worry about the low level details of your methods and classes, but you also need to worry about your overall design. Imagine explaining the design to someone new on your team. If the explanation involves layers upon layers of  new classes, while not obviously wrong, you should probably get up and walk around a little bit asking yourself if there is absolutely no other way to accomplish what you’re trying to accomplish.

Beyond a simple overall design, think about each line you write from the perspective of someone unfamiliar with the code reading it for the first time. Consider the `try` method in rails. Any time someone encounters it being used, they now have to incorporate the thought that the caller could be `nil` and have to think about what cases that could be true. Unfortunately, the `try` method doesn’t provide any of the information needed to determine when and whether the object is legitimately null. You should write code that clearly explains to the reader why it is doing what it is doing.

Debugging time increases as a square of the program’s size.
— Chris Wenham in Physics for Programmers

To optimize for debugging speed, after taking simplicity and readability into account, you need to write as little code as possible to accomplish your task. Steve Yegge argues that size is Code’s Worst Enemy, but it is also debugging’s worst enemy. There is plenty written about brevity being the first thing to optimize for, and from a perspective of making the code as easily debugged as possible you absolutely need to focus on expressing ideas in as little code as reasonably possible.

You’re always going run into cases where, like Jeff Atwood mentions above, you’ve completely exhausted all your other options and have to write some code under duress. In these cases, just writing a small amount of code isn’t enough, there is something much more dangerous to watch our for. You need to think about the other code that people are going to need to write to interact with yours, and minimize future-code as much as possible too. Not only do you need to fight the urge to not bring new lines of code into the world, but you need to make it easy for the users of your code to do the same. If you’ve just written a small readable class that now requires all its users to write hundreds of lines of setup just to use it, you’ve still failed. You are now responsible for bringing an immeasurable number of lines of code into the world over the lifetime of the project.


* Eagleson's Law: Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.

Why All Programmers Should Play MUDs

If you’re anything like me, you’ve wished it would be possible to get better at things that make you money by playing a game. I realized recently after reading Steve Yegge’s Programming’s Dirtiest Little Secret and reflecting on where I learned to type that such a game exists. It turns out that as programmers we are lucky to have such a game. These magical games are called MUDs. I spent most of my middle school to high school years playing MUDs and still hop in to see what’s going on occasionally. I didn’t realize it until recently that I can attribute some of my success as a programmer to all the time that I put into them. They may not seem like much more than text-based World of Warcraft at this point, but that isn’t really the point of this post. The point of this post is to justify the thousands of hours I spent on them talk about how spending some time playing one can actually improve your performance on the job as a programmer.

Typing

This one is probably obvious, but MUDs force you to become a fast and accurate typist. The only way to interact with the game is through text, so you won’t survive very long if you have to look down to type out the commands to heal yourself in the middle of a fight or are constantly hitting backspace to fix typos. Your progress and success is directly tied to your typing skills and as you spend more time in-game you naturally progress from a hunt-and-peck style where you think about individual letters to thinking in blocks of words and sentences that just seem to appear on screen with little effort.

Sure you can use some of the cool new web apps like typing.io which uses actual code and gives you detailed reports on how you did and where your problem areas lie, but MUDs can be incredibly addicting which is the main thing you need to get better at typing. You need to practice, a lot, and playing a game that makes you want to come back day after day is a great way to force yourself into practicing. I don’t really think it is worth spending time trying to explain why typing is important for a career as a programmer, but if you’re curious, Steve’s post above should be enough.

Scanning

The big realization I had that spurred this post was that MUDs also train you in scanning. Sure, it might be obvious that reading quickly is something you will pick up as you spend time mudding, but you also get better at not reading. With all the information that is scrolling on the screen constantly, it is just as important to know what you can ignore as it is to know what is important. Why this is particularly useful for programming is that we mostly have the same interface to our programs we’re writing as the MUD: a black screen with colored text. Unsurprisingly, being able to recognize and ignore unimportant text or quickly focus in on important text transfers incredibly well between the two domains.

Usually, this is something simple like quickly finding a method on screen, but occasionally you spot exactly what we are looking for in fast scrolling logs. You also find yourself being able to read in chunks rather than having to read every piece of the line. All of this really comes in handy when you’re debugging and/or tracing through multiple files – the less time you spend to find the what you’re looking for the better. Speed Matters.

Of course, MUDs are also fun and not just for becoming a better typist and scanner, but if you’ve ever seen or paired with someone who navigated a codebase with what seemed like impossible speed, there are few things better to train that skill than picking one and playing it for a few months. I’m sure you will see progress almost immediately and you’ll have a lot of fun while you’re doing it.

 

 

This Code is Crap, it Needs Rewritten

A few weeks ago I stumbled on Peter Naur’s essay Programming As Theory Building and it helped clarify a lot of things that have been on my mind for a while. It will likely be the source of many posts on this blog as time goes on, but there was one big idea that I’ve been obsessed with after reading it:

Not only are you building a theory of a program as you are programming, but you’re also building a theory of building programs.

It turns out that Naur even touches on this idea in Pluralism In Software Engineering (p79):

14CECF84-4C87-478D-876E-62FBDB3D30D5

“For me, program development is all about grasping the relationship between:

* the modellee (the real-world problem),
* the model (the program),
* the model building elements (the programming language constructs).”

I’m still figuring out all the implications of this and working out how usable of a thought it is for my career, but it does explain some of the things I’ve seen so far. One in particular is the topic of this post.

I’m sure we’ve all seen people join a team we’ve been on for a long time and immediately decide the program is crap and that it needs to be rewritten. I’m also sure that we’ve been that person many times as well. While there is a chance that it actually is crap, there’s even more of a chance that there is a mismatch in theories. There’s almost definitely a mismatch in the new programmer’s theory of how to solve the particular problem this program solves and the way the original programmers who have been working on the program since the beginning solved the problem. But, and this is the big thing, it is also just as likely that there is a mismatch in their different theories of building programs.

You can see this manifest itself in a bunch of different ways such as basic style differences, usage of different language idioms, usage of different programming patterns, and where the new person is on the software political axis versus the team who built the program. Unless you’re really lucky, you’re likely to have some significant differences in ways you program to solve problems – enough that you’ll run into something frustrating that someone else did before you.

The best use of this insight that I can think of is to come at all projects with an open mind – though in a different way than you probably think. You want to try as hard as possible to lose your attachment to the ways you have solved problems in the past no matter how much better you think they are. On one hand, you could get to more viscerally feel the cons of using a certain pattern or idiom – but on the other hand, you could also be learning something useful you’ll take with you the rest of your career. Either way, though, your goal on a new team isn’t to prove how smart you are. Your goal should be to minimize the amount of time it takes you to internalize the theory of the program you’re working on and the team’s theory of building programs. Being frustrated with the way the team works together and complaining about how bad the program is will just make that it take longer. I’m not saying that if things really are bad that you just have to live with them, but you should be as comfortable in the program and with the theory of the program as the best on the team before you start suggesting changes that deviate far from current styles. The upside is that once you’ve internalized the new style, you should be able to incorporate and easily switch between any of the styles you’ve learned so far. So while you may need to keep your ego in check at first and treat a new style with a beginner’s mind, in the long run it will make you a much better programmer.