Take the 2-minute tour ×

During a discussion, one of my colleagues told that he has some difficulties with his current project while trying to solve bugs. "When I solve one bug, something else stops working elsewhere", he said.

I started to think about how this could happen, but can't figure it out.

  • I have sometimes similar problems when I am too tired/sleepy to do the work correctly and to have an overall view of the part of the code I was working on. Here, the problem seems to be for a few days or weeks, and is not related to the focus of my colleague.
  • I can also imagine this problem arising on a very large project, very badly managed, where teammates don't have any idea of who does what, and what effect on other's work can have a change they are doing. This is not the case here neither: it's a rather small project with only one developer.
  • It can also be an issue with old, badly maintained and never documented codebase, where the only developers who can really imagine the consequences of a change had left the company years ago. Here, the project just started, and the developer doesn't use anyone's codebase.

So what can be the cause of such issue on a fresh, small-size codebase written by a single developer who stays focused on his work?

What may help?

  • Unit tests (there are none)?
  • Proper architecture (I'm pretty sure that the codebase has no architecture at all and was written with no preliminary thinking), requiring the whole refactoring?
  • Pair programming?
  • Something else?
share|improve this question
Ah, the good ol' "cascading waves of failure" design pattern. :-) –  Brian Knoblauch Dec 9 '11 at 18:36
I liken it to a bubble in a sheet of contact. Push it down, it pops up elsewhere. The better my coding gets, the less I see it –  johnc Dec 13 '11 at 22:44
add comment

8 Answers

up vote 27 down vote accepted

It doesn't have much to do with focus, project size, documentation, or other process issues. Problems like that are usually a result of excessive coupling in the design, which makes it very difficult to isolate changes.

share|improve this answer
this combined with poor or no regression testing –  Ryathal Dec 9 '11 at 17:52
True, @Ryathal, although regression testing won't prevent those kinds of bugs, just let you know about them sooner. –  Karl Bielefeldt Dec 9 '11 at 18:03
add comment

One of the causes can be tight coupling between the components of your software: if there are no simple, well-defined interfaces between components, then even a small change in one part of the code can introduce unexpected side-effects in other parts of the code.

As an example, lately I was working on a class that implements a GUI component in my application. For weeks new bugs were reported, I fixed them, and new bugs appeared somewhere else. I realised that that class had grown too large, was doing too many things, and many methods depended on other methods being called in the right sequence in order to work properly.

Instead of fixing the latest three bugs, I did some strong refactoring: split the component into a main class plus MVC classes (three additional classes). In this way I had to split the code into smaller, simpler pieces and define clearer interfaces. After the refactoring all the bugs were solved and no new bugs were reported.

share|improve this answer
add comment

It's easy for one bug to mask another. Suppose bug "A" results in the wrong function being called to handle input. When bug "A" is is fixed, suddenly the correct function is called, which has never been tested.

share|improve this answer
add comment

Well, the immediate cause is two wrongs making a right, or at least making a not-obviously-wrong. One part of the code is compensating for the incorrect behavior of the other part. Or if the first part isn't "wrong" as such, there's some unwritten agreement between the two parts which is being violated when the code is changed.

For example, suppose functions A and B use a zero-based convention for some quantity, so they work together correctly, but C uses one, you might "fix" A to work with C and then discover a problem with B.

The deeper problem is a lack of independent verification of the correctness of the individual parts. Unit tests are designed to address this. They also act as a specification of the proper inputs. E.g. a good set of tests would make it clear that functions A and B expected 0-based input and C 1-based.

Getting specifications right can also be done in other ways, from official documents to good comments in the code, depending on the needs of the project. The key is understanding what each component expects and what it promises, so you can find inconsistencies.

Good architecture helps with the problem of understanding the code, making this easier. Pair programming is helpful for avoiding bugs in the first place, or finding them more quickly.

Hope this helps.

share|improve this answer
add comment

It sounds like these "new" bugs are not actually "new" bugs. They were just not a problem, until the other code that was broken, was actually fixed. In other words your colleague does not realize he actually had two bugs the entire time. If the code that is not proving to be broken wasn't broken, it wouldn't have failed, once the other peice of code was actually fixed.

In both cases a better automated test regimen might be helpful. It sounds like your colleague needs to unit test the current code base. In the future regression testing will verify existing code continues to function.

share|improve this answer
add comment

Improve the breadth of your automated test regimen. ALWAYS run the full set of tests prior to committing code changes. That way, you'll detect the pernicious effect of your changes.

share|improve this answer
add comment

I just encountered this when a test was incorrect. The test checked a given permission state that was !correct. I updated the code and ran the permission test. It worked. Then I ran all tests. All of the other tests that used the checked resource failed. I corrected the test and the permission check, but there was a bit of panic at first.

Inconsistent specifications happen as well. Then it's almost guaranteed that fixing one bug will create another (exciting when that particular part of the spec isn't exercised until later in the project).

share|improve this answer
add comment

Imagine that you have a complete product. Then you add something new, everything seems fine, but you broke something else, which depends on some code that you change to make the new feature work. Even if you don't change any code, just add functionality to existing, it might broke something else.

So basically you nearly answered yourself:

  • loose coupling
  • lack of tests

Just learn to adapt TDD principle (at least for new features) and try to test every possible state that can happen.

Pair programming is great, but not always "available" (time, money, both..). But code reviews (by your colleagues for example) once a day/week/set of commits will help greatly too, especially, when the review includes the test suite. (I find it hard to not write bugs to test suites... sometimes I must test the test internally (sanity check) :) ).

share|improve this answer
add comment

Your Answer


