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.

CQRS, ReactJS, Docker in a nutshell

912 views

Published on

An journey in the world of Domain Driven Design using Command Query Responsibility Segregation, React and Docker as a deployment tool

Published in: Engineering
  • Be the first to comment

CQRS, ReactJS, Docker in a nutshell

  1. 1. CQRS, REACTJS, DOCKERIN A NUTSHELL Andrea GiulianoClaudio D'Alicandro Simone Di Maulo
  2. 2. NEW AMAZING PROJECT
  3. 3. WE CAN WRITE IT FROM SCRATCH
  4. 4. BUT
  5. 5. immagine manager incazzato WE NEED IT IN A VERY FEW TIME
  6. 6. AND
  7. 7. IT SHOULD BE
  8. 8. WTF!
  9. 9. WHERE DO WE START?
  10. 10. COMFORT ZONE
  11. 11. DOMAIN ▸ data come from and go to external entities ▸ users can configure to send a subset of data ▸ users send data based on their plan send data from a source to a target GOAL
  12. 12. THE DOMAIN ▸ unpredictable data structures ▸ ad hoc workflow for each vendor ▸ variable number of steps ▸ handle rate limits from different vendors ▸ handle different error cases from different vendors ▸ handle business-oriented limits (based on plans...) ▸ some tasks need to be done asynchronously
  13. 13. IDEA
  14. 14. BLACK BOX REASONING ▸ identify the main entities involved ▸ define a common input and output ▸ find a way to let things talk INPUT OUTPUT
  15. 15. FROM BLACK BOXES TO BOUNDED CONTEXTS
  16. 16. DEPENDENCIES INFRA BC MODEL APPLICATION PRESENTATION
  17. 17. PROJECT DIRECTORY TREE
  18. 18. APP DIRECTORY TREE
  19. 19. INFRASTRUCTURE DIRECTORY TREE
  20. 20. INSIDE THE BOUNDED CONTEXT
  21. 21. BC DIRECTORY TREE
  22. 22. BC APPLICATION DIRECTORY TREE
  23. 23. BC MODEL DIRECTORY TREE
  24. 24. BC PRESENTATION DIRECTORY TREE
  25. 25. EVERYTHING'S AWESOME ▸ the framework is an implementation detail ▸ the directory structure is explicit ▸ the domain is isolated
  26. 26. WE DON'T WANT TO MESS THINGS UP
  27. 27. DON'T MESS UP THINGS
  28. 28. WHAT'S THE ISSUE HERE ▸ understandable? ▸ code can't be reused ▸ high coupling ▸ untestable ▸ too many responsibilities ▸ hard to find bugs ▸ not changes-prone
  29. 29. WHAT WE WANT
  30. 30. COMMAND QUERY RESPONSIBILITY SEGREGATIONAKA CQRS A SOLUTION
  31. 31. CQRS ▸ separe reads from writes ▸ commands perform actions ▸ queries return data ▸ heterogeneous data storages ▸ easy scaling ▸ deal with eventual consistency
  32. 32. WRITE STORAGE QUERY COMMAND COMMAND COMMAND BUS COMMAND HANDLER DOMAIN REPOSITORY READ STORAGE REPOSITORY EVENT BUS EVENT SUBSCRIBER
  33. 33. IT'S ALL ABOUT BUSES
  34. 34. IT'S ALL ABOUT BUSES COMMUNICATION
  35. 35. INTERNAL COMMUNICATION BC EVENT COMMAND
  36. 36. MESSAGE BUS $ composer require simple-bus/message-bus
  37. 37. COMMANDS COMMAND BUS Represent the change that should be done in the domain 
 They are named with a verb in the imperative tense and may include the aggregate type, for example ScheduleATask.
  38. 38. COMMANDS COMMAND BUS CONTROLLER $commandBus->handle(
 ScheduleATask::fromTaskId($taskId)
 ); HANDLER public function handle(Command $command)
 {
 //do something with the $command
 }
  39. 39. EVENTS BC 1 BC 2 EVENT BUS An event represents something that took place in the domain. 
 
 They are always named with a past-participle verb, such as TaskScheduled
  40. 40. EVENTS BC 1 BC 2 EVENT BUS subscribes_to: 'user-created' subscribes_to: 'task-stopped' subscribes_to: 'task-suspended'
  41. 41. EVENTS BC 1 BC 2 EVENT BUS $messageBus->handle(
 UserCreatedEvent::fromUser($user)
 ); subscribes_to: 'user-created' subscribes_to: 'task-stopped' subscribes_to: 'task-suspended' $messageBus->handle(
 TaskSuspendedEvent::fromTask($task)
 );
  42. 42. COMMUNICATION AMONG BCS BC 1 BC 2 QUEUE NETWORK
  43. 43. QUEUE BC 1 BC 2 QUEUE $producer->publish($message); $consumer->consume($message);
  44. 44. NETWORK BC 1 BC 2 NETWORK $httpClient->post('/tasks/schedule'); POST /tasks/schedule
  45. 45. SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES TIMER
  46. 46. SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES TIMER SCHEDULER POST /tasks/schedule
  47. 47. SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES TIMER SCHEDULER POST /tasks/schedule DATA STORAGE $taskRepository->getAll()
  48. 48. SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES TIMER SCHEDULER POST /tasks/schedule DATA STORAGE $taskRepository->getAll() TASK QUEUE enqueue($taskId)
  49. 49. SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES TIMER SCHEDULER POST /tasks/schedule DATA STORAGE $taskRepository->getAll() TASK QUEUE enqueue($taskId) W1 W2 W3 W..N...
  50. 50. LET ME SEE WHAT YOU HAVE DONE IT'S TIME TO SHOW DOWN
  51. 51. WHAT THE TEAM HAS DELIVERED
  52. 52. WHAT THE MANAGEMENT SEE
  53. 53. WHAT THE MANAGEMENT WANTS
  54. 54. LET'S START FROM THE TEMPLATE
  55. 55. TWIG
  56. 56. THE FRONTEND STUFF
  57. 57. THE FRONTEND STUFF ORDER DEPENDENT
  58. 58. THE FRONTEND STUFF GLOBAL SCOPE
  59. 59. <script>
 $('.btn').click(function(e){
 e.stopPropagation();
 
 // Do something cool!
 
 });
 </script> NEVER TRUST THE GLOBAL SCOPE
  60. 60. A STEP BACKWARD
  61. 61. WE ARE BACKEND DEVELOPERS
  62. 62. OUR COMFORT ZONE
  63. 63. OOP
  64. 64. ENCAPSULATION
  65. 65. MODULES
  66. 66. DEPENDENCY INJECTION
  67. 67. GOOD NEWS
  68. 68. ECMASCRIPT 6
  69. 69. DEFAULT VALUES
  70. 70. CLASSES
  71. 71. INHERITANCE
  72. 72. CREATE YOUR MODULES
  73. 73. IMPORT A MODULE
  74. 74. IMPORT ONLY WHAT YOU NEED
  75. 75. WHAT ABOUT THE UI?
  76. 76. var React = require('react');
 var ReactDOM = require('react-dom'); ReactDOM.render(
 <h1>Hello, world!</h1>,
 document.getElementById('app')
 );
  77. 77. https://kangax.github.io/compat-table/es6/
  78. 78. ASSETIC CUSTOM FILTERS
  79. 79. ANOTHER STEP BACKWARD
  80. 80. REMEMBER THE BOUNDED CONTEXT
  81. 81. A LOT OF SMALL COMPONENTS
  82. 82. A LOT OF SMALL APPLICATIONS
  83. 83. BOUNDED CONTEXT FACEBOOK BOUNDED CONTEXT MAILCHIMPBOUNDED CONTEXT MAPPING
  84. 84. BOUNDED CONTEXT FACEBOOK BOUNDED CONTEXT MAILCHIMPBOUNDED CONTEXT MAPPING
  85. 85. Gulp Bundler + BOUNDED CONTEXT FACEBOOK BOUNDED CONTEXT MAILCHIMPBOUNDED CONTEXT MAPPING
  86. 86. DEVELOPMENT WORKFLOW
  87. 87. $ docker/gulp docker-compose run --rm --entrypoint bash npm -c "gulp"
  88. 88. // gulpfile.js
 var gulp = require('gulp');
 var hub = require('gulp-hub'); process
 .env
 .WEBPACK_CONFIG_FILE = path.join(
 __dirname,
 'webpack.config.js'
 )
 ; hub(['src/**/gulpfile.js']);
  89. 89. BOUNDED CONTEXT FACEBOOK BOUNDED CONTEXT MAILCHIMPBOUNDED CONTEXT MAPPING gulpfile.js gulpfile.js gulpfile.js
  90. 90. BOUNDED CONTEXT FACEBOOK gulpfile.js "## FacebookPresentationBundle.php
 $## Resources
 "## assets
 "## config
 "## public
 $## views
  91. 91. $ app/console assets:install LET'S EXPOSE TO THE WEB
  92. 92. APPLICATION ENTRYPOINT
  93. 93. IT'S A BIG WORLD OUT THERE!
  94. 94. THE DEVELOPMENT ENVIRONMENT ▸ Easy to use so many technologies at no installation cost ▸ Prepare the scaffolding for a new developer is extremely simple ▸ Superior performances over previous systems
  95. 95. docker-compose.yml docker-compose.dev.yml
  96. 96. THE INFRASTRUCTURE
  97. 97. THE INFRASTRUCTURE
  98. 98. THE INFRASTRUCTURE
  99. 99. THE INFRASTRUCTURE
  100. 100. THE INFRASTRUCTURE VS
  101. 101. THE INFRASTRUCTURE VS
  102. 102. STAGE ▸ Automate image building ▸ Copy the same structure used in dev
  103. 103. STAGE ▸ Automate image building ▸ Copy the same structure used in dev
  104. 104. AUFS: VOLUMES MIGHT BE A LITTLE HARDER THAN IT SEEMS
  105. 105. SYMFONY PARAMETERS
  106. 106. incenteev/composer-parameter-handler
  107. 107. DOCKER CLOUD REPOSITORY CONFIGURATION
  108. 108. DATA ONLY CONTAINER
  109. 109. DATA ONLY CONTAINER
  110. 110. DATA ONLY CONTAINER
  111. 111. DATA ONLY CONTAINER
  112. 112. FIRST DEPLOY
  113. 113. AN ELEPHANT IN THE ROOM... WE NEED ▸ Automated deploy strategy ▸ The freedom to easily scale
  114. 114. SCALE $ docker-compose scale web=2 worker=3
  115. 115. HARD TRUTH fpm: image: 'adespresso/hubespresso-staging:fpm-latest' deployment_strategy: every_node sequential_deployment: true tags: - fpm - hubespresso - production volumes: - /var/www/project volumes_from: - shared-fpm.hubespresso-production SCALE CONTAINERS IS WORTHLESS IF YOU DO NOT SCALE NODES
  116. 116. HARD TRUTH SCALE CONTAINERS IS WORTHLESS IF YOU DO NOT SCALE NODES fpm: image: 'adespresso/hubespresso-staging:fpm-latest' deployment_strategy: every_node sequential_deployment: true tags: - fpm - hubespresso - production volumes: - /var/www/project volumes_from: - shared-fpm.hubespresso-production
  117. 117. DATA ONLY CONTAINER IS A PAIN
  118. 118. DEPLOYMENT ▸ deploy the infrastructure is not straightforward ▸ multiple container in multiple nodes ▸ every container has its own lifecycle ▸ we are not assuring zero-downtime on deployment
  119. 119. THE SOLUTION: GREEN BLUE DEPLOYMENT
  120. 120. THE SOLUTION: GREEN BLUE DEPLOYMENT
  121. 121. THE SOLUTION: GREEN BLUE DEPLOYMENT
  122. 122. CONCLUSION
  123. 123. CQRSPHP7 DOCKER REACTJS MONGODBWEBPACK GULP
  124. 124. LEAVE THE COMFORT ZONE
  125. 125. THANKS
  126. 126. QUESTIONS?

×