On bad code
There are plenty of software projects in the wild with low quality codebase and if you are a software developer you have written some and there is a good chance you are maintaining one.
Some of the main reasons projects end up with low quality code are:
- Skilled Developers knowingly write low quality code
- Unskilled developers write low quality code
Well, there is a third reason which is not paying technical debt; but technical debt is the result of writing bad code.
Skilled Developers knowingly writing low quality code
Uncle Bob says: "No matter who. No matter what. No matter when. Short term. Long term. Any term. Writing good code is ALWAYS faster than writing bad code.". I agree with him except for the "ALWAYS" part. In software there is no always there is no never.
Feasibility study is (usually) undertaken by businesses before any project starts. As part of this practice the feasibility of the project is assessed against a variety of criteria and the result of this study tells the business whether they should go ahead with the project or not. Sometimes to pass the feasibility assessment some sacrifices have to be made.
Sometimes constraints, usually tight deadline and/or budget, drive you down undesirable paths. The following scenarios/exceptions are usually the reasons skilled developers knowingly write low quality software:
- Time to market: There is an opportunity you have to seize quickly or it will be lost. Sometimes it is because the opportunity is there for a very limited time and sometimes because your competitors may saturate the market if you are not fast enough. This is where you are forced to write bad code to pass Schedule Feasibility.
- Low budget: You have an idea that could get you a good customer base and some revenue but do not have enough financial backup to do a high quality job. You implement the software in a quick and dirty way so you can release it to market, generate some revenue and then later use some of that revenue to improve your codebase. If you do not do this you fail Financial Feasibility which if ignored results in project failure.
- Usefulness/value uncertainty: You have a new idea and do not know if it is going to be useful or not. You have to put out your idea to assess its usefulness and receive some feedback and improve on it through Observed Requirements if it succeeds. It is as if you are releasing a working prototype into the wild to assess its Operational Feasibility!
What I would like to highlight about the above exceptions is that it make sense to write bad code in these cases only if the project is very small. For any non-trivial project I am with Uncle Bob even in the face of above constraints.
Bad code usually takes longer to write for any non-trivial task, and for a rather big task you are better off writing quality code from the start. In other words, for a non-trivial project sacrificing quality not only does not save you time or money but it also costs you more.
Why is it ok to write bad code, and why knowingly?
You should know you are writing bad code and you should be ready to pay the cost of writing bad code. The cost is the interest you pay on your technical debt: "doing things the quick and dirty way sets us up with a technical debt, which is similar to a financial debt. Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice."
Writing bad code, if it costs less and helps gain a big benefit as explained above, is IMO worth it. It is like getting a loan to buy a house: sure you are going to pay interest on your mortgage; but perhaps if you do not get the loan and buy the house in the buyers' market, the house would cost you much more later. So yes, you lose money by getting a loan, but you make up for that loss by capital gain and make some money. "The metaphor also explains why it may be sensible to do the quick and dirty approach. Just as a business incurs some debt to take advantage of a market opportunity developers may incur technical debt to hit an important deadline."
As mentioned above, though, you should know that you are writing bad code and you should try to improve it (when it makes sense). Unlike most financial debts that you have to pay as you go, technical debt payment can and unfortunately in a lot of cases is deferred, and this is a big problem: "The all too common problem is that development organizations let their debt get out of control and spend most of their future development effort paying crippling interest payments."
Beware: there is a trap
How many times have you been asked to do something in much shorter time than your estimation? Usually the excuse is that there is not much time and we should get it out of the door ASAP. In my experience a lot of such rushes are not based on real business needs; but rather an irrational desire to have the product faster.
How many times have you put a quick and dirty application together as a PoC and you have maintained it in production for years!?
Beware of these traps. You should be ready to write bad code when it makes sense; but do not be afraid to say No when the constraints are not real.
There are usually alternatives
Dealing with tight deadline/budget does not necessarily mean we should write bad code. It is usually a better idea to write fewer/smaller high quality features. In some cases you could negotiate the project scope and/or feature scope with the product owner and get some discount on the amount of code required to do the task. This way you will release smaller set of functionality; but the result has a higher quality.
Unskilled developers writing low quality code
Each software team should have at least one skilled developer. Note that I am deliberately avoiding the term senior developer; because seniority in software industry is usually judged by the number of years a programmer has been programming which in a lot of cases is no indicator of being a good programmer. Some programmers with decades of programming experience write the worst code. Also it is worth noting that skilled programmer does not equal certified programmer. Many great programmers in our industry do not have any (related) academic qualification or certificate.
The skilled programmer should try to improve the overall codebase quality by mentoring the team! In a team of developers you cannot improve the quality of codebase by yourself. If you want good result you need teamwork; so instead of singlehandedly trying to improve everything you should mentor and help the team to become better which over the time results in an overall codebase improvement.
If you know the code you have produced is bad, you have taken the first and a hard step to become a better programmer; that is admittance. The step that a lot of programmers do not take.
Writing bad code because you can always rewrite!!
Rob Conery says something on the lines of it is ok to write bad code; you can always rewrite it! I think this conveys a wrong message. I would not mind rewriting a very small application only if it takes a week or two to do so and if I do not have any thing better to do in that time. Rob talks about rewriting a small website and redoing a podcast. Well, yeah that I think would be OK - you can perhaps do that in your spare time!
And then in the comments Rob agrees with the following comment:
"My mate always used to say you have to write three version of an app to get something decent.
The first version is tight from the users perspective, but is a constantly changing monstrosity used to test your ideas in the face of the enemy (aka the users).
If the project has merit, you create the second version, a complete re-write it to encapsulate the ideal of the product, removing the fluff and delivering your pure, simple creation to the world.
The next re-write starts when your customer loves it so much they want to add features, lots of features, flowery crazy features, and you realise that your ideal of the 'project' has to mutate freely at the whims of insane people, but still remain reliable. Version 3 through 23 are still version 3, assuming you got version 3 right"
Most .Net programmers work as part of a team on non-trivial projects. On these projects rewrite is almost always a very big mistake (I should write a post about this).
It is sometimes ok to rewrite
In some cases rewrite makes a lot of sense. For example the application that drives the business may have been written many years ago with a now-obsolete technology. There are not many developers who can maintain the application and adding new features is a painful process for everyone involved. Maybe the old programming language does not support many of the features the business requires now. In this case it may make sense to rewrite this application to open new doors; but even then there are still a lot of risks involved in the rewrite.
You may also rewrite small parts of the application. For example the project starts small and because of some now-not-very-good-decisions made at the time your infrastructure does not support some of the non-functional requirements. You may decide to rewrite some parts of infrastructure (perhaps with backward compatibility in mind to minimize the rippling effect) to allow for business growth.
There are other cases that rewrite makes sense; but they are more of an exception. Rob talks about his good experience with rewrite and generalize that into a wrong message: "Rewrites Happen. Don't Limit Yourself". That message is read by many developers who work on projects where rewrite could result into a catastrophe.
So how to deal with bad codebase
The short answer is that you should pay down your technical debt one step at a time.
If you have a bad codebase try to improve it. Whenever you touch some part of the code add some tests and refactor it and make it better or as The Boy Scout Rule says "Always leave the campground cleaner than you found it."
Start paying your debt a bug at a time and you will find your codebase in a far better position in a year.
You should try your best to write good code; but it is sometimes inevitable to write bad code. But:
- Do not write bad code because you are asked to.
- Do not write bad code because you are going to rewrite it.
- Do not write bad code because it sounds like a quick and easy answer because it is not.
Before you write bad code, consider and discuss the consequences and alternatives and try to avoid it if possible. Do a cost/value analysis for bad vs good code and write the one that makes more sense to your situation.
If you decide to write bad code, know the consequences and prepare yourself to deal with them. Try to improve your codebase when it hurts and when you get a chance. Do not leave it there thinking you may be given a chance to rewrite it. A bad codebase causes headache and embarrassment for you more than anyone else.
Stop thinking about rewrite. Software rewrite could turn into your worst nightmare. Teams and businesses who start a rewrite usually have no idea what they are getting themselves into.