I used to think I was good at programming. Since I started doing TDD in 1999, I’ve come to discover that I am not so good. I make a lot of little mistakes. Copy-paste is a specifically error-prone activity for me. When I copy and paste and N changes are needed, on a good day I can usually get N-1 on the first try.
When I’m almost done, I get a little careless. I’m not the only one! Take a look at this analysis of the Last Line Effect. He show lots of copy-paste bug examples from real code from products you know. In the article the author also mentions this may not be just programming.
mountain-climbers often fall off in the last few dozen meters of their ascent. Not because they are tired; they are simply too joyful about almost reaching the top – they anticipate the sweet taste of victory, get less attentive, and make some fatal mistake. I guess something similar happens to programmers.
I’ve watched a lot of programmers program in training context. They are not so good at programming either. Little mistakes are the norm, not the exception. But programmers generally don’t know how error prone their work is, because the feedback loop is too long pre-TDD. TDD puts the mistakes in your face so you can find them before they hatch into bugs.
With the mistakes in your face, you can certainly see them and fix them. You might, though awareness, start to do them less as you work on your weakness.
Virtually every line of code is written in response to some failure. It often is a test failure, but might be a compilation failure, or a web page that does not exist.
Through my 16 years of practicing TDD, I have come to discover that establishing cause and effect is critical to getting every line of code right. I’ve done most my TDD in embedded C and C++.
Over the last couple years, with the help of a couple friends, I built my ruby on rails website. I did not know ruby (or rails obviously). I know it a little bit now. I used to follow the several step procedures to bring up a new feature on my website. I would do the 3–6 steps outlined, and my new page would not come up. I’d spend considerable time trying to find the mistake and eventually get the thing to work. It would have involved several changes. The next day I would likely run into another problem because one of the changes was not really needed and I broke something else. In hindsight, I made changes without establishing cause and effect. My new feature started working often due to offsetting defects.
I started treating each step in the procedure as a test. For example If I tried to bring up a web page, that did not exist, what error would I get? I would look for a way to make one of the changes in the several step procedure and get a different error message. Getting new errors was not, but was it the right error? I learned to get the right error that moved my code in the right direction. I establish cause and effect. Cause and effect?! I am programming as an engineer. What is the problem? Can I impact that problem positively, and move my code in the right direction. Sometimes this cause and effect involves TDD tests, other times it is wiring code that once I get it right, I leave it alone
I just found this definition of engineering “skillful or artful contrivance; maneuvering.” I’d say that is the ideal I strive for in building software and a business. Yes, TDD affects how I run my business. TDD is built on cause and effect. Engineering! I doubt I would appreciate the cause and effect approach to programming (and life) if it were not for TDD.