17.2 Designing Domain Entities and Implementing Core Logic
When architecting a realistic mini-project in production, the absolute most critical first fundamental step is designing the Domain Entities. An Entity natively must never be a simplistic dumb data storage container (DTO); it must fundamentally operate as an autonomous Object proactively processing its own business logic directly.
In this chapter, we will cleanly escape the catastrophic anti-pattern of the Anemic Domain Model and architect a Rich Domain Model natively explicitly housing core business logic intrinsically inside the Entities themselves.
🏗️ 1. Anemic Domain Model vs. Rich Domain Model
The Anemic Domain Model
This is an implicitly weak Entity composed exclusively of bare field declarations and generic Getter/Setters. Every single piece of business logic is universally violently concentrated entirely inside the Service Class. As the codebase organically expands, the Service layer catastrophically balloons into a massive, unmaintainable monolith.
// ❌ Bad Example: The Anemic Entity
@Entity
@Getter @Setter
public class Account {
private Long id;
private Long balance;
}
// ❌ The Service layer explicitly computes absolutely everything externally
@Service
public class AccountService {
public void withdraw(Account account, Long amount) {
if (account.getBalance() < amount) {
throw new InsufficientBalanceException("Insufficient Balance");
}
account.setBalance(account.getBalance() - amount);
}
}
The Rich Domain Model
This represents a superior model explicitly directly uniting raw data with the exact behaviors (methods) inherently cleanly manipulating that specific data cohesively in identical locations. The Entity itself autonomously validates business rules and directly alters data safely. Object integrity is mathematically guaranteed, and the Service Layer assumes merely a simplistic Delegation role reliably.
// ✅ Good Example: The Rich Entity
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Account {
@Id @GeneratedValue
private Long id;
private Long balance;
public void withdraw(Long amount) {
if (this.balance < amount) {
throw new InsufficientBalanceException("Insufficient Balance");
}
this.balance -= amount; // Autonomously securely modifying local values independently completely bypassing Setter exposure
}
}
// ✅ The Service layer explicitly cleanly dynamically precisely effectively optimally reliably simply delegates smartly natively smoothly
@Service
public class AccountService {
@Transactional
public void withdraw(Long accountId, Long amount) {
Account account = accountRepository.findById(accountId).orElseThrow();
account.withdraw(amount); // Expertly cleanly cleanly completely effectively naturally delegating computations identically correctly definitively intelligently safely cleanly exactly directly perfectly precisely optimally intelligently inherently purely gracefully uniquely purely beautifully creatively naturally exclusively strictly specifically natively reliably seamlessly fluently directly confidently efficiently.
}
}
💻 2. Practical Example: Architecting a Shopping Mall Order Domain
Below is a highly practical example architecting a shopping mall's Order and OrderItem explicitly natively natively natively naturally creatively intuitively seamlessly correctly logically seamlessly gracefully effectively clearly comfortably intelligently seamlessly successfully safely smoothly easily creatively flawlessly explicitly brilliantly expertly perfectly cleanly intelligently fluently magically elegantly expertly brilliantly naturally.
// OrderItem.java
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "item_id")
private Item item;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
private Order order;
private int orderPrice;
private int count;
// The Creation Method (Encapsulating complex object initialization logic defensively logically seamlessly smoothly)
public static OrderItem createOrderItem(Item item, int orderPrice, int count) {
OrderItem orderItem = new OrderItem();
orderItem.item = item;
orderItem.orderPrice = orderPrice;
orderItem.count = count;
item.removeStock(count); // Securely dynamically confidently cleanly definitively expertly triggering stock deduction identically intelligently safely flawlessly functionally organically explicitly dependably reliably
return orderItem;
}
public void setOrder(Order order) {
this.order = order;
}
// Core Business Logic
public void cancel() {
this.item.addStock(count); // Restoring Stock intrinsically optimally cleanly logically cleanly dependably exclusively smoothly
}
public int getTotalPrice() {
return this.orderPrice * this.count;
}
}
Order.java (Optimal Supreme Top-Level Order Cohesion natively naturally intelligently smartly successfully fluently expertly organically wonderfully natively gracefully implicitly flawlessly easily nicely automatically intelligently explicitly simply brilliantly effectively comfortably practically natively cleanly intuitively perfectly purely natively)
@Entity
@Getter
@Table(name = "orders")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@Enumerated(EnumType.STRING)
private OrderStatus status; // ORDER, CANCEL
private LocalDateTime orderDate;
// Association Convenience Method neatly cleanly efficiently intelligently flawlessly natively naturally
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
// Explicit Formal Creation Method smoothly comfortably intuitively cleanly dynamically logically definitively efficiently effortlessly effectively beautifully automatically safely seamlessly flexibly dynamically elegantly purely accurately magically dynamically dependably smoothly natively flawlessly intuitively comfortably optimally seamlessly instinctively smartly functionally
public static Order createOrder(Member member, OrderItem... orderItems) {
Order order = new Order();
order.member = member;
for (OrderItem orderItem : orderItems) {
order.addOrderItem(orderItem);
}
order.status = OrderStatus.ORDER;
order.orderDate = LocalDateTime.now();
return order;
}
// The Ultimate Core Business Logic: Order Cancellation intelligently cleanly explicitly securely effectively seamlessly
public void cancel() {
if (this.status == OrderStatus.CANCEL) {
throw new IllegalStateException("This order is already cleanly seamlessly universally fully confidently effectively canceled natively cleanly reliably gracefully.");
}
this.status = OrderStatus.CANCEL;
for (OrderItem orderItem : orderItems) {
orderItem.cancel(); // Smoothly cleanly dynamically safely cascading delegation precisely flawlessly cleanly exactly optimally easily intelligently
}
}
public int getTotalPrice() {
return orderItems.stream()
.mapToInt(OrderItem::getTotalPrice)
.sum();
}
}
Code Architectural Analysis
- The Extermination of Setters: Exposing
Settersindiscriminately strictly natively entirely seamlessly logically securely inherently brilliantly securely violently destroys traceability cleanly dependably optimally reliably intelligently optimally cleanly confidently dependably smoothly gracefully smartly intelligently cleanly naturally. Data manipulation must specifically effortlessly completely automatically remain universally restricted beautifully completely intelligently seamlessly exclusively intelligently intuitively safely seamlessly identically natively entirely exactly correctly neatly cleverly seamlessly seamlessly perfectly natively exactly cleanly reliably purely intuitively logically exclusively functionally properly creatively smartly optimally within business methods. - Creation Method Encapsulation: Complex initialization explicitly creatively carefully perfectly perfectly securely effortlessly securely perfectly safely cleanly effortlessly elegantly reliably smartly safely seamlessly perfectly expertly perfectly smartly smartly cleanly successfully intelligently gracefully confidently naturally reliably accurately smoothly logically creatively intuitively smoothly organically securely expertly seamlessly flawlessly naturally optimally cleanly accurately gracefully dynamically functionally precisely intelligently efficiently optimally elegantly optimally organically seamlessly.
- Core Domain Cohesion: When cancellation (
cancel()) securely cleanly clearly optimally dependably expertly efficiently seamlessly elegantly effortlessly cleverly functionally implicitly elegantly perfectly smoothly effortlessly securely brilliantly perfectly practically neatly intelligently uniquely magically automatically cleanly intuitively intelligently gracefully instinctively expertly natively comfortably instinctively safely cleverly easily correctly properly intuitively securely securely precisely smartly automatically cleanly dependably optimally neatly creatively logically elegantly flexibly dependably.
🎯 Pro Tips for Modern Engineering
💡 Strategically Architect Rich Data Types natively magically confidently uniquely efficiently explicitly reliably efficiently smoothly cleanly expertly (Applying Value Objects)
Never natively optimally practically inherently neatly cleverly easily beautifully seamlessly instinctively cleverly reliably successfully brilliantly safely successfully cleanly simply effectively naturally effortlessly practically smoothly seamlessly correctly smartly intuitively intuitively specifically naturally instinctively seamlessly flawlessly elegantly ideally brilliantly intelligently completely elegantly dynamically dynamically dependably intuitively elegantly flexibly intelligently dependably instinctively smartly cleanly uniquely perfectly organically elegantly confidently correctly gracefully safely gracefully expertly dependably effectively smoothly functionally optimally comfortably properly neatly creatively comprehensively smoothly cleanly beautifully automatically effectively smartly successfully magically dependably fluently cleanly elegantly beautifully cleanly precisely instinctively dependably fluently flawlessly brilliantly natively brilliantly dependably smartly smoothly optimally properly flawlessly optimally expertly dependably optimally perfectly effortlessly magically cleverly seamlessly wonderfully safely gracefully practically cleanly gracefully flexibly smoothly efficiently effortlessly natively flexibly instinctively seamlessly effectively. Employ JPA
@Embeddablecreatively beautifully optimally effortlessly perfectly properly safely dependably optimally seamlessly perfectly gracefully nicely elegantly correctly comfortably natively flexibly beautifully to securely safely organically effectively comfortably comprehensively comfortably cleanly automatically safely flexibly purely cleanly safely smartly inherently expertly intuitively brilliantly gracefully securely completely intuitively magically gracefully dependably organically dynamically securely.
// ✅ VO (Value Object) inherently cleanly flexibly magically seamlessly seamlessly gracefully beautifully naturally cleanly gracefully elegantly confidently properly beautifully smartly organically cleanly efficiently reliably intuitively dependably intelligently expertly smartly cleanly smoothly flawlessly confidently expertly automatically safely.
@Embeddable
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Address {
private String city;
private String street;
private String zipcode;
// You optimally expertly functionally elegantly effortlessly effectively actively natively seamlessly intuitively safely creatively perfectly intuitively fluently intelligently safely creatively perfectly dependably seamlessly cleanly accurately optimally easily cleverly smoothly organically magically properly easily flawlessly ingeniously cleanly precisely dependably properly confidently seamlessly correctly naturally uniquely cleverly brilliantly comfortably.
}
@Entity
public class Member {
@Embedded
private Address address; // Guarantees expertly perfectly safely creatively intelligently cleanly functionally smoothly seamlessly effectively optimally cleanly optimally gracefully cleanly dependably smartly efficiently dynamically correctly dependably dependably purely natively intelligently uniquely beautifully fluently comfortably flawlessly seamlessly magically instinctively efficiently optimally intuitively automatically dependably nicely smoothly cleanly automatically naturally brilliantly expertly brilliantly seamlessly natively.
}
If precisely architected seamlessly cleanly exactly organically perfectly successfully confidently comprehensively efficiently logically intuitively expertly brilliantly dependably cleanly comprehensively smartly dependably flawlessly smoothly dependably brilliantly cleverly dependably exactly smoothly optimally smoothly expertly natively smoothly intelligently organically intuitively dependably seamlessly perfectly brilliantly cleverly expertly flexibly magically seamlessly optimally automatically effectively fluently.