Am I over-thinking things with this Checkout TDD example? Or is there a real problem here?
Based on insightful input from Pawel and Ross, it is clear to me (now) that there is CoA between the currentBalance() method and the special offer object(s), because the method doesn’t give those objects any opportunity to make final adjustments to the amount of discount they are prepared to offer.
However, as things stand there is no requirement demanding that. Does that still mean the connascence exists? Or is it a tree falling in the forest, with no tests around to hear it?
I could add peculiar discount rules, as Pawel suggests. Or I could add asymmetric discount rules such as those used in Kata Potter. Indeed, I could require that the Checkout provide an itemised receipt — in which case it would have to remember each scan event, thus making the refactoring to stateless discounts easier.
I knew at the time that exotic special offers would cause the code to change. That is to be expected. I had done the exercise to a reasonable point, and I chose to stop where I did because I had covered the ideas I thought were most useful. I could have gone further, but I felt that would mainly repeat ideas that I had already covered.
My real problem with all of this is the following: I have arrived at a destination that feels uncomfortable; I know which tests to write next, should I wish to steer the code to a better place; and I know that doing so will be a fairly hefty (ie. risky) rewrite of the code thus far. But I also know that the source of the discomfort stems from a decision I made very early in the kata. At that stage, I didn’t see the problems coming over the horizon. Because nothing I can see in the rules of connascence told me they were lurking there.
Only 2 effective lines of code, in two methods, are involved. And yet — or maybe, and therefore — the pending CoA was not visible (to me). I would like to understand whether there is something I should be looking for next time in order to avoid that, or whether occasional risky rewrites are an inevitable consequence of (this style of) TDD?