Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Implementing DDD in your project

Implementing DDD in your project

This presentation shows a simple approach of a DDD implementation in your project.
Was exposed in PHP Barcelona first Monthly Talk (Barcelona)

Sergio Moya

June 11, 2014
Tweet

More Decks by Sergio Moya

Other Decks in Technology

Transcript

  1. Sergio Moya @soyelsergillo
    IN

    View full-size slide

  2. @SOYELSERGILLO GITHUB.COM/SMOYA
    Backend Engineer at Social Point
    !
    DDD Fan
    !
    Hip Hop Culture lover
    !
    Badaloní (from Badalona)
    SERGIO

    View full-size slide

  3. MODEL
    3
    2
    4
    1 DOMAIN CONTEXT
    UBIQUITOUS

    View full-size slide

  4. KNOW YOUR
    UBIQUITOUS LANGUAGE

    View full-size slide

  5. The Lead of the Backend engineers team has decided to split the team into smaller
    two-member teams.
    !
    Each team will develop a different component.
    !
    Our team will develop the Payment Component

    View full-size slide

  6. SERVICE
    ORM
    CONTRO
    LLER
    REPOSIT
    ORY DB
    MANAGER
    YOUR

    View full-size slide

  7. THIS IS WAR!

    View full-size slide

  8. BUT YOU WANT THIS

    View full-size slide

  9. BUT WE WANT THIS
    TODAY
    YOU WILL GET THIS

    View full-size slide

  10. …⋯
    SRC
    …⋯
    …⋯
    PAYMENTBUNDLE
    …⋯
    COMPONENT
    PAYMENT
    BUNDLE
    FILE

    View full-size slide

  11. We are recording Events!

    View full-size slide

  12. BUT
    WHAT IS A DOMAIN
    EVENT?

    View full-size slide

  13. REMEMBER
    A CUSTOMER CAN ORDER A PRODUCT
    !
    A CUSTOMER CAN PAY AN ORDER

    View full-size slide

  14. public function pay(Money $money)!
    {!
    try {!
    if (!$this->product->getPrice()->isEqualTo($money)) {!
    throw new OrderException('The Order amount is not satisfied');!
    }!
    $this->product->deliver($this->customer);!
    $this->status = OrderStatus::create(OrderStatus::ORDER_PAID);!
    } catch (\Exception $e) {!
    $this->status = OrderStatus::create(OrderStatus::ORDER_FAILED);!
    }!
    return $this->status;!
    }
    OUR

    View full-size slide

  15. interface OrderRepository!
    {!
    public function exists($id);!
    !
    public function find($id, $customerId);!
    !
    public function findByCustomerId($customerId);!
    !
    public function save($id, $productId, $customerId, $status = 1);!
    !
    public function remove($id);!
    !
    public function removeByCustomerId($customerId);!
    !
    public function clearAll();!
    }!
    OUR

    View full-size slide

  16. public function buyProductAction(Request $request)!
    {!
    $customer = new Customer($request->request->get('customerId'));!
    !
    $productRepository = $this->get('tato.payment.product_respository');!
    $product = $productRepository->find($request->request->get('productId'));!
    !
    $order = $customer->order($product);!
    !
    $paid = new Money(!
    $request->request->get('paid'), !
    $request->request->get(‘currency')!
    );!
    $status = $order->pay($paid);!
    !
    $this->get(‘tato.payment.order_repository')->save(!
    ! ! $order->getId(), !
    $product, !
    $customer->getId(), !
    $status->getStatus()!
    );!
    !
    return new JsonResponse(array('status' => $status->getStatus()));!
    }!
    }
    A

    View full-size slide

  17. public function buyProductAction(Request $request)!
    {!
    $customer = new Customer($request->request->get('customerId'));!
    !
    $productRepository = $this->get('tato.payment.product_respository');!
    $product = $productRepository->find($request->request->get('productId'));!
    !
    $order = $customer->order($product);!
    !
    $paid = new Money(!
    $request->request->get('paid'), !
    $request->request->get(‘currency')!
    );!
    $status = $order->pay($paid);!
    !
    $this->get(‘tato.payment.order_repository')->save(!
    ! ! $order->getId(), !
    $product, !
    $customer->getId(), !
    $status->getStatus()!
    );!
    !
    return new JsonResponse(array('status' => $status->getStatus()));!
    }!
    }
    A

    View full-size slide

  18. TAKE A PIECE OF
    CQRS
    COMMAND QUERY RESPONSIBILITY SEGREGATION

    View full-size slide

  19. Any method
    that mutates
    state.
    Any method
    that returns a
    value.
    COMMAND QUERY
    COMMAND

    View full-size slide

  20. class BuyProductCommand!
    {!
    public $customerId;!
    !
    public $productId;!
    !
    public $paid;!
    !
    public $currency;!
    !
    public function __construct($customerId, $productId, $paid, $currency)!
    {!
    $this->customerId = $customerId;!
    $this->productId = $productId;!
    $this->paid = $paid;!
    $this->currency = $currency;!
    } !
    }
    THE

    View full-size slide

  21. public function handle(BuyProductCommand $command)!
    {!
    $customer = new Customer($command->customerId);!
    $product = $this->productRepository->find($command->productId);!
    !
    $order = $customer->order($product);!
    $status = $order->pay(new Money($command->paid, $command->currency));!
    !
    $events = $customer->getRecordedEvents();!
    !
    // @todo do something with this events!
    !
    $this->orderRepository->setOrder(!
    $command->gatewayName,!
    $order->getId(),!
    $command->customerId,!
    $status->getStatus()!
    );!
    !
    return $order;!
    }
    A

    View full-size slide

  22. INFRASTRUCTURE

    View full-size slide

  23. SERVICES
    services:!
    tato.payment.order_repository:!
    class: Tato\Component\Game\CustomOrderRepository!
    arguments:!
    - @doctrine.orm.entity_manager!
    !
    tato.payment.product_repository:!
    class: Tato\Component\Game\Product\CustomProductRepository!
    arguments:!
    - @doctrine.orm.entity_manager!
    !
    tato.payment.command.handler.buy_product:!
    class: Tato\Component\Payment\Command\BuyProductCommandHandler!
    arguments:!
    order_repository: @tato.payment.order_repository!
    product_repository: @tato.payment.product_repository!

    View full-size slide

  24. public function buyProductAction(Request $request)!
    {!
    $customer = new Customer($request->request->get('customerId'));!
    !
    $productRepository = $this->get('tato.payment.product_respository');!
    $product = $productRepository->find($request->request->get('productId'));!
    !
    $order = $customer->order($product);!
    !
    $paid = new Money(!
    $request->request->get('paid'), !
    $request->request->get(‘currency')!
    );!
    $status = $order->pay($paid);!
    !
    $this->get(‘tato.payment.order_repository')->save(!
    ! ! $order->getId(), !
    $product, !
    $customer->getId(), !
    $status->getStatus()!
    );!
    !
    return new JsonResponse(array('status' => $status->getStatus()));!
    }!
    }
    THE

    View full-size slide

  25. BE HEXAGONAL!

    View full-size slide

  26. Sergio Moya @soyelsergillo
    THANKS
    I’M

    View full-size slide