← Назад к вопросам

Что есть внутри объектов для работы бизнес-процессов

2.2 Middle🔥 61 комментариев
#SOLID и паттерны проектирования#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что есть внутри объектов для работы бизнес-процессов

Объекты для работы бизнес-процессов — это основа, на которой строится вся логика приложения. Рассмотрю, что в них содержится и как они используются.

1. Entity классы (Сущности БД)

Это объекты, которые напрямую соответствуют таблицам в базе данных:

@Entity
@Table(name = "orders")
public class Order {
    // Идентификаторы
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // Бизнес-данные
    @Column(nullable = false)
    private String orderNumber;        // Номер заказа
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;         // Статус: NEW, PROCESSING, COMPLETED
    
    @Column(nullable = false)
    private BigDecimal totalAmount;     // Сумма заказа
    
    @Column(nullable = false)
    private LocalDateTime createdAt;    // Дата создания
    
    @Column
    private LocalDateTime completedAt;  // Дата завершения
    
    // Связи с другими сущностями
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    private User customer;              // Кто заказал
    
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<OrderItem> items;      // Товары в заказе
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "payment_id")
    private Payment payment;            // Платеж
    
    // Служебные поля
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt;    // Когда создан
    
    @Column(nullable = false)
    private LocalDateTime updatedAt;    // Когда изменен
    
    @Version
    private Long version;               // Для оптимистичной блокировки
    
    // Методы бизнес-логики
    public void cancel(String reason) {
        if (this.status != OrderStatus.NEW) {
            throw new InvalidOperationException("Can only cancel new orders");
        }
        this.status = OrderStatus.CANCELLED;
        this.cancelReason = reason;
    }
    
    public void complete() {
        if (this.status != OrderStatus.PROCESSING) {
            throw new InvalidOperationException("Can only complete processing orders");
        }
        this.status = OrderStatus.COMPLETED;
        this.completedAt = LocalDateTime.now();
    }
}

2. Value Objects (Объекты значений)

Это простые объекты, которые не имеют идентификатора и используются как значения:

// Встроенный Value Object
@Embeddable
public class Address {
    @Column(nullable = false)
    private String street;
    
    @Column(nullable = false)
    private String city;
    
    @Column(nullable = false)
    private String zipCode;
    
    @Column(nullable = false)
    private String country;
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Address)) return false;
        Address address = (Address) o;
        return Objects.equals(street, address.street) &&
               Objects.equals(city, address.city) &&
               Objects.equals(zipCode, address.zipCode) &&
               Objects.equals(country, address.country);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(street, city, zipCode, country);
    }
}

// Использование в Entity
@Entity
@Table(name = "users")
public class User {
    @Id
    private Long id;
    
    @Column(nullable = false)
    private String email;
    
    // Встроенный Value Object
    @Embedded
    private Address shippingAddress;
    
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "street", column = @Column(name = "billing_street")),
        @AttributeOverride(name = "city", column = @Column(name = "billing_city"))
        // ...
    })
    private Address billingAddress;
}

// Другой пример: Money Value Object
public class Money {
    private final BigDecimal amount;
    private final String currency;  // USD, EUR, RUB
    
    public Money(BigDecimal amount, String currency) {
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Amount cannot be negative");
        }
        this.amount = amount;
        this.currency = currency;
    }
    
    public Money add(Money other) {
        if (!this.currency.equals(other.currency)) {
            throw new IllegalArgumentException("Cannot add different currencies");
        }
        return new Money(this.amount.add(other.amount), this.currency);
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Money)) return false;
        Money money = (Money) o;
        return Objects.equals(amount, money.amount) &&
               Objects.equals(currency, money.currency);
    }
}

3. Data Transfer Objects (DTO)

Это объекты для передачи данных между слоями и по сети:

// Request DTO (входящие данные)
public class CreateOrderRequest {
    @NotEmpty(message = "Order items cannot be empty")
    private List<OrderItemRequest> items;  // Что заказывает клиент
    
    @NotNull(message = "Shipping address is required")
    private AddressDto shippingAddress;
    
    @NotNull(message = "Payment method is required")
    private String paymentMethod;           // CREDIT_CARD, PAYPAL
    
    // Getters
    public List<OrderItemRequest> getItems() { return items; }
    public AddressDto getShippingAddress() { return shippingAddress; }
    public String getPaymentMethod() { return paymentMethod; }
}

// Response DTO (исходящие данные)
public class OrderResponse {
    private Long id;
    private String orderNumber;
    private OrderStatus status;
    private BigDecimal totalAmount;
    private String currency;
    private LocalDateTime createdAt;
    private LocalDateTime completedAt;
    
    private UserResponse customer;         // Информация о покупателе
    private List<OrderItemResponse> items; // Товары в заказе
    private PaymentResponse payment;       // Информация о платеже
    
    // Getters
    public Long getId() { return id; }
    public String getOrderNumber() { return orderNumber; }
    // ...
}

// Пример маппинга Entity → DTO
@Service
public class OrderService {
    public OrderResponse getOrder(Long id) {
        Order order = orderRepository.findById(id)
            .orElseThrow(() -> new OrderNotFoundException(id));
        
        // Маппируем Entity в DTO
        return new OrderResponse(
            order.getId(),
            order.getOrderNumber(),
            order.getStatus(),
            order.getTotalAmount(),
            order.getCurrency(),
            order.getCreatedAt(),
            order.getCompletedAt(),
            mapUserToResponse(order.getCustomer()),
            mapItemsToResponse(order.getItems()),
            mapPaymentToResponse(order.getPayment())
        );
    }
}

4. Service Objects (Объекты для бизнес-логики)

Это объекты, которые содержат бизнес-логику:

// Сервис для работы заказов
@Service
public class OrderService {
    private final OrderRepository orderRepository;
    private final PaymentService paymentService;
    private final EmailService emailService;
    private final InventoryService inventoryService;
    
    // Процесс создания заказа
    @Transactional
    public OrderResponse createOrder(CreateOrderRequest request, Long userId) {
        // 1. Валидируем входные данные
        validateOrderRequest(request);
        
        // 2. Получаем пользователя
        User user = userService.getUserById(userId);
        
        // 3. Проверяем доступность товаров
        for (OrderItemRequest itemReq : request.getItems()) {
            Product product = productService.getProduct(itemReq.getProductId());
            if (product.getStock() < itemReq.getQuantity()) {
                throw new InsufficientStockException(product.getId());
            }
        }
        
        // 4. Создаем новый заказ
        Order order = new Order();
        order.setOrderNumber(generateOrderNumber());
        order.setStatus(OrderStatus.NEW);
        order.setCustomer(user);
        order.setTotalAmount(calculateTotal(request.getItems()));
        order.setShippingAddress(mapAddress(request.getShippingAddress()));
        
        // 5. Добавляем товары
        for (OrderItemRequest itemReq : request.getItems()) {
            OrderItem item = new OrderItem();
            item.setProduct(productService.getProduct(itemReq.getProductId()));
            item.setQuantity(itemReq.getQuantity());
            item.setPrice(item.getProduct().getPrice());
            order.addItem(item);
        }
        
        // 6. Сохраняем заказ
        order = orderRepository.save(order);
        
        // 7. Создаем платеж
        Payment payment = paymentService.createPayment(
            order.getTotalAmount(),
            request.getPaymentMethod(),
            user.getPaymentDetails()
        );
        order.setPayment(payment);
        orderRepository.save(order);
        
        // 8. Зарезервируем товары
        inventoryService.reserveItems(order);
        
        // 9. Отправляем уведомление
        emailService.sendOrderConfirmation(user.getEmail(), order);
        
        return mapToResponse(order);
    }
    
    // Процесс отмены заказа
    @Transactional
    public void cancelOrder(Long orderId, String reason) {
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new OrderNotFoundException(orderId));
        
        // Проверяем статус
        if (order.getStatus() != OrderStatus.NEW) {
            throw new InvalidOperationException("Cannot cancel completed order");
        }
        
        // Отменяем заказ
        order.cancel(reason);
        
        // Отменяем платеж
        if (order.getPayment() != null) {
            paymentService.refund(order.getPayment());
        }
        
        // Освобождаем зарезервированные товары
        inventoryService.unreserveItems(order);
        
        // Сохраняем изменения
        orderRepository.save(order);
        
        // Уведомляем пользователя
        emailService.sendCancellationNotification(order.getCustomer().getEmail(), order);
    }
}

5. Command Objects (Команды для операций)

Объекты, которые представляют операции/команды:

// Command для создания заказа
public class CreateOrderCommand {
    private final Long userId;
    private final List<OrderItemRequest> items;
    private final AddressDto shippingAddress;
    private final String paymentMethod;
    
    public CreateOrderCommand(Long userId, List<OrderItemRequest> items,
                             AddressDto shippingAddress, String paymentMethod) {
        this.userId = userId;
        this.items = items;
        this.shippingAddress = shippingAddress;
        this.paymentMethod = paymentMethod;
    }
    
    // Getters
}

// Command Handler
@Service
public class OrderCommandHandler {
    private final OrderService orderService;
    
    public OrderResponse handle(CreateOrderCommand command) {
        return orderService.createOrder(
            new CreateOrderRequest(command.getItems(), command.getShippingAddress(),
                                  command.getPaymentMethod()),
            command.getUserId()
        );
    }
}

6. Event Objects (События в системе)

Объекты, которые представляют события, произошедшие в системе:

// Событие: заказ создан
public class OrderCreatedEvent {
    private final Long orderId;
    private final String orderNumber;
    private final Long userId;
    private final BigDecimal amount;
    private final LocalDateTime createdAt;
    
    public OrderCreatedEvent(Long orderId, String orderNumber, Long userId,
                            BigDecimal amount, LocalDateTime createdAt) {
        this.orderId = orderId;
        this.orderNumber = orderNumber;
        this.userId = userId;
        this.amount = amount;
        this.createdAt = createdAt;
    }
}

// Event Listener
@Component
public class OrderEventListener {
    private final EmailService emailService;
    private final NotificationService notificationService;
    
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        // Отправить email
        emailService.sendOrderConfirmation(event);
        
        // Отправить уведомление
        notificationService.notify(event.getUserId(), 
            "Your order " + event.getOrderNumber() + " has been created");
    }
}

Итоговая структура объектов

Database Layer
    ↓
Entity Objects (Order, User, Product)
    ↓
Value Objects (Money, Address)
    ↓
Service Layer (OrderService, PaymentService)
    ↓
DTO Objects (CreateOrderRequest, OrderResponse)
    ↓
Command/Event Objects (CreateOrderCommand, OrderCreatedEvent)
    ↓
REST Controller
    ↓
Client

Каждый уровень отвечает за свою ответственность и содержит соответствующие данные и методы для работы с бизнес-процессами.

Что есть внутри объектов для работы бизнес-процессов | PrepBro