Last time I fixed two instances of Connascence of Algorithm. Then I realised that I had introduced some more, so I fixed that too. After I had put that post to bed I also noticed that I had missed some alternative solutions. This article puts that right.
Towards the end of the previous article I noticed that the following test would fail:
@Test public void independentCheckouts() { Money priceOfA = randomPrice(); MultibuyDiscount discount = new MultibuyDiscount("A", Money.fromPence(20), 2); Checkout checkout1 = new Checkout(discount); Checkout checkout2 = new Checkout(discount); checkout1.scan("A", priceOfA); checkout2.scan("A", priceOfA); assertEquals(priceOfA, checkout1.currentBalance()); assertEquals(priceOfA, checkout2.currentBalance()); }
I fixed it by introducing a MultibuyDiscountFactory, so that the Checkout could always create its own instance of the discounter. And then I went for a walk, during which I realised that I was uncomfortable about having two classes — the rule and the factory — for one concept, and both with the same constructor parameters.
So, after much tramping across fields, I back out the change that introduced the factory. I now know that I can fix that Connascence of Algorithm without even touching the test: I will update the MultibuyDiscount so that it can be cloned by the Checkout:
public class Checkout { //... public Checkout(MultibuyDiscount discount) { this.discount = discount.reset(); } }
public class MultibuyDiscount { //... public MultibuyDiscount reset() { return new MultibuyDiscount(watchedSku, discount, trigger); } }
(On method naming: I decided that “clone” wasn’t a domain term, whereas it seems reasonable to ask a discount rule to reset itself before use. I may well find an even better name in the future.)
Next time I plan to look ahead at what remains to be done in this code, and also to look back and reflect on the journey so far…
Pingback: Connascence of Algorithm | silk and spinach