diff --git a/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/value/object/Money.java b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/value/object/Money.java index a6ff19f..b51d4e0 100644 --- a/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/value/object/Money.java +++ b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/ddd/value/object/Money.java @@ -3,9 +3,11 @@ import java.math.BigDecimal; import java.math.RoundingMode; -record Money(BigDecimal amount) { +public record Money(BigDecimal amount) { - Money(BigDecimal amount) { + public static Money ZERO = new Money(BigDecimal.ZERO); + + public Money(BigDecimal amount) { if (amount == null) { throw new IllegalArgumentException("Amount must not be null"); } @@ -27,6 +29,10 @@ public Money subtract(Money other) { return new Money(this.amount.subtract(other.amount)); } + public Money multiply(BigDecimal multiplier) { + return new Money(this.amount.multiply(multiplier)); + } + public static Money of(BigDecimal amount) { return new Money(amount); } diff --git a/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/grasp/GRASP.java b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/grasp/GRASP.java new file mode 100644 index 0000000..b48d8e9 --- /dev/null +++ b/CleanCode/src/main/java/pl/mperor/lab/java/clean/code/grasp/GRASP.java @@ -0,0 +1,8 @@ +package pl.mperor.lab.java.clean.code.grasp; + +/** + * General Responsibility Assignment Software Pattern (1997) + * - OOP design principles. + */ +public interface GRASP { +} diff --git a/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/value/object/ValueObjectTest.java b/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/value/object/ValueObjectTest.java index b1d1bf3..57e5ddd 100644 --- a/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/value/object/ValueObjectTest.java +++ b/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/ddd/value/object/ValueObjectTest.java @@ -21,7 +21,7 @@ class ValueObjectTest { @Test void shouldAllowToUseMoneyAsValueObject() { - var money = Money.of(BigDecimal.ZERO); + var money = Money.ZERO; Assertions.assertEquals(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_EVEN), money.amount()); Assertions.assertThrows(IllegalArgumentException.class, () -> new Money(null)); diff --git a/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/grasp/InformationExpertTest.java b/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/grasp/InformationExpertTest.java new file mode 100644 index 0000000..ce9b7fa --- /dev/null +++ b/CleanCode/src/test/java/pl/mperor/lab/java/clean/code/grasp/InformationExpertTest.java @@ -0,0 +1,68 @@ +package pl.mperor.lab.java.clean.code.grasp; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import pl.mperor.lab.java.clean.code.ddd.value.object.Money; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +/** + * 🤓 Information Expert + * + *

The principle states that a class should be responsible for behavior + * that is directly related to its data. + * + * This test verifies that: + *

+ * Each class encapsulates its own logic, following the principle of expert knowledge. + */ +class InformationExpertTest { + + record Cart(List order) { + Cart(Order... orders) { + this(Arrays.asList(orders)); + } + + Cart(List order) { + this.order = List.copyOf(order); + } + + Money totalCost() { + return order.stream() + .map(Order::totalPrice) + .reduce(Money.ZERO, Money::add); + } + } + + record Order(OrderItem item, int quantity) { + Order { + if (quantity < 1) { + throw new IllegalArgumentException("Quantity must be greater then 0!"); + } + } + + Money totalPrice() { + return item.price.multiply(BigDecimal.valueOf(quantity)); + } + } + + record OrderItem(String name, Money price) {} + + @Test + void cartShouldFollowInformationExpertPrinciple () { + var pencil = new OrderItem("Pencil", Money.of(BigDecimal.ONE)); + var rubber = new OrderItem("Rubber", Money.of(new BigDecimal("1.5"))); + var cart = new Cart( + new Order(pencil, 2), + new Order(rubber, 1) + ); + + Assertions.assertEquals(new Money(new BigDecimal("3.50")), cart.totalCost()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new Order(pencil, 0)); + } +}