π»[Code Review] OrderItem
κ΄λ ¨ ν΄λμ€λ€μ λν μ½λ 리뷰.
ποΈ μν€ν μ² λ° μ€κ³ (Architecture & Design)
DDD(λλ©μΈ μ£Όλ μ€κ³)μ νλΆν λλ©μΈ λͺ¨λΈ(Rich Domain Model) μ μλ²½νκ² κ΅¬νν λͺ¨λ²μ μΈ μν€ν μ²μ λλ€.
- Domain Entity : ν΅μ¬ λΉμ¦λμ€ λ‘μ§κ³Ό λ°μ΄ν°λ₯Ό ν¨κ» κ΄λ¦¬
- μ μ ν©ν 리 λ©μλ : 볡μ‘ν μμ± λ‘μ§μ μΊ‘μν
- μμ¨μ κ°μ²΄ : κ°μ²΄κ° μ€μ€λ‘ μμ μ μνμ νμλ₯Ό μ± μ
- μ°κ΄κ΄κ³ κ΄λ¦¬ : JPAλ₯Ό νμ©ν ν¨μ¨μ μΈ κ°μ²΄ κ΄κ³ λ§€ν
μ΄λ¬ν ꡬ쑰λ SOLIDμ λ¨μΌ μ± μ μμΉ(SRP) κ³Ό μΊ‘μν(Encapsulation) μμΉμ μλ²½νκ² λ§μ‘±νλ©°, λ¨μν λ°μ΄ν° λ©μ΄λ¦¬κ° μλ μ΄μμλ κ°μ²΄λ‘μμ μν μ μνν©λλ€.
β ν΄λμ€λ³ μμΈ λ¦¬λ·° (Detailed Class Review)
package com.kobe.productmanagement.domain;
import com.kobe.productmanagement.common.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "order_items")
public class OrderItem extends BaseTimeEntity {
@Id
@Column(length = 26)
private String orderItemId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
private Order order;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "product_id")
private Product product;
@Column(nullable = false)
private int quantity; // μ£Όλ¬Έ μλ
@Column(nullable = false)
private int orderPrice; // μ£Όλ¬Έ λΉμ κ°κ²©
@Builder
public OrderItem(String orderItemId,
Order order,
Product product,
int quantity,
int orderPrice
) {
this.orderItemId = orderItemId;
this.order = order;
this.product = product;
this.quantity = quantity;
this.orderPrice = orderPrice;
}
public static OrderItem createOrderItem(String orderItemId,
Order order,
Product product,
int quantity
) {
if (product.getStockQuantity() < quantity) {
throw new IllegalArgumentException("μνμ μ¬κ³ κ° λΆμ‘±ν©λλ€.");
}
OrderItem orderItem = OrderItem.builder()
.orderItemId(orderItemId)
.order(order)
.product(product)
.quantity(quantity)
.orderPrice(product.getProductRegularPrice()) // μμ± μμ μ μν κ°κ²©μ μ¬μ©
.build();
order.addOrderItem(orderItem);
return orderItem;
}
public int getTotalPrice() {
return getOrderPrice() * getQuantity();
}
}
1. OrderItem.java
(Domain Entity) - βοΈ ν΅μ¬
-
OOP/SOLID :
- κ°μ₯ μΉμ°¬νκ³ μΆμ λΆλΆ!!
-
createOrderItem
μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν΄ 볡μ‘ν μμ± λ‘μ§μ μλ²½νκ² μΊ‘μννμ΅λλ€. -
βμ¬κ³ κ° μΆ©λΆνμ§ νμΈβ νλ λΉμ¦λμ€ κ·μΉκ³Ό βμ£Όλ¬Έ μμ μ μν κ°κ²©μ μ μ₯β νλ μ€μν λ‘μ§μ΄
OrderItem
ν΄λμ€ λ΄λΆμ μλ²½νκ² μΊ‘μνλμμ΅λλ€. - μ΄λ‘μ¨ μλΉμ€ κ³μΈ΅μ
OrderItem
μ΄ μ΄λ»κ² μμ±λλμ§μ λν 볡μ‘ν κ³Όμ μ μ νμ μμ΄, λ¨μνOrderItem.createOrderItem(...)
μ νΈμΆνμ¬ μΌμ μμνκΈ°λ§ νλ©΄ λ©λλ€.
-
κ°μ²΄μ μμ¨μ± :
-
getTotalPrice()
λ©μλλ₯Ό ν΅ν΄OrderItem
μ΄ μκΈ° μμ μ μ΄κΈμ‘μ μ€μ€λ‘ κ³μ°νλλ‘ μ± μμ λΆμ¬νμ΅λλ€. - μ΄λ βλ°μ΄ν°μ κ·Έ λ°μ΄ν°λ₯Ό μ¬μ©νλ λ‘μ§μ νκ³³μ μμ΄μΌ νλ€βλ κ°μ²΄μ§ν₯μ κΈ°λ³Έ μμΉμ μλ²½νκ² λ°λ₯Έ κ²μ λλ€.
-
-
λ°μ΄ν° μ ν©μ± :
-
orderPrice
νλλ₯Ό μ ννκ² ν¬ν¨νμ¬, μν κ°κ²©μ΄ λ³λλλλΌλ κ³Όκ±° μ£Όλ¬Έ λ΄μμ λ°μ΄ν° μ ν©μ±μ μλ²½νκ² λ³΄μ₯νκ³ μμ΅λλ€.
-
-
JPA μ΅μ ν :
-
@ManyToOne
κ΄κ³ μ€μ κ³ΌFetchType.LAZY
λ₯Ό μ¬μ©ν μ±λ₯ μ΅μ ν λ± JPA μν°ν°λ‘μμ κΈ°λ³Έ μ€κ³κ° λ§€μ° νλ₯ν©λλ€.
-
π μΆκ° κ°μ μ μ (Enhancement Suggestions)
μ°κ΄κ΄κ³ νΈμ λ©μλ νμ©
Order
μ OrderItem
μ μλ°©ν₯ κ΄κ³λ₯Ό λ§Ίκ³ μμ΅λλ€. OrderItem
μ΄ μμ±λ λ, μμ μ μμ±ν Order
μ orderItems
리μ€νΈμ μ€μ€λ‘λ₯Ό μΆκ°νλ λ‘μ§μ λ£μ΄μ£Όλ©΄ λμ± μλ²½ν κ΅¬μ‘°κ° λ©λλ€.
// domain/OrderItem.java
public static OrderItem createOrderItem(String orderItemId,
Order order, // Order κ°μ²΄λ₯Ό νλΌλ―Έν°λ‘ λ°μ
Product product,
int quantity) {
if (product.getStockQuantity() < quantity) {
throw new IllegalArgumentException("μνμ μ¬κ³ κ° λΆμ‘±ν©λλ€.");
}
OrderItem orderItem = OrderItem.builder()
.orderItemId(orderItemId)
.product(product)
.quantity(quantity)
.orderPrice(product.getProductRegularPrice())
.build();
order.addOrderItem(orderItem); // Orderμ μ°κ΄κ΄κ³ νΈμ λ©μλ νΈμΆ
return orderItem;
}
// domain/Order.java
public class Order extends BaseTimeEntity {
// ...
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
//==μ°κ΄κ΄κ³ νΈμ λ©μλ==//
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
}
π μ΄ν
λ§€μ° νλ₯ν©λλ€ (Outstanding Implementation)
-
λ¨μν λ°μ΄ν°λ₯Ό λ΄λ κ²μ λμ΄, μμ μ μνμ κ΄λ ¨λ λΉμ¦λμ€ λ‘μ§κΉμ§ μ± μμ§λ μ§μ ν κ°μ²΄μ§ν₯μ μ½λλ₯Ό μμ±νμ ¨μ΅λλ€.
-
createOrderItem
μ μ ν©ν 리 λ©μλμgetTotalPrice
λ©μλλ μ΄ ν΄λμ€λ₯Ό λ¨μν μν°ν°κ° μλ, μ μ€κ³λ λλ©μΈ λͺ¨λΈλ‘ λ§λ ν΅μ¬μ μΈ μμμ λλ€. -
DDD(λλ©μΈ μ£Όλ μ€κ³)μ βνλΆν λλ©μΈ λͺ¨λΈ(Rich Domain Model)β μ κ΅κ³Όμμ μΌλ‘ ꡬνν λͺ¨λ²μ μΈ μ¬λ‘μ λλ€.
-
μ΄λ¬ν μ€κ³ λ°©μμ κΎΈμ€ν μ μ§ν΄ λκ°μ λ€λ©΄, μ μ§λ³΄μκ° μ©μ΄νκ³ νμ₯ κ°λ₯ν νλ₯ν μμ€ν μ΄ λ κ²μ λλ€.