Command Object và DTO

⚠️ Đừng nhầm với Command Pattern của GoF. Ở đây “Command” được hiểu là Command Object / DTO (Data Transfer Object) - một class đơn giản gom toàn bộ input của một use case thành một đối tượng duy nhất, để truyền vào Application Service. (Nó gần với “command” trong CQRS - Command Query Responsibility Segregation hơn là pattern đóng gói-hành-động của GoF.)

📦 Ý tưởng

Thay vì truyền hàng loạt tham số rời rạc vào phương thức service, ta tạo một class biểu thị yêu cầu người dùng muốn thực hiện:

$command = new PlaceOrderCommand(
    $request->get('customer_id'),
    $request->get('items'),
    $request->get('email'),
);
$orderId = $placeOrderService->handle($command);
  • Tên class diễn đạt ý định nghiệp vụ: PlaceOrderCommand, CreateOrderCommand - “người dùng muốn tạo một đơn hàng mới”.
  • Constructor yêu cầu đủ thông tin → command luôn hợp lệ khi được tạo.
  • Chứa các thuộc tính + getter (customerId, items, email…).

✨ Lợi ích

  1. Code gọn gàng, truyền tải ý định rõ ràng - một đối tượng thay vì mớ tham số.
  2. Tách tầng web khỏi tầng ứng dụng. Controller chịu trách nhiệm chuyển đổi từ chi tiết giao thức (HTTP) sang command. Muốn thêm kênh mới (CLI, API mobile) → chỉ cần dựng PlaceOrderCommand tương ứng, không nhân đôi logic.
  3. Dễ validate và kiểm thử. Có thể kiểm tra tính hợp lệ của command trước khi đưa vào service (lớp Validator riêng). Trong unit test, tạo một PlaceOrderCommand mẫu + inject mock repository → gọi handle(), không cần dựng request giả hay môi trường web.

🔗 Bức tranh tổng

Data vào được gói trong command, logic xử lý nằm trong Application Service, data ra trả về dạng đơn giản (value object hoặc View Model). Controller/handler chỉ còn nhiệm vụ chuyển đổi dữ liệu và gọi dịch vụ.

Liên quan