Mapping entity objects to domain interface
3
I have an interface in domain and two string infrastructure that represent that interface. the problem is, the interface cannot initiate in mapper class so I don't know how to map entity to domain in manual mapping. I started learning senior coding so I shouldn't use switch and should consider solid concepts. The codes I wrote:
OrderDiscount is an interface in domain
discountType, discountValue are in database. These feilds should map to orderDiscount
domain:
private Order(String id,
String customerId,
List items,
Money totalPrice,
OrderDiscount discount,
OrderStatus status,
LocalDateTime createdAt,
LocalDateTime updatedAt
)
public static Order create(String customerId,
List items,
OrderDiscount discount){
LocalDateTime now = LocalDateTime.now();
Money finalPrice = calculateFinalPrice(items, discount);
return new Order(
UUID.randomUUID().toString(),
customerId,
items,
finalPrice,
discount,
OrderStatus.PENDING,
now,
now);
}
public interface OrderDiscount {
Money applyTo(Money total);
OrderDiscountDetail getDetails();
DiscountType type();
}
public interface OrderDiscountFactory {
DiscountType supportedType();
OrderDiscount create(OrderDiscountDetail detail,Currency currency);
}
public final class FixedAmountDiscount implements OrderDiscount {
private final Money fixedAmountDiscount;
private FixedAmountDiscount(Money fixedAmountDiscount) {
if (fixedAmountDiscount == null) {
throw new IllegalArgumentException(
"Flat Discount cannot be null"
);
}
if (fixedAmountDiscount.getAmount().compareTo(BigDecimal.ZERO) factories;
public DiscountRegistry(List factories) {
this.factories =
factories.stream()
.collect(Collectors.toMap(
OrderDiscountFactory::supportedType,
Function.identity()));
}
public OrderDiscount create(OrderDiscountDetail detail, Currency currency) {
return factories
.get(detail.type())
.create(detail, currency);
}
}
public class FixedAmountDiscountFactory implements OrderDiscountFactory {
private final DiscountRegistry registry;
public FixedAmountDiscountFactory(DiscountRegistry registry) {
this.registry = registry;
}
@Override
public DiscountType supportedType() {
return DiscountType.FIXED_AMOUNT;
}
@Override
public OrderDiscount create(OrderDiscountDetail detail, Currency currency) {
return registry.create(detail, currency);
}
}
infrastructure/entity:
@Getter
@Enumerated(EnumType.STRING)
@Column(name = "discount_type", nullable = false, length = 30)
@NotNull(message = "discount type is required")
private DiscountType discountType = DiscountType.NONE;
@Getter
@Column(name = "discount_value", nullable = false, precision = 19, scale = 2)
@NotNull(message = "discount value is required")
private BigDecimal discountValue = BigDecimal.ZERO;
The orderMapper I wrote:
public class OrderMapper {
private final OrderDiscountFactory discountFactory;
public OrderMapper(OrderDiscountFactory discountFactory) {
this.discountFactory = discountFactory;
}
public static OrderEntity toEntity(Order order) {
OrderDiscountDetail discountDetail = order.getDiscount().getDetails();
OrderEntity entity = new OrderEntity(
order.getId(),
order.getCustomerId(),
order.getTotalPrice().getAmount(),
CurrencyMapper.toEntity(
order.getTotalPrice().getCurrency()
),
order.getStatus(),
discountDetail.type(),
discountDetail.value()
);
for (OrderItem orderItem : order.getItems()) {
entity.addItem(toItemEntity(orderItem));
}
return entity;
}
private static OrderItemEntity toItemEntity(OrderItem item) {
return new OrderItemEntity(
item.getProductId(),
item.getProductName(),
item.getQuantity(),
item.getPrice().getAmount(),
CurrencyMapper.toEntity(item.getPrice().getCurrency()));
}
public Order toDomain(OrderEntity entity) {
Currency currency = Currency.getInstance(entity.getCurrency());
Money money = Money.create(entity.getTotalAmount(), currency);
OrderDiscountDetail detail =
new OrderDiscountDetail(
entity.getDiscountType(),
entity.getDiscountValue()
);
OrderDiscount discount =
discountFactory.create(detail, currency);
List items = entity.getItems()
.stream()
.map(OrderItemMapper::toDomain)
.toList();
return Order.restore(
entity.getId(),
entity.getCustomerId(),
items,
money,
discount,
entity.getStatus(),
entity.getCreatedAt(),
entity.getUpdatedAt()
);
}
}
I found this mapper is bad because the mapper becomes domain-dependent. Please give me the enterprise level answer. I meanthe senior code.
Arianna Angeletti 118 1 silver badge11 bronze badges
asked Jun 22 at 11:56
F.M 551 2 gold badges9 silver badges22 bronze badges
5 0
I think the domain interface should remains pure. 'OrderDetail' belongs to Order domain:
public interface OrderDiscount {
Money applyTo(Money total);
DiscountType type();
}
answered Jun 22 at 15:29
peter8015 41 7 bronze badges
1 Comment
Start asking to get answers
Find the answer to your question by asking.