Sunday, September 7, 2008

Why bugs appear in software

Where do bugs come from and why are they always there in software development. Almost every engineer will give you a different take on the subject, and this is mine. I try to focus what I feel is common to all engineers. I'll be modifying this slightly and massaging it over time, since I want it to be comprehensive, maybe even with charts. But this is "1.0" of my article.


In Summary:
Here is the summary before the breakdown. All complex systems, and i mean ALL complex systems have their form of "bugs", or deviations from the norm - since this is the nature of the universe. Seen from that most generic point of view, bugs are inevitable, unavoidable and often times expected.

Software exhibits bugs when...

  • the use cases driving the software are not fully understood or change during development.
  • the code is too rigid - lacks flexibility and robustness
  • the developer uses bad practices and makes it hard for new developers to read and use the code, or even himself 6 months down the road.
  • there are too many levels of communication in the stack of code, or layers of indirection. Concepts degrade from receiver to receiver resulting in corrupted information.
  • the long and complicated string of logic required for development is somehow interrupted.
  • any many more... please read on for a comprehensive set. I don't think this is really in any order yet.

1. Constraints

Time
  • Time is both the whip that prods the engineer and the pressure that cooks the engineer from coal to a diamond.
  • Learning how to code with time constraints forces the engineer to gain efficiency - which means less code and less bugs : elegance. And as we all know, the best code is elegant code. Elegant code is the holy grail of development. It is not the end goal, rather, functionality is the end goal, but elegance is the grail.
  • Time, however you look at it, is a force exerted upon the developer. Decisions must be made, often without the time to follow those use cases to their best end result. Because of this, the core of the system design, no matter how small - is naturally going to suffer in the realm of robustness and flexibility. When these two attributes suffer, the possibility for that or other developers to add buggy code is higher.
  • A separate metric here is experience - time as related to experience shows (graphically) that as the experience of the developer grows over time, the likelihood grows that robustness, flexibility and overall elegance of the system will be in place before the product is released.
Other projects, part 1
  • Bugs are possible even when a developer is focused on one project - but this is rarely the case. Often times, and especially in an environment that lacks sufficient talent for so many burgeoning new projects, developers are forced to do more than one project at a time. The same resource must be divided amongst many projects and this leads to the lack of sufficient time, and lack of time leads to bugs.
Lack of knowledge
  • I consider this to be a constraint. Lack of knowledge here is not lack of expertise. The knowledge here is twofold: knowledge of what the use cases are that the software should support (in use-case driven engineering) and the overall knowledge of the group within engineering - the engineer's surroundings.
  • The first aspect, use cases, shows us that bugs can get into software when use cases are either not fully understood by the engineer for whatever reason or when use cases are introduced, and then changed over time.
  • The second aspect, surroundings, shows us that bugs can be introduced when the engineer is working in a team, but for whatever reason is not synchronized with that team in terms of his or her knowledge - the knowledge about exactly what everyone is doing. This can happen over long development cycles. Again, the engineer has to backtrack or modify the code, resulting in bugs.

2. Changes

Use case changes, scope creep
  • Changes in use cases often times happens during the product development and causes many bugs. Use case changes are the most dramatic and damaging of all possible ways that bugs can be introduced. This can happen when those responsible for the use cases of the software suddenly realize that they were wrong, the customer was wrong, or that the use cases outlined are not enough.
Other Bugs
  • Bugs beget bugs! The biggest reason why bugs cause bugs is because of the inevitable lack of robustness or lack of elegance in code. When a developer has to fix a bug, it is very, very likely that they will fix one bug and cause another. This has to do with all of the bullet points listed on this entire page.

3. Emotional Coding
  • Even the most hard-nosed iNTJ, introverted genius savant will have some aspect of emotion in their code. We are emotion and logic driven creatures. Because life outside of the world of development is full of complexities, it is nearly impossible to remove all that when you code.
  • Anger, lust, lovesickness, spite, joy, disgust or overwhelming glee can occur even when developers are in their Coding trance. All of our bodily movements, and even our ability to formulate logic are driven by emotion of some kind, even at the most animal level - for we are fright-or-flight creatures first, and rational man second. Even the brain shows us in its structure hierarchy that reason and logic are built upon the concepts of movement, lower-level emotion, and survival.
  • So what does all this emotion mean? Everything. There are only so many keys on the keyboard to press in order to input characters to the screen which will ultimately become code. The neurons that fire to command your fingers to code logic one way versus another is entirely subject to the current emotional experience of the developer. Trances help to limit this kind of development, but can't be removed entirely. As a result, and over the lifetime of the software development, there are subtle variations in the robustness and flexibility of the code.

4. Distractions

Other projects, part 2
  • Bugs are possible even when a developer is focused on one project - but this is rarely the case, as I said already. Switching gears between projects increases the likelihood that ideas will be forgotten and deviations from robustness and flexibility will increase. This is a fundamentally different problem than simply having more than one project. In other projects, part 1, I outline that the division of a resource across projects reduces time per project. Here I am saying that switching gears among projects leads to confusion, inefficiency and ultimately to stress and emotional coding.
Other People
  • Those darn other humans! They keep taking me out of my coding trance! This leads me to code more emotionally. This leads me to distraction. Distraction helps ensure that I will forget the very long and complex string of logic I had to create in order to make the software work. This is a necessity in the work place since no man is an island. We work in engineering teams and must be able to focus on other people.
  • Noises, especially these days are at an all time high. People take for granted all the clicks, beeps, boops and rings that are in the office environment. It is often true that people with the talents of coding exhibit traits of introversion (but not always), but also traits of sensory sensitivity and enhanced abilities to view systems as a whole, assemble and disassemble complex patterns, and abilities to string together long strands of complicated logic. The same systems allow engineers to be easily distracted by impurities of environment. Impurities, like real flying bugs, destroy the experience.

5. Levels of Expertise

Experience
  • Achieving any level of homogeneity in an engineering team regarding experience is tough - but well worth the effort. Having most of your developers at roughly the same level of experience will ensure that they are all playing the same game. Can you imagine if a baseball team or a football team was forced to play their weakest players at all times? In the office, we can bench our weakest players, but in the end they are touching code and inexperience means bugs. Nobody is sitting on a bench doing nothing or they would be let go in the blink of an eye.
  • There is not much else here to say. The more experienced you are, the more likely you are to write sustainable, robust code. The less experienced you are, the more likely you are to write inefficient code which leads to bugs.

Complexity of the system
  • This could be considered a constraint, but there are many levels of communication in the average stack of code. From the thinest user-interaction layer of the browser, to the business logic, to the database, often times there are 3, 4, 5, 6 or more layers of independently self-sustaining software platforms or "tiers" that make the software run. And that is just the software that is being created. Imagine all the layers involved when software is installed into software! The fact that anything works is nothing short of an absolute miracle. Very few non-developers will truly appreciate this.
  • Concepts degrade from receiver to receiver resulting in corrupted information. The bible lost a lot of its original meaning when translated from language to language over the course of thousands of years - and the analogue of bugs here is the mistakes of interpretation

Finally...

When it comes down to the nitty-gritty, development, as in life shows the true nature of the engineer when things aren't going well. We do get credit for our ability to plan, but the true measure of an engineer comes when forced to deal with the inevitable bugs that arise from their or some other software.

"It's not about how you plan, its about how you deal with crisis."

No comments: