Cette semaine, c'est Alice qui vous propose un #KataOfTheWeek : Le prix des boissons (beverage prices refactoring)
Briefing du Kata : Le code calcule le prix de différentes boissons qui sont vendues dans un café. Des suppléments peuvent être ajoutés à ces boissons. Chaque supplément fait augmenter le prix de la boisson.
Le but du kata est d'ajouter un supplément optionnel de cannelle à 0.05€ au catalogue de boissons existant. Il faut réfactorer le code avant d'ajouter la nouvelle feature.
Le code initial peut être trouvé ici : https://github.com/trikitrok/beveragespricingrefactoring_kata
Saurez-vous résoudre le problème ?
Bon courage !
Et voici une solution proposée par l'auteur en Java :
interface Beverage {
double price();
}
class Coffee implements Beverage {
@Override
public double price() {
return 1.2;
}
}
class HotChocolate implements Beverage {
@Override
public double price() {
return 1.45;
}
}
class Tea implements Beverage {
@Override
public double price() {
return 1.5;
}
}
interface Topping {
double price();
}
class Milk implements Topping {
@Override
public double price() {
return 0.10;
}
}
class Cream implements Topping{
@Override
public double price() {
return 0.15;
}
}
class Cinnamon implements Topping {
@Override
public double price() {
return 0.05;
}
}
class Drink {
private Beverage beverage;
private List<Topping> toppingList;
public double price(){
return beveragePrice() + toppingPrice();
}
private double beveragePrice(){
if (this.beverage != null) {
return this.beverage.price();
}
return 0;
}
private double toppingPrice(){
return this.toppingList.stream()
.filter(Objects::nonNull)
.map(topping -> topping.price())
.reduce(0d, (a, b) -> a + b);
}
public Drink(Beverage beverage){
this(beverage, Collections.emptyList());
}
public Drink(Beverage beverage, List<Topping> toppingList){
this.beverage = beverage;
this.toppingList = toppingList == null ? Collections.emptyList() : toppingList;
}
}
// tests part
class BeveragesPricingTest {
@Test
public void computes_no_beverage_price() {
Drink coffee = new Drink(null);
assertThat(coffee.price(), is(closeTo(0, 0.001)));
}
@Test
public void computes_coffee_price() {
Drink coffee = new Drink(new Coffee());
assertThat(coffee.price(), is(closeTo(1.20, 0.001)));
}
@Test
public void computes_tea_price() {
Drink tea = new Drink(new Tea());
assertThat(tea.price(), is(closeTo(1.50, 0.001)));
}
@Test
public void computes_hot_chocolate_price() {
Drink hotChocolate = new Drink(new HotChocolate());
assertThat(hotChocolate.price(), is(closeTo(1.45, 0.001)));
}
@Test
public void computes_tea_with_milk_price() {
Drink teaWithMilk = new Drink(new Tea(), List.of(new Milk()));
assertThat(teaWithMilk.price(), is(closeTo(1.60, 0.001)));
}
@Test
public void computes_coffee_with_milk_price() {
Drink coffeeWithMilk = new Drink(new Coffee(), List.of(new Milk()));
assertThat(coffeeWithMilk.price(), is(closeTo(1.30, 0.001)));
}
@Test
public void computes_coffee_with_milk_and_cream_price() {
Drink coffeeWithMilkAndCream = new Drink(new Coffee(), List.of(new Milk(), new Cream()));
assertThat(coffeeWithMilkAndCream.price(), is(closeTo(1.45, 0.001)));
}
@Test
public void computes_hot_chocolate_with_cream_price() {
Drink hotChocolateWithCream = new Drink(new HotChocolate(), List.of(new Cream()));
assertThat(hotChocolateWithCream.price(), is(closeTo(1.60, 0.001)));
}
@Test
public void computes_hot_chocolate_with_cream_and_cinnamon_price() {
Drink hotChocolateWithCreamCinnamon = new Drink(new HotChocolate(), List.of(new Cream(), new Cinnamon()));
assertThat(hotChocolateWithCreamCinnamon.price(), is(closeTo(1.65, 0.001)));
}
}
Votre équipe TakiVeille