Transactional Script: основа бизнес-логики
Сегодня мы рассмотрим паттерн Transactional Script — пожалуй, самый популярный и наиболее старый подход к организации бизнес-логики в приложениях. В простых сценариях и контекстах Domain Driven Design именно он будет часто и широко использоваться.
Этот паттерн был впервые формально описан Мартином Фаулером в его книге Patterns of Enterprise Application Architecture (2002), хотя самим подходом разработчики пользуются столько же, сколько существует программирование. Фаулер каталогизировал его как один из основных способов организации логики в корпоративных приложениях.
Суть паттерна предельно проста: каждый бизнес-сценарий выполняется в одной функции, которая получает входные данные, обрабатывает их, сохраняет результат и возвращает ответ. Но за этой простотой часто скрывается множество подводных камней, которые превращают ваш простой скрипт в сложный ком спагетти.
Давайте разберем все по порядку.
Как правильно писать transactional script
Давайте посмотрим, как организовать Transactional Script на «классическом» примере оформления заказа в интернет-магазине:
public class OrderService {
public OrderDto createOrder(CreateOrderRequest request) {
// 1. Валидация входных данных
validateRequest(request);
// 2. Создание заказа
Order order = new Order();
order.setCustomerId(request.getCustomerId());
order.setStatus(OrderStatus.CREATED);
order.setItems(request.getItems());
// 3. Расчёт итоговой цены
BigDecimal total = calculateTotal(request.getItems());
// 4. Применение скидки (если есть)
if (request.hasPromoCode()) {
PromoCode promo = promoRepository.findByCode(request.getPromoCode());
if (promo != null && promo.isValidFor(total)) {
total = total.subtract(promo.getDiscountAmount());
}
}
// 4.1. Установка итоговой цены
order.setTotal(total);
// 5. Сохранение
orderRepository.(order);save
// 6. Отправка события
eventPublisher.publish(new OrderCreatedEvent(order.getId()));
// 7. Возврат DTO
return toDto(order);
}
}
Ключевой принцип:
Вся бизнес-логика должна быть явно видна в одной функции — «скрипте» транзакции.
Можно выносить:
- валидацию,
- маппинг в DTO,
- обработку ошибок,
- технические детали (сохранение, публикация событий).
Но не стоит прятать саму суть операции — расчёт цены или применение скидки, в другие классы или методы без явной причины. Иначе логика «размазывается» и понять, что происходит становится сложно.
Сегодня мы рассмотрим паттерн Transactional Script — пожалуй, самый популярный и наиболее старый подход к организации бизнес-логики в приложениях. В простых сценариях и контекстах Domain Driven Design именно он будет часто и широко использоваться.
Этот паттерн был впервые формально описан Мартином Фаулером в его книге Patterns of Enterprise Application Architecture (2002), хотя самим подходом разработчики пользуются столько же, сколько существует программирование. Фаулер каталогизировал его как один из основных способов организации логики в корпоративных приложениях.
Суть паттерна предельно проста: каждый бизнес-сценарий выполняется в одной функции, которая получает входные данные, обрабатывает их, сохраняет результат и возвращает ответ. Но за этой простотой часто скрывается множество подводных камней, которые превращают ваш простой скрипт в сложный ком спагетти.
Давайте разберем все по порядку.
Как правильно писать transactional script
Давайте посмотрим, как организовать Transactional Script на «классическом» примере оформления заказа в интернет-магазине:
public class OrderService {
public OrderDto createOrder(CreateOrderRequest request) {
// 1. Валидация входных данных
validateRequest(request);
// 2. Создание заказа
Order order = new Order();
order.setCustomerId(request.getCustomerId());
order.setStatus(OrderStatus.CREATED);
order.setItems(request.getItems());
// 3. Расчёт итоговой цены
BigDecimal total = calculateTotal(request.getItems());
// 4. Применение скидки (если есть)
if (request.hasPromoCode()) {
PromoCode promo = promoRepository.findByCode(request.getPromoCode());
if (promo != null && promo.isValidFor(total)) {
total = total.subtract(promo.getDiscountAmount());
}
}
// 4.1. Установка итоговой цены
order.setTotal(total);
// 5. Сохранение
orderRepository.(order);save
// 6. Отправка события
eventPublisher.publish(new OrderCreatedEvent(order.getId()));
// 7. Возврат DTO
return toDto(order);
}
}
Ключевой принцип:
Вся бизнес-логика должна быть явно видна в одной функции — «скрипте» транзакции.
Можно выносить:
- валидацию,
- маппинг в DTO,
- обработку ошибок,
- технические детали (сохранение, публикация событий).
Но не стоит прятать саму суть операции — расчёт цены или применение скидки, в другие классы или методы без явной причины. Иначе логика «размазывается» и понять, что происходит становится сложно.
Просмотры: 10