14

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?
4
  • 14
    Ah, the good ol' "cascading waves of failure" design pattern. :-) Dec 9, 2011 at 18:36
  • 1
    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, 2011 at 22:44
  • 2
    On a side note, I had exactly that on an embedded system. I added a function call to fix an issue. That function call was too much for the stack (the microcontroller had no stackoverflow detection) and so it wrote some random stuff elsewhere to the memory, which of course broke something somewhere completely different. So, this thing CAN happen on a small codebase with only one developer and good architecture. Jan 15, 2016 at 15:00
  • ...and that was a nightmare to debug. Jan 15, 2016 at 15:02

9 Answers 9

38

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.

3
  • 15
    this combined with poor or no regression testing
    – Ryathal
    Dec 9, 2011 at 17:52
  • 3
    True, @Ryathal, although regression testing won't prevent those kinds of bugs, just let you know about them sooner. Dec 9, 2011 at 18:03
  • If you know about them soon enough (e.g. within minutes of creating the bugs) then you can undo your changes and effectively pretend they never happened.
    – bdsl
    Feb 4, 2018 at 14:16
14

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.

7

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.

5

Tight coupling, lack of testing, these are probably the most common culprits. Basically the common issue is just shoddy standards and procedure. Another is just incorrect code managing to get lucky for a while with correct behavior. Consider memcpy bug from Linus Torvalds where changing its implementation exposed (not caused) bugs in clients which used memcpy in places where they should have used memmove with overlapping source and destination.

4

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.

3

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.

0

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.

0

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).

0

Let's say developer A wrote some code with a bug. The code doesn't exactly what it is supposed to do, but something slightly different. Developer B wrote code that relied on A's code doing exactly what it is is spec'ed to do, and B's code doesn't work. B investigates, finds the incorrect behaviour in A's code, and fixes it.

Meanwhile developer C's code only worked correctly because he relied on A's code incorrect behaviour. A's code is now correct. And C's code stops working. Which means when you fix code, you need to check very carefully who uses this code, and how their behaviour will change with the fixed code.

I have had another situation: Some code misbehaved and stopped a feature completely from working in some situation X. So I changed the misbehaviour and made the feature work. The unfortunate side effect was that the whole feature had significant problems in situation X and failed all over the place - this had been completely unknown to anybody because the situation had never arisen before. Well, that's tough.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.