When you see (or hear) the phrase “software defect” what does that mean to you? Other than the obvious fact that defects are bad, what are they? If you are a fan of wikipedia, then maybe you liken a defect to:

an error, flaw, mistake, failure, or fault in a computer program that prevents it from behaving as intended

I certainly agree with this definition; however, the latter part of it (”prevents it from behaving”) tends to focus on a running application. Don’t get me wrong, defects (as we’re used to defining them) usually manifest themselves when an application is run (i.e. the nefarious Blue Screen of Death); nevertheless, if you subscribe to the notion that code should be, in essence, mistake proof through arduous early testing, then I have found that by expanding the definition of what a defect is has the benefit of improving a software development process by highlighting how one’s actions from day one can have long terms implications.

For instance, if your definition of a defect is limited to application behavior (say, in user terms), you may end up delaying your own ability to actually find them. The time delta between when code is cut and when someone can exercise some sort of acceptance test is directly related to an increase in actual costs (as everyone already knows). This is why, of course, Agile methodologies espouse short iterations as opposed to big bang waterfall-like cycles.

Alternatively, if you broaden your definition of a defect, then you can, more often than not, find them sooner. Assuming your team is actually writing developer tests, then a defect could be that a test failed (note that 9 times out of 10, a developer test is executed against a portion of a running system). Ideally, if tests exist and you’ve got an automated build system, then you can run those tests often (like every time your SCM system changes via Continuous Integration). Already, in this scenario, you can find defects early.

What if you take it a step further– say, if a failing developer test is considered a defect, then perhaps another form of a defect could be the lack of a developer test? If you define “legacy code” as code that doesn’t have a unit test and you’ve committed to stop writing legacy code, then by definition, code that is modified or new and doesn’t have a test is therefore legacy code (which is bad); hence, the addition of legacy code into an SCM should be a defect!

But wait! Developer tests (i.e. unit tests) require that people actually write them (in some cases they can be generated). And as I noted earlier, tests are usually executed against a running system. What if you further expanded your definition of a defect to include variations in code metrics, such as complexity? For example, if you are able to measure complexity (such as cyclomatic complexity) and you tend to eschew it, then if complexity increases, you can surely consider that a defect, can’t you?

You can even combine various measurable aspects of developmental activities to further exploit finer grained defects. For example, if you have developer tests, then you can surely obtain code coverage numbers. Once you’ve obtained coverage values, if they drop, you can infer a few things:

  • New code was added that doesn’t have any tests for it (legacy code == defect)
  • Someone deleted some tests

Either way, code coverage dropped, so why not consider that a defect?

What’s more, why not combine measurements further– if code coverage drops for a particular section of code AND the complexity of that code increased, bingo! Defect. Of course, the combinatorics go on, but hopefully, the point is evident: if you broaden what a defect is to you, you can then do things to find them early.

Your definition will be different based upon business needs as well, but rest assured that if you want to produce reliable code quickly, you’ve got to find defects as early as possible and to do that you’ve got to expand your definition of a defect.