Skip to content

Commit 8beddba

Browse files
authored
Add value object examples (#66)
1 parent fd097bd commit 8beddba

File tree

4 files changed

+109
-0
lines changed

4 files changed

+109
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package pl.mperor.lab.java.clean.code.ddd.value.object;
2+
3+
import java.time.LocalDateTime;
4+
5+
record DateTimeRange(LocalDateTime start, LocalDateTime end) {
6+
7+
DateTimeRange {
8+
if (start == null || end == null) {
9+
throw new IllegalArgumentException("Date range start & end cannot be null!");
10+
}
11+
if (start.isAfter(end)) {
12+
throw new IllegalArgumentException("Date range start cannot be after end!");
13+
}
14+
}
15+
16+
boolean isWithinRange(LocalDateTime dateTime) {
17+
return !dateTime.isBefore(start) && !dateTime.isAfter(end);
18+
}
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package pl.mperor.lab.java.clean.code.ddd.value.object;
2+
3+
import java.util.regex.Pattern;
4+
5+
record EmailAddress(String email) {
6+
7+
private static final Pattern emailPattern = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
8+
9+
EmailAddress {
10+
if (email == null || emailPattern.asMatchPredicate().negate().test(email)) {
11+
throw new IllegalArgumentException("Invalid email address!");
12+
}
13+
}
14+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package pl.mperor.lab.java.clean.code.ddd.value.object;
2+
3+
import java.math.BigDecimal;
4+
import java.math.RoundingMode;
5+
6+
record Money(BigDecimal amount) {
7+
8+
Money(BigDecimal amount) {
9+
if (amount == null) {
10+
throw new IllegalArgumentException("Amount must not be null");
11+
}
12+
if (amount.compareTo(BigDecimal.ZERO) < 0) {
13+
throw new IllegalArgumentException("Amount cannot be negative!");
14+
}
15+
this.amount = setScale(amount);
16+
}
17+
18+
private BigDecimal setScale(BigDecimal input) {
19+
return input.setScale(2, RoundingMode.HALF_EVEN);
20+
}
21+
22+
public Money add(Money other) {
23+
return new Money(this.amount.add(other.amount));
24+
}
25+
26+
public Money subtract(Money other) {
27+
return new Money(this.amount.subtract(other.amount));
28+
}
29+
30+
public static Money of(BigDecimal amount) {
31+
return new Money(amount);
32+
}
33+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package pl.mperor.lab.java.clean.code.ddd.value.object;
2+
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.math.BigDecimal;
7+
import java.math.RoundingMode;
8+
import java.time.LocalDateTime;
9+
10+
11+
class ValueObjectTest {
12+
13+
@Test
14+
void shouldAllowToUseMoneyAsValueObject() {
15+
var money = Money.of(BigDecimal.ZERO);
16+
Assertions.assertEquals(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_EVEN), money.amount());
17+
18+
Assertions.assertThrows(IllegalArgumentException.class, () -> new Money(null));
19+
Assertions.assertThrows(IllegalArgumentException.class, () -> new Money(new BigDecimal("-1")));
20+
21+
var three = Money.of(BigDecimal.ONE).add(Money.of(BigDecimal.TWO));
22+
Assertions.assertEquals(new BigDecimal("3.00"), three.amount());
23+
Assertions.assertEquals(new BigDecimal("2.00"), three.subtract(Money.of(BigDecimal.ONE)).amount());
24+
}
25+
26+
@Test
27+
void shouldAllowToUseEmailAddressAsValueObject() {
28+
var email = new EmailAddress("[email protected]");
29+
Assertions.assertEquals("[email protected]", email.email());
30+
Assertions.assertThrows(IllegalArgumentException.class, () -> new EmailAddress(null));
31+
Assertions.assertThrows(IllegalArgumentException.class, () -> new EmailAddress("not an email @.wtf"));
32+
}
33+
34+
@Test
35+
void shouldAllowToUseDateTimeRangeAsValueObject() {
36+
Assertions.assertTrue(new DateTimeRange(LocalDateTime.MIN, LocalDateTime.MAX)
37+
.isWithinRange(LocalDateTime.now()));
38+
Assertions.assertTrue(new DateTimeRange(LocalDateTime.MIN, LocalDateTime.MAX)
39+
.isWithinRange(LocalDateTime.MIN));
40+
Assertions.assertTrue(new DateTimeRange(LocalDateTime.MIN, LocalDateTime.MAX)
41+
.isWithinRange(LocalDateTime.MAX));
42+
}
43+
}

0 commit comments

Comments
 (0)