A network of sites, tools, and technology to bring ideas into reality.

The Digital Tumbleweed

Thoughts and ramblings of an enthusiast

Fixing Mistakes – Some Thoughts On TDD/Rot/Debt

drhorribleSoftware development is always a good way to realize that you’re human. I’m sure there are other professions that give you this feeling as well, but my experience is limited to the software development field so I’ll talk about it from that light. There are really two ways to go on this subject. I could talk about code rot and the need to clean it up and/or talk about test driven development. Because I think they both have something to do with each other, why not make it about both eh?

The Church of TDD

Test Driven Development is a nice concept. The key here is concept. The idea here is that you write tests for a piece of functionality (ideally you know what you’re trying to get out of your function) and then write the actual functionality such that all your tests pass when your functionality is complete. Why you might ask? Well, I’ll answer! The reasoning is that when you’re 3 months into your project, breaking Brooks’ law, and trying to cope with the ever changing requirements of your project, you’ll simply have to make your change and re-run your tests. If they fail, you caught the problems at test time rather than at 3 AM when your boss friend calls you up and lets you know that he was just informed about emails being sent around to customers with usernames, email addresses, phone numbers, and contact lists for about 500,000 users.

Obviously a made-up case, but I have read about similar scenarios. That said, test driven development is only useful when you’re testing the right things. Testing functionality isn’t just about testing that you get a string back in all cases. Let’s say your working with Java and StringTokenizer’s. You might need to test the return values of each token. Also you may have to test the number of tokens or if a token is supposed to be empty that it isn’t null. If an exception should be thrown, you should check that case too. There are plenty of example cases to check here, but the point is that if you’re testing a method and only checking that something was returned then you aren’t finished.

google-algorithmStart out with a plan. This works in either the agile or waterfall methodologies. By this I mean, think about what you are about to produce. It usually helps me to take a step back and process what the method is expected to do. “What do I expect to see when I call x()?” “What assumptions do I seem to be making about x() where I’m calling it?” Running through questions like these are a good way to get a base set of tests for your functions.

So now you have a handful of tests that should make sure your code works right? Right!?!? Not necessarily. Let’s go back to my first line here. “Software development is always a good way to realize that you’re human.” You’ll miss something. It’s inevitable and, what’s better, it isn’t because you are bad at what you do. There are so many other things that are likely going on in your brain. If you are anything like me the whistle of a dart flying by your head or the ping and the pong of a game going on in the distance is enough to bring you out from your “I should write tests” concentration. What’s more, there are just going to be cases that you miss. It is O.K. to miss things, but there is a stipulation here. When you do and when it is caught, you need to write a test that checks for the situation/case.

Subscribing to TDD for the sake of it wont get you far and will likely slow your productivity. But, if you take a pragmatic approach to TDD and write tests as you think of cases your source base will likely be more stable since you’ll find bugs when you run the tests instead of through the client. And, you’ll have a system in place for those bugs that do slip through so that you can make sure they don’t come up again. Clients are a lot less understanding when you have issues with your code base and you can’t assure them that you wont ever have that problem again because you have no tests in place to ensure it.

Code Rot and Technical Debt

Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite…. The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object-oriented or otherwise. – Ward Cunningham on Technical Debt

carrying_debtSoftware development is one of those knowledge based fields. You write software with what you know at the time. If you are any good at what you do, you should still be learning every single day. The old saying “you can’t teach an old dog new tricks” really doesn’t hold water in this industry. Once you stop learning new things, techniques, and methods, you’ve effectively signed yourself into retirement or unemployment. That is just the way our industry works.

So, with this new-found knowledge and all powerful ability you’ll begin to smell something. It’s a familiar smell. You’ll be working on your code base and look at a method you wrote a couple weeks ago and have to plug your nose. That, my friends, is code rot.

The two, technical debt and code rot, are interesting. Understanding that you may take shortcuts to get a project moving only works when you refactor. If you do not refactor your code after you’ve introduced the questionable code you’re in for a “fun” time.

Lets not get the two confused. Code rot is typically when things change external to the code such as your ability to program or changes in the industry that your software works with. Technical debt tends to be what you introduce knowingly to the code with the intention of cleaning up later. However, as you find code rot, it becomes technical debt when you do nothing about it.

Technical debt is something that needs to be paid back. Relating this to real life; imagine yourself going so far into debt that you cannot imagine yourself ever getting out from under the load you carry. You will either be stuck with extreme payments the rest of your life or you’ll claim bankruptcy. In a software project, the equivalent of bankruptcy is a complete rewrite. You have invested time, sweat, tears, and likely a decent amount of money into whatever you’re working on. You don’t want to lose what you already have, but sometimes it’s inevitable.

The point I’m trying to make here is that you need to be willing to pay back your technical debt such that when you incur more debt, you aren’t overwhelmed by it. Paying that back can be related back to time and effort. Hell, even if you spend 5-10% of your time just refactoring your code you’ll have been paying back some of the incurred debt.

I’m probably beating a dead horse here so I’ll move on.

Problems

There are always issues right? “Sure, what you’re saying makes sense, but we don’t have the time or the budget to go through our code and fix it.” I know. I’ve heard and said this before. But, think about it like this.

badbrakesI have a car. I drive it places and it serves me well. I put gas in and all is right in the world. Then one day I feel some light vibrations when I press the brake. I don’t think much of it because the car still _works_. I don’t have the time to get it taken in to the shop. About a week or two later I feel a stronger vibration and every so often some squeaking coming from the car. Again, no time- I’m a busy man! Another couple weeks pass and now the squeaking is a screeching and it’s loud. It pierces my ears. I know that sound and realize that it means I likely need to fix more of the car. Now things are getting pricey and I don’t have the money to fix it all at this point.

You see what’s happening? I put it off so long that it became prohibitively expensive to surgically remove the rot. Instead now it is going to cost me a fair amount of cash, time, and effort to actually get these fixed. And, who knows, if I continue on the current path I might end up in a wreck.

Still when you are under constraints that you have very little control over there doesn’t seem to be much that you can do. Most of the time you are forced into situations where you either piss off the PM’s and management or just continue to let the code grow it’s warts. Ideally, you’ll prove to those that make time and budget based decisions that your changes will be worth it. By worth it I don’t mean “the code will be better”, I mean “in the long run, we’ll say 30% and gain 5% in revenue”.

Solutions

One of the serious mistakes that developers make with manager types is that they think they are relating to them with terminology and analogies. Typically it requires actual impact to prove that you are right. In order to get impact values you have to gather some metrics. Hopefully some of what follows can help there.

If you already have tests in place for the code you’ve written you can do a couple of things. Lie to the people that are asking you what you’re working on. *cough* working on that scalable synergistic thing-a-ma-bob that will grow our profits exponentially *cough*. Or, you can tell them the truth. Regardless of what you do, you can have some faith in the fact that your system should operate in the way you expect it to because you have tests in place for just this reason. At some point this code was going to be changed and you wanted to make sure that you did some CYA when it did change.

If you don’t have tests you can again, lie to the people. Or, you can explain to them why it is important and some tactical approaches to solving the problems. Some fuel for the fire:

Think about things like this. You want to get rid of this technical debt. It’s very likely that the project manager does too. But, explaining these things to the people who are interested in release dates can be challenging. Try explaining that customers are more happy when their software works. The more you can ensure that the better. Often it’ll require charts and figures with bug numbers over time. Be sure to show where you’re making improvements too. For instance, “as you can see we refactored the code on 3/12 and the number of bugs being reported decreased by n%”. By doing this, you are effectively showing ROI and how your changesĀ  affect the bottom line. For people concerned mostly about money that is important.

And, if all else fails, show them this video!

Sometimes it’s better to just ask for forgiveness in doing these things. Even if it means temporary irritation, the benefitsĀ  outweigh the downside.

  • Share/Bookmark