Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Decoupling Ulabox.com
monolith
From CRUD to DDD
Aleix Vergés
Backend developer
Scrum Master
@avergess
aleix.verges@ulabox.com
1. What’s Ulabox?
2. Decoupling. Why?
/**
* @param Cart $cart
* @return Order $order
*/
public function createOrder(Cart $cart)
{
// Year 2011
$order = $this->m...
WTF!
Past
● CRUD doesn’t make sense anymore
● It had sense at the beginning
● Product, Logistic, Delivery, Cart, Customers, ......
Our solution
/**
* @param Cart $cart
*/
public function createOrder(Cart $cart)
{
$createOrder = new CreateOrderCommand(Ca...
3. The tools
● Domain
● Aggregate / Aggregate Root
● Repository
● Domain Events
● Service
● Command Bus
● Event Bus
* Domain Drive Desi...
4. A responsability question
Refactoring and manage technical debt is
not a choice, but a responsability
Decoupling Ulabox.com monolith. From CRUD to D...
5. Controllers
REFUND!
5.1. OrderController
5. Controllers
class OrderController extends BaseController
{
public function refundAction(Request $request, $id)
{
$em = $this->containe...
Decoupling Ulabox.com monolith. From CRUD to DDD
Problems
● Hidden dependencies
● Inheritance.
● Biz logic in the controll...
* Dependency Injection: https://es.wikipedia.org/wiki/Inyecci%C3%B3n_de_dependencias
Decoupling Ulabox.com monolith. From ...
5.2. Controller as a service
5. Controllers
# services.yml
imports:
- { resource: controllers.yml }
# controllers.yml
ulabox_ulaoffice.controllers.order:
class: Ulabo...
5. Controllers
5.3. Dependency Injection
/**
* @Route("/orders", service="ulabox_ulaoffice.controllers.order")
*/
class OrderController
{
/**
* @param Refund $refu...
5. Controllers
5.4. Delegate logic to services
/**
* @Route("/orders", service="ulabox_ulaoffice.controllers.order")
*/
class OrderController
{
public function refundAct...
5. Controllers
5.5. Unit test
class OrderControllerTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->refund = $this->prophesize...
class OrderControllerTest extends PHPUnit_Framework_TestCase
{
...
public function testShouldDelegateOrderRefund()
{
$orde...
6. Symfony Forms
RESCHEDULE
6. Symfony Forms
6.1. Anemic Model
class OrderController extends BaseController
{
public function rescheduleAction(Request $request, $id)
{
$order = $this->c...
Decoupling Ulabox.com monolith. From CRUD to DDD
Problems
● Coupling between entities and Symfony Forms.
● Anemic Model.
●...
Decoupling Ulabox.com monolith. From CRUD to DDD
Solutions
● Use of DTO/Command
● Reflect the Intention!
● Rich Domain.
● ...
6. Symfony Forms
6.2. Command !== CLI Command
class Reschedule
{
public $orderId;
public $addressId;
public $slotVars;
public $comments;
public function __construct($or...
6. Symfony Forms
6.3. Building the Form
class OrderController extends BaseController
{
public function rescheduleDisplayingAction(Request $request, $id)
{
$order ...
6. Symfony Forms
6.4. Submitting the Form
class OrderController extends BaseController
{
public function rescheduleUpdateAction(Request $request, $id)
{
$requestDat...
6. Symfony Forms
6.5. Unit test
class OrderControllerTest extends PHPUnit_Framework_TestCase
{
public function testShouldDelegateOrderRescheduleToCommandB...
7. From CRUD to DDD
7. From CRUD to DDD
7.1. Summing...
class OrderController extends BaseController
{
public function rescheduleUpdateAction(Request $request, $id)
{
$requestDat...
7. From CRUD to DDD
7.2. Handling
class RescheduleHandler extends CommandHandler
{
public function __construct( ... ) { ... }
public function handleReschedu...
Decoupling Ulabox.com monolith. From CRUD to DDD
Problems
● Biz logic out of domain.
● Aggregate access.
● Aggregate Root?...
Decoupling Ulabox.com monolith. From CRUD to DDD
Solutions
● Aggregate Root. Order or Delivery?
● Unique acces point to th...
7. From CRUD to DDD
7.3. Order or Delivery?
7. From CRUD to DDD
7.4. Aggregate access point
class RescheduleHandler extends CommandHandler
{
public function __construct( ... ) { ... }
public function handleReschedu...
7. From CRUD to DDD
7.5. Business logic
class Delivery implements AggregateRoot
{
public function reschedule(TimelineSlot $timelineSlot)
{
$this->setDate($timelin...
7. From CRUD to DDD
7.6. Unit test
class RescheduleHandlerTest extends PHPUnit_Framework_TestCase
{
public function testShouldRescheduleDelivery()
{
$deliver...
class DeliveryTest extends PHPUnit_Framework_TestCase
{
public function testShouldRescheduleDelivery()
{
$delivery = Order...
7. From CRUD to DDD
7.7. Domain event
DeliveryWasRescheduled
Delivery Order
Load
Slot
TimeStart
Date
OrderLine
Product
Tax
Deliveries Orders
8. Aggregates and Repositories
CREDIT CARDS
8. Aggregates and Repositories
8.1. Entity / Repository
class CustomerCreditcardModel
{
public function add($number, $type, $token = null, $expiryDate = null)
{
$customer = $this...
Decoupling Ulabox.com monolith. From CRUD to DDD
Problems
● Aggregate?
● CreditCardRepository???
● Unprotected Domain.
Decoupling Ulabox.com monolith. From CRUD to DDD
Solutions
● Which is the Aggregate?
● What’s the Intention?
● Testing
Customer
CreditCard
class Customer implements AggregateRoot
{
public function addCreditCard($number, $type, $token = '', $...
8. Aggregates and Repositories
8.2. RegisterCreditCard
class RegisterCreditCard
{
public $customerId;
public $cardNumber;
public $type;
public $token;
public $expiry;
public fun...
8. Aggregates and Repositories
8.3. RegisterCreditCardHandler
class RegisterCreditCardHandler extends CommandHandler
{
private $customerRepository;
private $eventBus;
public function _...
8. Aggregates and Repositories
8.4. Business rules
class Customer implements AggregateRoot
{
public function addCreditCard($number, $type, $token, $expiryDate)
{
if ($this->...
9. Learned lessons
This is not a Big-Bang
Decoupling Ulabox.com monolith. From CRUD to DDD
Aggregate Election
Decoupling Ulabox.com monolith. From CRUD to DDD
Communication
Decoupling Ulabox.com monolith. From CRUD to DDD
Team
Decoupling Ulabox.com monolith. From CRUD to DDD
¡¡¡Be a Professional!!!
Decoupling Ulabox.com monolith. From CRUD to DDD
@avergess
aleix.verges@ulabox.com
www.linkedin.com/in/avergess
Thank’s
Questions?
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
Upcoming SlideShare
Loading in …5
×

8

Share

Download to read offline

Decoupling the Ulabox.com monolith. From CRUD to DDD

Download to read offline

Experiences decoupling Ulabox.com codebase in order to ease the transition between a traditional CRUD model to a DDD model

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Decoupling the Ulabox.com monolith. From CRUD to DDD

  1. 1. Decoupling Ulabox.com monolith From CRUD to DDD
  2. 2. Aleix Vergés Backend developer Scrum Master @avergess aleix.verges@ulabox.com
  3. 3. 1. What’s Ulabox?
  4. 4. 2. Decoupling. Why?
  5. 5. /** * @param Cart $cart * @return Order $order */ public function createOrder(Cart $cart) { // Year 2011 $order = $this->moveCartToOrder($cart); $this->sendConfirmationEmail($order); $this->reindexSolr($order); $this->sendToWarehouse($order); // Year 2012 $this->sendToFinantialErp($order); $this->sendDonationEmail($order); // Year 2014 $this->sendToDeliveryRoutingSoftware($order); // Year 2015 $this->sendToJustInTimeSuppliers($order); // Year 2016 $this->sendToWarehouseSpoke($order); // WTF! $this->sendToShipLoadSoftware($order); // WTF!!!! } Decoupling Ulabox.com monolith. From CRUD to DDD Our problem
  6. 6. WTF!
  7. 7. Past ● CRUD doesn’t make sense anymore ● It had sense at the beginning ● Product, Logistic, Delivery, Cart, Customers, ... ● It’s not sustainable. Decoupling Ulabox.com monolith. From CRUD to DDD
  8. 8. Our solution /** * @param Cart $cart */ public function createOrder(Cart $cart) { $createOrder = new CreateOrderCommand(Cart $cart); $this->commandBus->dispatch($createOrder) } Event bus CreateOrder command OrderWasCreated event subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe subscribe Decoupling Ulabox.com monolith. From CRUD to DDD
  9. 9. 3. The tools
  10. 10. ● Domain ● Aggregate / Aggregate Root ● Repository ● Domain Events ● Service ● Command Bus ● Event Bus * Domain Drive Design: https://en.wikipedia.org/wiki/Domain-driven_design Decoupling Ulabox.com monolith. From CRUD to DDD
  11. 11. 4. A responsability question
  12. 12. Refactoring and manage technical debt is not a choice, but a responsability Decoupling Ulabox.com monolith. From CRUD to DDD
  13. 13. 5. Controllers
  14. 14. REFUND!
  15. 15. 5.1. OrderController 5. Controllers
  16. 16. class OrderController extends BaseController { public function refundAction(Request $request, $id) { $em = $this->container->get('doctrine.orm.entity_manager'); $orderPayment = $em->getRepository('UlaboxCoreBundle:OrderPayment')->find($id); $amount = $request->request->get('refund'); $data = $this->container->get('sermepa')->processRefund($orderPayment, $amount); $orderRefund = new OrderPayment(); $orderRefund->setAmount($amount); ... $em->persist($orderRefund); $em->flush(); return $this->redirectToRoute('order_show', ['id' => $orderPayment->getOrder()->getId()]); } public function someOtherAction(Request $request, $id) ... }
  17. 17. Decoupling Ulabox.com monolith. From CRUD to DDD Problems ● Hidden dependencies ● Inheritance. ● Biz logic in the controller. ● Non aggregate root. ● Difficult to test.
  18. 18. * Dependency Injection: https://es.wikipedia.org/wiki/Inyecci%C3%B3n_de_dependencias Decoupling Ulabox.com monolith. From CRUD to DDD Solutions ● Dependency Injection ● Break inheritance from base controller. ● Application services. ● Testing
  19. 19. 5.2. Controller as a service 5. Controllers
  20. 20. # services.yml imports: - { resource: controllers.yml } # controllers.yml ulabox_ulaoffice.controllers.order: class: UlaboxUlaofficeBundleControllerOrderController arguments: - '@refund' - '@router' ...
  21. 21. 5. Controllers 5.3. Dependency Injection
  22. 22. /** * @Route("/orders", service="ulabox_ulaoffice.controllers.order") */ class OrderController { /** * @param Refund $refund * @param RouterInterface $router */ public function __construct(Refund $refund, RouterInterface $router, ……..) { $this->refund = $refund; $this->router = $router; ... } }
  23. 23. 5. Controllers 5.4. Delegate logic to services
  24. 24. /** * @Route("/orders", service="ulabox_ulaoffice.controllers.order") */ class OrderController { public function refundAction(Request $request, $id) { $amount = $request->request->get('refund'); $method = $request->request->get('method'); $orderId = $request->request->get('order_id'); try { $this->refund->execute($orderId, $id, (float)$amount, $method); $this->session->getFlashBag()->add('success', 'Refund has been processed correctly'); } catch (Exception $e) { $this->session->getFlashBag()->add('danger', $e->getMessage()); } return new RedirectResponse($this->router->generate('order_show', ['id' => $orderId])); } }
  25. 25. 5. Controllers 5.5. Unit test
  26. 26. class OrderControllerTest extends PHPUnit_Framework_TestCase { public function setUp() { $this->refund = $this->prophesize(Refund::class); $this->router = $this->prophesize(RouterInterface::class); $this->orderController = new OrderController( $this->refund->reveal(), $this->router->reveal() ); } ... }
  27. 27. class OrderControllerTest extends PHPUnit_Framework_TestCase { ... public function testShouldDelegateOrderRefund() { $orderPaymentId = 34575; $amount = 10.95; $orderId = 12345; $orderRoute = 'some/route'; $request = $this->mockRequest($orderId, $orderPaymentId, $amount, $orderRoute); $this->refund ->execute($orderId, $orderPaymentId, $amount, PaymentPlatform::REDSYS) ->shouldBeCalled(); $this->router->generate('order_show', ['id' => $orderId])->willReturn($orderRoute); $actual = $this->orderController->refundAction($request->reveal(), $orderPaymentId); $this->assertEquals(new RedirectResponse($orderRoute), $actual); } }
  28. 28. 6. Symfony Forms
  29. 29. RESCHEDULE
  30. 30. 6. Symfony Forms 6.1. Anemic Model
  31. 31. class OrderController extends BaseController { public function rescheduleAction(Request $request, $id) { $order = $this->container->get('order')->reposition($id); $form = $this->createForm(new OrderType(), $order); $form->handleRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($order); $em->flush(); $request->getSession()->getFlashBag()->add('success', 'Your changes were saved!'); return $this->redirect($this->generateUrl('reschedule_success')); } return ['entity' => $entity, 'form' => $form->createView()]; } }
  32. 32. Decoupling Ulabox.com monolith. From CRUD to DDD Problems ● Coupling between entities and Symfony Forms. ● Anemic Model. ● Intention?
  33. 33. Decoupling Ulabox.com monolith. From CRUD to DDD Solutions ● Use of DTO/Command ● Reflect the Intention! ● Rich Domain. ● Testing.
  34. 34. 6. Symfony Forms 6.2. Command !== CLI Command
  35. 35. class Reschedule { public $orderId; public $addressId; public $slotVars; public $comments; public function __construct($orderId, $addressId, $slotVars, $comments) { $this->orderId = $orderId; $this->addressId = $addressId; $this->slotVars = $slotVars; $this->comments = $comments; } }
  36. 36. 6. Symfony Forms 6.3. Building the Form
  37. 37. class OrderController extends BaseController { public function rescheduleDisplayingAction(Request $request, $id) { $order = $this->orderRepository->get($id); $address = $order->deliveryAddress()->asAddress(); $rescheduleOrder = Reschedule::fromPayload([ 'order_id' => $order->getId(), 'address_id' => $address->getId(), 'slot_vars' => $order->deliverySlotVars(), 'comments' => $order->deliveryComments(), ]); $rescheduleForm = $this->formFactory->create(OrderRescheduleType::class, $rescheduleOrder); return ['order' => $order, 'form' => $rescheduleForm->createView()]; } }
  38. 38. 6. Symfony Forms 6.4. Submitting the Form
  39. 39. class OrderController extends BaseController { public function rescheduleUpdateAction(Request $request, $id) { $requestData = $request->get('order_reschedule'); $rescheduleOrder = Reschedule::fromPayload([ 'order_id' => $id, 'address_id' => $requestData['addressId'], 'slot_vars' => $requestData['slotVars'], 'comments' => $requestData['comments'], ]); $rescheduleForm = $this->formFactory->create(OrderRescheduleType::class, $rescheduleOrder); if ($rescheduleForm->isValid()) { $this->commandBus->dispatch($rescheduleOrder); } return new RedirectResponse($this->router->generate($this->entity Properties['route'])); } }
  40. 40. 6. Symfony Forms 6.5. Unit test
  41. 41. class OrderControllerTest extends PHPUnit_Framework_TestCase { public function testShouldDelegateOrderRescheduleToCommandBus() { $orderId = 12345; $addressId = 6789; $slotVars = '2016-03-25|523|2|15'; $comments = 'some comments'; $expectedRoute = 'http://some.return.url'; $request = $this->mockRequest($orderId, $addressId, $slotVars, $comments); $form = $this->mockForm(); $form->isValid()->willReturn(true); $this->router->generate('order')->willReturn($expectedRoute); $this->commandBus->dispatch(Argument::type(Reschedule::class))->shouldBeCalled(); $actual = $this->orderController->rescheduleUpdateAction($request->reveal(), $orderId); $this->assertEquals(new RedirectResponse($expectedRoute), $actual); } }
  42. 42. 7. From CRUD to DDD
  43. 43. 7. From CRUD to DDD 7.1. Summing...
  44. 44. class OrderController extends BaseController { public function rescheduleUpdateAction(Request $request, $id) { $requestData = $request->get('order_reschedule'); $rescheduleOrder = Reschedule::fromPayload([ 'order_id' => $id, 'address_id' => $requestData['addressId'], 'slot_vars' => $requestData['slotVars'], 'comments' => $requestData['comments'], ]); $rescheduleForm = $this->formFactory->create(OrderRescheduleType::class, $rescheduleOrder); if ($rescheduleForm>isValid()) { $this->commandBus->dispatch($rescheduleOrder); } return new RedirectResponse($this->router->generate($this->entity Properties['route'])); } }
  45. 45. 7. From CRUD to DDD 7.2. Handling
  46. 46. class RescheduleHandler extends CommandHandler { public function __construct( ... ) { ... } public function handleReschedule(Reschedule $rescheduleOrder) { $timeLineSlot = $this->slotManager->createTimelineSlotFromVars($rescheduleOrder->slotVars); $order = $this->orderRepository->get($rescheduleOrder->aggregateId); $delivery = $order->getOrderDelivery(); $delivery->setSlot($timeLineSlot->getSlot()); $delivery->setLoadTime($timeLineSlot->getLoadTime()); $delivery->setShift($timeLineSlot->getShift()->getShift()); ... $order->rescheduleDelivery($delivery); $this->orderRepository->save($order); $this->eventBus->publish($order->getUncommittedEvents()); } }
  47. 47. Decoupling Ulabox.com monolith. From CRUD to DDD Problems ● Biz logic out of domain. ● Aggregate access. ● Aggregate Root? ● Unprotected Domain.
  48. 48. Decoupling Ulabox.com monolith. From CRUD to DDD Solutions ● Aggregate Root. Order or Delivery? ● Unique acces point to the domain. ● Clear intention!! ● Testing.
  49. 49. 7. From CRUD to DDD 7.3. Order or Delivery?
  50. 50. 7. From CRUD to DDD 7.4. Aggregate access point
  51. 51. class RescheduleHandler extends CommandHandler { public function __construct( ... ) { ... } public function handleReschedule(Reschedule $rescheduleDelivery) { $timeLineSlot = $this->slotManager->createTimelineSlotFromVars($rescheduleDelivery->slotVars); $delivery = $this->deliveryRepository->get($rescheduleDelivery->deliveryId); $delivery->reschedule($timeLineSlot); $this->deliveryRepository->save($delivery); $this->eventBus->publish($delivery->getUncommittedEvents()); } }
  52. 52. 7. From CRUD to DDD 7.5. Business logic
  53. 53. class Delivery implements AggregateRoot { public function reschedule(TimelineSlot $timelineSlot) { $this->setDate($timelineSlot->getDate()); $this->setLoadTime($timelineSlot->getLoadTime()); $this->setSlot($timelineSlot->getSlot()); $this->setShift($timelineSlot->getShift()); $this->setLoad($timelineSlot->getLoad()); $this->setPreparation($timelineSlot->getPreparationDate()); $this->apply( new DeliveryWasRescheduled( $this->getAggregateRootId(), $this->getProgrammedDate(), $this->getTimeStart(), $this->getTimeEnd(), $this->getLoad()->spokeId() ) ); } }
  54. 54. 7. From CRUD to DDD 7.6. Unit test
  55. 55. class RescheduleHandlerTest extends PHPUnit_Framework_TestCase { public function testShouldRescheduleDelivery() { $deliveryId = 12345; $slotVars = '2016-03-25|523|2|15'; $timeLineSlot = TimelineSlotStub::random(); $delivery = $this->prophesize(Delivery::class); $this->deliveryRepository->get($deliveryId)->willReturn($delivery); $this->slotManager->createTimelineSlotFromVars($slotVars)->willReturn($timeLineSlot); $delivery->reschedule($timeLineSlot)->shouldBeCalled(); $this->deliveryRepository->save($delivery)->shouldBeCalled(); $this->eventBus->publish($this->expectedEvents())->shouldBeCalled(); $this->rescheduleOrderHandler->handleReschedule(new Reschedule($deliveryId, $slotVars)); } }
  56. 56. class DeliveryTest extends PHPUnit_Framework_TestCase { public function testShouldRescheduleDelivery() { $delivery = OrderDeliveryStub::random(); $timeLineSlot = TimelineSlotStub::random(); $delivery->reschedule($timeLineSlot); static::assertEquals($timeLineSlot->getDate(), $delivery->getProgrammedDate()); static::assertEquals($timeLineSlot->getLoadTime(), $delivery->getLoadTime()); static::assertEquals($timeLineSlot->getSlot(), $delivery->getSlot()); static::assertEquals($timeLineSlot->getShift(), $delivery->getShift()); static::assertEquals($timeLineSlot->getPreparationDate(), $delivery->getPreparation()); $messageIterator = $delivery->getUncommittedEvents()->getIterator(); $this->assertInstanceOf( DeliveryWasRescheduled::class, $messageIterator->current()->getPayload() ); } }
  57. 57. 7. From CRUD to DDD 7.7. Domain event
  58. 58. DeliveryWasRescheduled Delivery Order Load Slot TimeStart Date OrderLine Product Tax Deliveries Orders
  59. 59. 8. Aggregates and Repositories
  60. 60. CREDIT CARDS
  61. 61. 8. Aggregates and Repositories 8.1. Entity / Repository
  62. 62. class CustomerCreditcardModel { public function add($number, $type, $token = null, $expiryDate = null) { $customer = $this->tokenStorage->getToken()->getUser(); $creditCard = new CustomerCreditcard(); $creditCard->setNumber($number); $creditCard->setCustomer($customer); $creditCard->setType($type); $creditCard->setToken($token); $creditCard->setExpiryDate($expiryDate); $this->creditCardRepository->add($creditCard); return $creditCard; } }
  63. 63. Decoupling Ulabox.com monolith. From CRUD to DDD Problems ● Aggregate? ● CreditCardRepository??? ● Unprotected Domain.
  64. 64. Decoupling Ulabox.com monolith. From CRUD to DDD Solutions ● Which is the Aggregate? ● What’s the Intention? ● Testing
  65. 65. Customer CreditCard class Customer implements AggregateRoot { public function addCreditCard($number, $type, $token = '', $expiryDate = '') { $creditCard = CustomerCreditcard::create($number, $type, $token, $expiryDate); $this->creditCards->add($creditCard); $this->apply(new CreditCardWasRegistered($this->getAggregateRootId(), $number)); } } Decoupling Ulabox.com monolith. From CRUD to DDD
  66. 66. 8. Aggregates and Repositories 8.2. RegisterCreditCard
  67. 67. class RegisterCreditCard { public $customerId; public $cardNumber; public $type; public $token; public $expiry; public function __construct($customerId, $cardNumber, $type, $token, $expiry) { $this->customerId = $customerId; $this->cardNumber = $cardNumber; $this->type = $type; $this->token = $token; $this->expiry = $expiry; } }
  68. 68. 8. Aggregates and Repositories 8.3. RegisterCreditCardHandler
  69. 69. class RegisterCreditCardHandler extends CommandHandler { private $customerRepository; private $eventBus; public function __construct( ... ) { ... } public function handleRegisterCreditCard(RegisterCreditCard $registerCreditCard) { $customer = $this->customerRepository->get($registerCreditCard->customerId()) $customer->addCreditCard( $registerCreditCard->cardNumber(), $registerCreditCard->type(), $registerCreditCard->token(), $registerCreditCard->expiry() ); $this->customerRepository->save($customer); $this->eventBus->publish($customer->getUncommittedEvents()); } }
  70. 70. 8. Aggregates and Repositories 8.4. Business rules
  71. 71. class Customer implements AggregateRoot { public function addCreditCard($number, $type, $token, $expiryDate) { if ($this->creditCardExists($number, $type)) { $this->renewCreditCard($number, $type, $token, $expiryDate); return; } $creditCard = CustomerCreditcard::create($number, $type, $token, $expiryDate); $this->creditCards->add($creditCard); $this->apply(new CreditCardWasRegistered($this->getAggregateRootId(), $number)); } private function renewCreditCard($number, $type, $token, $expiryDate) { ... } }
  72. 72. 9. Learned lessons
  73. 73. This is not a Big-Bang Decoupling Ulabox.com monolith. From CRUD to DDD
  74. 74. Aggregate Election Decoupling Ulabox.com monolith. From CRUD to DDD
  75. 75. Communication Decoupling Ulabox.com monolith. From CRUD to DDD
  76. 76. Team Decoupling Ulabox.com monolith. From CRUD to DDD
  77. 77. ¡¡¡Be a Professional!!! Decoupling Ulabox.com monolith. From CRUD to DDD
  78. 78. @avergess aleix.verges@ulabox.com www.linkedin.com/in/avergess Thank’s Questions?
  • MikoajCzajkowski1

    Oct. 14, 2019
  • guolongcang

    Sep. 9, 2019
  • BeatEspiaDiaz

    Mar. 8, 2019
  • AlexKulina

    Jul. 27, 2018
  • powerirs

    Jun. 20, 2017
  • liopic

    Dec. 15, 2016
  • ginsen

    Sep. 22, 2016
  • joserpr

    Sep. 20, 2016

Experiences decoupling Ulabox.com codebase in order to ease the transition between a traditional CRUD model to a DDD model

Views

Total views

1,639

On Slideshare

0

From embeds

0

Number of embeds

291

Actions

Downloads

37

Shares

0

Comments

0

Likes

8

×