Skip to main content
Mod Moved Comments To Chat
added 687 characters in body
Source Link
Sklivvz
  • 5.3k
  • 20
  • 34

I don't think TDD has a problem of local maxima. The code you write might, as you have correctly noticed, but that's why refactoring (rewriting code without changing functionality) is in place. Basically, as your tests increase, you can rewrite significant portions of your object model if you need to while keeping the behavior unchanged thanks to the tests. Tests state invariant truths about your system which, therefore, need to be valid both in local and absolute maxima.

If you are interested in problems related to TDD I can mention three different ones that I often think about:

  1. The completeness problem: how many tests are necessary to completely describe a system? Is "coding by example cases" a complete way to describe a system?

  2. The hardening problem: whatever tests interface to, needs to have an unchangeable interface. Tests represent invariant truths, remember. Unfortunately these truths are not known at all for most of the code we write, at best only for external facing objects.

  3. The test damage problem: in order to make assertions testable, we might need to write suboptimal code (less performant, for example). How do we write tests so the code is as good as it can be?


Edited to address a comment: here's an example of excaping a local maximum for a "double" function via refactoring

Test 1: when input is 0, return zero

Implementation:

function double(x) {
  return 0; // simplest possible code that passes tests
}

Refactoring: not needed

Test 2: when input is 1, return 2

Implementation:

function double(x) {
  return x==0?0:2; // local maximum
}

Refactoring: not needed

Test 3: when input is 2, return 4

Implementation:

function double(x) {
  return x==0?0:x==2?4:2; // needs refactoring
}

Refactoring:

function double(x) {
  return x*2; // new maximum
}

I don't think TDD has a problem of local maxima. The code you write might, as you have correctly noticed, but that's why refactoring (rewriting code without changing functionality) is in place. Basically, as your tests increase, you can rewrite significant portions of your object model if you need to while keeping the behavior unchanged thanks to the tests. Tests state invariant truths about your system which, therefore, need to be valid both in local and absolute maxima.

If you are interested in problems related to TDD I can mention three different ones that I often think about:

  1. The completeness problem: how many tests are necessary to completely describe a system? Is "coding by example cases" a complete way to describe a system?

  2. The hardening problem: whatever tests interface to, needs to have an unchangeable interface. Tests represent invariant truths, remember. Unfortunately these truths are not known at all for most of the code we write, at best only for external facing objects.

  3. The test damage problem: in order to make assertions testable, we might need to write suboptimal code (less performant, for example). How do we write tests so the code is as good as it can be?

I don't think TDD has a problem of local maxima. The code you write might, as you have correctly noticed, but that's why refactoring (rewriting code without changing functionality) is in place. Basically, as your tests increase, you can rewrite significant portions of your object model if you need to while keeping the behavior unchanged thanks to the tests. Tests state invariant truths about your system which, therefore, need to be valid both in local and absolute maxima.

If you are interested in problems related to TDD I can mention three different ones that I often think about:

  1. The completeness problem: how many tests are necessary to completely describe a system? Is "coding by example cases" a complete way to describe a system?

  2. The hardening problem: whatever tests interface to, needs to have an unchangeable interface. Tests represent invariant truths, remember. Unfortunately these truths are not known at all for most of the code we write, at best only for external facing objects.

  3. The test damage problem: in order to make assertions testable, we might need to write suboptimal code (less performant, for example). How do we write tests so the code is as good as it can be?


Edited to address a comment: here's an example of excaping a local maximum for a "double" function via refactoring

Test 1: when input is 0, return zero

Implementation:

function double(x) {
  return 0; // simplest possible code that passes tests
}

Refactoring: not needed

Test 2: when input is 1, return 2

Implementation:

function double(x) {
  return x==0?0:2; // local maximum
}

Refactoring: not needed

Test 3: when input is 2, return 4

Implementation:

function double(x) {
  return x==0?0:x==2?4:2; // needs refactoring
}

Refactoring:

function double(x) {
  return x*2; // new maximum
}
Source Link
Sklivvz
  • 5.3k
  • 20
  • 34

I don't think TDD has a problem of local maxima. The code you write might, as you have correctly noticed, but that's why refactoring (rewriting code without changing functionality) is in place. Basically, as your tests increase, you can rewrite significant portions of your object model if you need to while keeping the behavior unchanged thanks to the tests. Tests state invariant truths about your system which, therefore, need to be valid both in local and absolute maxima.

If you are interested in problems related to TDD I can mention three different ones that I often think about:

  1. The completeness problem: how many tests are necessary to completely describe a system? Is "coding by example cases" a complete way to describe a system?

  2. The hardening problem: whatever tests interface to, needs to have an unchangeable interface. Tests represent invariant truths, remember. Unfortunately these truths are not known at all for most of the code we write, at best only for external facing objects.

  3. The test damage problem: in order to make assertions testable, we might need to write suboptimal code (less performant, for example). How do we write tests so the code is as good as it can be?