Connascence: a mis-step
I had a very interesting discussion today with Ross about my recent connascence/TDD posts. Neither of us was happy about either of the solutions to the corruption problem with the special offer object. Even with the cloning approach, it still seems that both the Checkout and the MultiBuyDiscount have to collude in avoiding the issue; if either gets it wrong, the tests will probably fail.
After a few minutes, we realised that the root of the problem arises from the MultiBuyDiscount having state, and we began to cast around for alternatives. At some point it dawned on me that the origins of the problem go right back to the first article and the first couple of refactorings I did.
Let’s revisit that early code. After I had fixed the CoV arising from making the first test pass, the Checkout looked like this:
public class Checkout {
private int balance = 0;
public void scan(String sku, int price) {
balance = price;
}
public int currentBalance() {
return balance;
}
}
Then in the second article, after I had recycled the test to add multiple scanned items, the Checkout had become:
public class Checkout {
private Money balance = Money.ZERO;
public Checkout scan(String sku, Money price) {
balance = balance.add(price);
return this;
}
public Money currentBalance() {
return balance;
}
}
I had blindly made the Checkout keep a running balance, without pausing to realise that there was an alternative: I could have made it remember the scanned items, and only total them up in the currentBalance() method. Had I done so, it would then have been natural to calculate the discounts there too. And that could have been done by a special offer object that had no state. Thus avoiding all that faffing about with factories!
The problem I have with that, though, is that the code I wrote for the first (recycled) test was simpler than the alternative. I had no test, and no connascence, pushing me to remember the scanned items and total them later. At least, right now I can’t see that test or that connascence.
I feel that either my blind approach has led me to a poor design that will cost a lot to correct, or that I failed to spot something that could have prevented this. Food for thought…
Kevin Rutherford's Blog
- Kevin Rutherford's profile
- 20 followers

