Clean Development Series: Part 2, Dirty Code (why we do it)
Lately I have been talking about clean application development, and how developers can do a better job of it. Due to the strong focus on this I decided to write some content from my latest talks into a series of blog posts. Enabling everyone to reap the benefits of the subject matter, and allow attendees of my talks to refresh the content covered at one of the events I spoke at.
In Part 1 of this series I discussed the causes and effects of dirty code, and how disastrous it can be for us and/or our employer. I think it’s easy to see how the terrible effects caused by writing dirty code is not desirable. Most of us try to avoid wasting time, introducing bugs, increasing technical debt, causing our companies to lose money, and looking for a new job because our employer went out of business. So if we don’t like these things, why do we write dirty code in the first place? It is our own fault after all, but it’s not something we consciously do…most of the time. Let’s take a look at a sample scenario, and see how we sometimes get ourselves in this type of situation:
New Job and a Simple Request
We start a new job, of perhaps we are approached by our supervisor with a request. We know how it works. The boss mentions how wonderful it would be if the application was able to do some sort of functionality, and asks if it’s possible. Of course in our haste to please and impress we say, “Of course”, and head off to our lair to perform our magic. We sit down behind the keyboard and already have an excellent idea of how to build the new functionality our boss was asking for. What do we do first?
Do we write unit tests? No. Do we document the requirements? No. Perhaps we at least write down some sort of decision making flow chart? No. So we at least have an idea of standards we will use and follow? No. Well, maybe we download a framework, or figure out what functions we already have rather than recreating the wheel? No say.
What actually happens is pretty mystical. Like a maestro ready to conduct an elegant symphony we go back to our desk, fire up our favorite IDE or editor capable of helping us create the best code imaginable by man. These tools have built in auto complete, connectors to version control, able to link to ticket and bug tracking systems, debuggers, project file management, structure tree display, code inspectors, refactor modules, and even direct connections to hosting and command line tools. We can now create true masterpieces of intellectual property.
But we don’t have any time for all of those bells and whistles today. We are excited and in a hurry to prove that our boss made the right decision by hiring us. So instead of using these awesome tools at our disposal we code the entire thing in very short order, and then spend a few minutes to do some functional testing and ensure it doesn’t blow up on us while we demo it.
Barely able to contain ourselves we rush into our bosses office to announce we have completed the functionality he requested. Our excitement is quickly contagious and our boss looks on wide-eyed as we demo our accomplishment. He is a little surprised we were able to finish it so quickly, and thanks us for our hard work.
Then, faster than we can think of what we will have for lunch, our boss immediately thinks of some sort of enhancement to the item we just completed. He quickly outlines how it could work and what it could bring the company. In the excitement of the moment, and our newly found feelings of accomplishment, we tell our boss it’s a small task and we should be able to get it done pretty fast.
We head back to our desk feeling the afterglow of the moment, feeling like we saved the world as well as earned our keep at this new employer. Once again we have a task to accomplish.
True to form we perform exactly as well on this second task assigned to us. In our haste to please we ignore best practices, testing, and standards as we quickly complete the new request. Upon completion, the meeting and presentation go pretty much like the first, and ends with yet another task.
More of the Same
This cycle continues over and over again, and we continue to perform admirably. Our boss seems to be a wealth of knowledge and ideas, and we continue to turn these ideas into application at an astounding rate. However, with each iteration there are more bugs, more overlap between one functionality and the next, and more “gotcha” moments as we try to demo the newly created functionality. We are starting to struggle with the code base a bit as our technical debt has been steadily increasing little by little.
Longer Time frames
Of course we are smart, and realize very fast that those little “gotcha” moments as we demo to our boss are taking a toll on his trust of our ability. We quickly realize we need to test a little better before presenting the functionality. This requires some time to complete so we start to pad our time estimates a bit to compensate. But with each task this time frame grows longer and longer, and soon these time estimates become a week, a month, two months, a quarter, then six months.
By now our code has become so unstable we fear it, and are tripping over quick decisions made months ago. There are no unit tests, no standard functional tests, no documented regression tests. Our code is just layer upon layer of classes and functions that are so tightly coupled we constantly trip over them. A change in one place causes things to break in 4 other places. We have not even sat down and set a coding standard, let alone done any documentation of the application.
It’s at this point that every time someone makes a request our first answer is “6 months”. However, we know in our mind that there is no way we can get it done in that time frame. But marketing needed some sort of answer and there is no way they would settle for a number larger than 6 months.
We’ve dug a hole of technical debt over time by not using best practices, and we are in a danger area. Our once pleased boss is questioning every choice and estimate we make. Perhaps he is forgiving a little because he realizes we have worked so hard up to now, and we have earned some “professional credit” to this point. We realize that action needs to happen…and happen fast.
Time to Pay
As with all debt, whether it is financial or technical, we must eventually pay it off somehow. With financial debt we either pay it off by making payment arrangements, or we go bankrupt. Technical debt is similar. With technical debt we can either refactor bit by painful bit (making payments), or we can do a full rewrite of the application (go bankrupt). Of course we could also leave the company and therefore leave the mess for someone else to clean up, but lets assume we are responsible developers and feel obligated to do the right thing.
I am sure most of us have played a part in the story above, and can nod our heads in understanding. Hopefully most of us have learned from the experience and no longer do it. (Yeah, right.) Those who have not had the luxury of making these mistakes should take heed of the story and learn from these common mistakes. The story above IS NOT how to do things.
IMPORTANT: Our employers hire us to be professionals. By following the sequence above we set the standard ourselves, in a bad way. Please do things the right way, and be the professional you were hired to be.
Throughout this series I will continue to outline ways to avoid making these mistakes, and how we can accomplish “Clean Development”. I hope you found this breakdown helpful, and learned from it.