Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!

5 985 vues

Publié le

Domain-driven Design in PHP and Symfony - Drupal Camp Wrocław 18/10/2014

Publié dans : Ingénierie
  • Hello! High Quality And Affordable Essays For You. Starting at $4.99 per page - Check our website! https://vk.cc/82gJD2
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici

Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!

  1. 1. Domain-Driven Design in PHP & Symfony
  2. 2. Kacper Gunia @cakper Software Engineer @SensioLabsUK Symfony Certified Developer PHPers Silesia @PHPersPL
  3. 3. Software is complex
  4. 4. How to tackle it?
  5. 5. Domain-Driven Design is ! an approach to the development of complex software in which we: –Eric Evans
  6. 6. 1. Focus on the core domain. –Eric Evans
  7. 7. 2. Explore model in ! a creative collaboration of domain practitioners and software practitioners. –Eric Evans
  8. 8. 3. Speak an ubiquitous language within an explicitly bounded context. –Eric Evans
  9. 9. When to use DDD?
  10. 10. Complex domain
  11. 11. Domain Experts
  12. 12. Iterative process
  13. 13. Object-Oriented Design
  14. 14. Strategic DDD
  15. 15. Strategy! ! Stratos - army/resources! Ago - leading
  16. 16. Strategy! ! ! = What
  17. 17. Bounded Context
  18. 18. Bounded contexts of product ❖ Catalogue! ❖ Sales! ❖Marketing! ❖Warehouse
  19. 19. Ubiquitous language
  20. 20. Core Domain
  21. 21. Supporting Domain
  22. 22. Model-Driven Design
  23. 23. Continuous Integration
  24. 24. UI SERVICE UNIT
  25. 25. Refactoring Towards Deeper Insight
  26. 26. Tactical DDD
  27. 27. Tactics! ! Taktike - the art of organising an army, a maneuver
  28. 28. Tactics! ! ! = How
  29. 29. Building Blocks
  30. 30. Layered architecture
  31. 31. USER INTERFACE APPLICATION DOMAIN INFRASTRUCTURE
  32. 32. . └── src └── Dcwroc ├── Shopping ├── Emejzon ├── EmejzonBundle └── DoctrineAdapter
  33. 33. Entities
  34. 34. class Sale { (…) private $id; ! function __construct($name, DateTimeInterface $dueDate) { $this-­‐>name = $name; $this-­‐>dueDate = $dueDate; } ! public function getId() { return $this-­‐>id; } }
  35. 35. class Sale { (…) public function activate() { if (true === $this-­‐>active) { throw new LogicException('Sale already activated!'); } ! $this-­‐>active = true; } }
  36. 36. Value objects
  37. 37. class Email { (…) public function __construct($email) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException(); } ! $this-­‐>email = $email; } ! function asString() { return $this-­‐>email; } }
  38. 38. Aggregates
  39. 39. class Order {(…) function __construct( Customer $customer, ProductList $productList ){ $this-­‐>customer = $customer; $this-­‐>productList = $productList; $this-­‐>status = Status::open(); } ! public function getTotal(); }
  40. 40. Repositories
  41. 41. interface OrderRepository { public function save(Order $order); ! public function remove(Order $order); public function findById($orderId); ! public function findObsolete(); }
  42. 42. class DoctrineOrderRepository implements OrderRepository {} ! class FileOrderRepository implements OrderRepository {} ! class InMemoryOrderRepository implements OrderRepository {}
  43. 43. Factories
  44. 44. class CustomerFactory { public function register(Email $email, Password $password) { (...) ! return $customer; } }
  45. 45. Services
  46. 46. interface Notifier { public function send(Message $message); }
  47. 47. class EmailNotifier implements Notifier { private $mailer; ! function __construct(Swift_Mailer $mailer) { $this-­‐>mailer = $mailer; } ! public function send(Message $message) { (…) } }
  48. 48. Domain Events
  49. 49. class ResetPassword { function request(Email $email) { $user = $this-­‐>userRepository-­‐>findOneByEmail($email); ! if (!$user instanceof User) { return $this-­‐>raise(new UserDoesNotExistEvent($email)); } ! $request = Password::requestReset($user); $this-­‐>passwordResetRequestRepository-­‐>save($request); $this-­‐>raise(new RequestIssuedEvent($request)); } }
  50. 50. class ResetPassword { function request(Email $email) { $user = $this-­‐>userRepository-­‐>findOneByEmail($email); ! if (!$user instanceof User) { return $this-­‐>raise(new UserDoesNotExistEvent($email)); } ! $request = Password::requestReset($user); $this-­‐>passwordResetRequestRepository-­‐>save($request); $this-­‐>raise(new RequestIssuedEvent($request)); } }
  51. 51. class ResetPassword { function request(Email $email) { $user = $this-­‐>userRepository-­‐>findOneByEmail($email); ! if (!$user instanceof User) { return $this-­‐>raise(new UserDoesNotExistEvent($email)); } ! $request = Password::requestReset($user); $this-­‐>passwordResetRequestRepository-­‐>save($request); $this-­‐>raise(new RequestIssuedEvent($request)); } }
  52. 52. class ResetPassword { function request(Email $email) { $user = $this-­‐>userRepository-­‐>findOneByEmail($email); ! if (!$user instanceof User) { return $this-­‐>raise(new UserDoesNotExistEvent($email)); } ! $request = Password::requestReset($user); $this-­‐>passwordResetRequestRepository-­‐>save($request); $this-­‐>raise(new RequestIssuedEvent($request)); } }
  53. 53. Modules
  54. 54. . └── Shopping └── Authentication ├── InvalidPasswordResetRequest.php ├── ResetPassword.php ├── PasswordResetRequest.php └── PasswordResetRequestRepository.php
  55. 55. Supple Design
  56. 56. Make behaviour obvious
  57. 57. Intention revealing interfaces
  58. 58. Design for change
  59. 59. Create software other developers want to work with
  60. 60. Ignore persistance
  61. 61. Domain model is always in a valid state
  62. 62. Command Pattern
  63. 63. class ChangeEmailCommand { public $email; public $customerId; }
  64. 64. class ChangeEmailCommandHandler { private $customerRepository; ! function __construct(CustomerRepository $customerRepository) { $this-­‐>customerRepository = $customerRepository; } ! public function handle(ChangeEmailCommand $command) { $customer = $this-­‐>customerRepository -­‐>findById($command-­‐>customerId); $customer-­‐>changeEmail($command-­‐>email); } }
  65. 65. Specification Pattern
  66. 66. interface Specification { public function isSatisfiedBy($object); }
  67. 67. class PayingCustomerSpecification implements Specification { public function isSatisfiedBy($object) { return $object instanceof Customer && $object-­‐>getAmountSpent() > 0.0; } }
  68. 68. class FreeDeliveryCalculator { private $specification; ! function __construct(Specification $specification) { $this-­‐>specification = $specification; } ! public function applyDiscount(Order $order) { $customer = $this-­‐>$order-­‐>getCustomer(); if ($this-­‐>specification-­‐>isSatisfiedBy($customer)) { $order-­‐>deliverForFree(); } } }
  69. 69. class FreeDeliveryCalculator { private $specification; ! function __construct(Specification $specification) { $this-­‐>specification = $specification; } ! public function applyDiscount(Order $order) { $customer = $this-­‐>$order-­‐>getCustomer(); if ($this-­‐>specification-­‐>isSatisfiedBy($customer)) { $order-­‐>deliverForFree(); } } }
  70. 70. Command-Query Responsibility Segregation
  71. 71. Commands
  72. 72. Use ORM to fetch/save aggregate roots
  73. 73. Queries
  74. 74. Use specialised queries and DTO’s to fetch presentation data
  75. 75. DDD Summary
  76. 76. Explore Domain Knowledge
  77. 77. With Domain Experts
  78. 78. By speaking Ubiquitous Language
  79. 79. Make use of Building Blocks
  80. 80. By applying Object-Oriented Design
  81. 81. Design for change
  82. 82. That’s the only constant!
  83. 83. “In order to create good software, you have to know what that software is all about.” –Eric Evans
  84. 84. Kacper Gunia Software Engineer Thanks! Symfony Certified Developer PHPers Silesia

×