Created
February 9, 2015 19:31
-
-
Save kevinrutherford/5adea38fc1012b9f2247 to your computer and use it in GitHub Desktop.
The checkout kata after 5 stages of connascence removal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Checkout { | |
private Money balance = Money.ZERO; | |
private MultibuyDiscount discount; | |
public Checkout(MultibuyDiscount discount) { | |
this.discount = discount.reset(); | |
} | |
public Checkout scan(String sku, Money price) { | |
balance = balance.add(price); | |
balance = balance.subtract(discount.discountFor(sku)); | |
return this; | |
} | |
public Money currentBalance() { | |
return balance; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import static org.junit.Assert.assertEquals; | |
import java.util.Random; | |
import org.junit.Test; | |
public class CheckoutTests { | |
@Test | |
public void basicPrices() { | |
Money priceOfA = randomPrice(); | |
MultibuyDiscount discount = new MultibuyDiscount("A", Money.fromPence(20), 2); | |
Checkout checkout = new Checkout(discount); | |
Money priceOfB = randomPrice(); | |
checkout.scan("A", priceOfA).scan("B", priceOfB); | |
assertEquals(priceOfA.add(priceOfB), checkout.currentBalance()); | |
} | |
@Test | |
public void discountForTwoAs() { | |
Money priceOfA = randomPrice(); | |
Money priceOfB = randomPrice(); | |
MultibuyDiscount discount = new MultibuyDiscount("A", Money.fromPence(20), 2); | |
Checkout checkout = new Checkout(discount); | |
checkout.scan("A", priceOfA).scan("B", priceOfB) | |
.scan("A", priceOfA); | |
Money expectedTotal = priceOfA.add(priceOfA).add(priceOfB) | |
.subtract(Money.fromPence(20)); | |
assertEquals(expectedTotal, checkout.currentBalance()); | |
} | |
@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()); | |
} | |
private Money randomPrice() { | |
int pence = new Random().nextInt(1000); | |
return Money.fromPence(pence); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Money { | |
public static final Money ZERO = new Money(0); | |
private int pence; | |
private Money(int pence) { | |
this.pence = pence; | |
} | |
public static Money fromPence(int pence) { | |
return new Money(pence); | |
} | |
public Money add(Money other) { | |
return new Money(pence + other.pence); | |
} | |
public Money subtract(Money other) { | |
return new Money(pence - other.pence); | |
} | |
@Override | |
public boolean equals(Object other) { | |
Money m = (Money) other; | |
return pence == m.pence; | |
} | |
@Override | |
public int hashCode() { | |
return new Integer(pence).hashCode(); | |
} | |
@Override | |
public String toString() { | |
return "" + pence + "p"; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MultibuyDiscount { | |
private String watchedSku; | |
private Money discount; | |
private int trigger; | |
private int itemsSeen = 0; | |
public MultibuyDiscount(String sku, Money discount, int trigger) { | |
this.watchedSku = sku; | |
this.discount = discount; | |
this.trigger = trigger; | |
} | |
public Money discountFor(String sku) { | |
if (sku.equals(watchedSku)) | |
itemsSeen++; | |
return (itemsSeen == trigger) ? discount : Money.ZERO; | |
} | |
public MultibuyDiscount reset() { | |
return new MultibuyDiscount(watchedSku, discount, trigger); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment