CQRS, REACTJS, DOCKER
IN A NUTSHELL
Andrea Giuliano
Claudio D'Alicandro Simone Di Maulo
Slide 2
Slide 2 text
NEW AMAZING
PROJECT
Slide 3
Slide 3 text
WE CAN WRITE IT
FROM SCRATCH
Slide 4
Slide 4 text
BUT
Slide 5
Slide 5 text
immagine manager incazzato
WE NEED IT IN A VERY FEW TIME
Slide 6
Slide 6 text
AND
Slide 7
Slide 7 text
IT SHOULD BE
Slide 8
Slide 8 text
WTF!
Slide 9
Slide 9 text
WHERE DO WE
START?
Slide 10
Slide 10 text
COMFORT ZONE
Slide 11
Slide 11 text
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
Slide 12
Slide 12 text
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
Slide 13
Slide 13 text
IDEA
Slide 14
Slide 14 text
BLACK BOX REASONING
▸ identify the main entities involved
▸ define a common input and output
▸ find a way to let things talk
INPUT OUTPUT
Slide 15
Slide 15 text
FROM
BLACK BOXES
TO
BOUNDED CONTEXTS
Slide 16
Slide 16 text
DEPENDENCIES INFRA BC
MODEL
APPLICATION
PRESENTATION
Slide 17
Slide 17 text
PROJECT DIRECTORY TREE
Slide 18
Slide 18 text
APP DIRECTORY TREE
Slide 19
Slide 19 text
INFRASTRUCTURE DIRECTORY TREE
Slide 20
Slide 20 text
INSIDE THE
BOUNDED CONTEXT
Slide 21
Slide 21 text
BC DIRECTORY TREE
Slide 22
Slide 22 text
BC APPLICATION DIRECTORY TREE
Slide 23
Slide 23 text
BC MODEL DIRECTORY TREE
Slide 24
Slide 24 text
BC PRESENTATION DIRECTORY TREE
Slide 25
Slide 25 text
EVERYTHING'S AWESOME
▸ the framework is an
implementation detail
▸ the directory structure is
explicit
▸ the domain is isolated
Slide 26
Slide 26 text
WE DON'T WANT TO
MESS THINGS UP
Slide 27
Slide 27 text
DON'T MESS UP THINGS
Slide 28
Slide 28 text
WHAT'S THE ISSUE HERE
▸ understandable?
▸ code can't be reused
▸ high coupling
▸ untestable
▸ too many responsibilities
▸ hard to find bugs
▸ not changes-prone
Slide 29
Slide 29 text
WHAT WE WANT
Slide 30
Slide 30 text
COMMAND QUERY
RESPONSIBILITY
SEGREGATIONAKA CQRS
A SOLUTION
Slide 31
Slide 31 text
CQRS
▸ separe reads from writes
▸ commands perform actions
▸ queries return data
▸ heterogeneous data storages
▸ easy scaling
▸ deal with eventual consistency
Slide 32
Slide 32 text
WRITE STORAGE
QUERY
COMMAND
COMMAND
COMMAND BUS
COMMAND HANDLER
DOMAIN
REPOSITORY
READ STORAGE
REPOSITORY
EVENT BUS
EVENT SUBSCRIBER
Slide 33
Slide 33 text
IT'S ALL ABOUT
BUSES
Slide 34
Slide 34 text
IT'S ALL ABOUT
BUSES COMMUNICATION
Slide 35
Slide 35 text
INTERNAL COMMUNICATION
BC
EVENT
COMMAND
Slide 36
Slide 36 text
MESSAGE BUS
$ composer require simple-bus/message-bus
Slide 37
Slide 37 text
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.
Slide 38
Slide 38 text
COMMANDS
COMMAND BUS
CONTROLLER
$commandBus->handle(
ScheduleATask::fromTaskId($taskId)
);
HANDLER
public function handle(Command $command)
{
//do something with the $command
}
Slide 39
Slide 39 text
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
Slide 40
Slide 40 text
EVENTS
BC 1 BC 2
EVENT BUS
subscribes_to: 'user-created'
subscribes_to: 'task-stopped'
subscribes_to: 'task-suspended'
Slide 41
Slide 41 text
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)
);
Slide 42
Slide 42 text
COMMUNICATION AMONG BCS
BC 1 BC 2
QUEUE
NETWORK
Slide 43
Slide 43 text
QUEUE
BC 1 BC 2
QUEUE
$producer->publish($message); $consumer->consume($message);
Slide 44
Slide 44 text
NETWORK
BC 1 BC 2
NETWORK
$httpClient->post('/tasks/schedule');
POST /tasks/schedule
Slide 45
Slide 45 text
SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES
TIMER
Slide 46
Slide 46 text
SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES
TIMER SCHEDULER
POST /tasks/schedule
Slide 47
Slide 47 text
SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES
TIMER SCHEDULER
POST /tasks/schedule
DATA STORAGE
$taskRepository->getAll()
Slide 48
Slide 48 text
SCENARIO: TRIGGER THE TASKS SCHEDULE EVERY 10 MINUTES
TIMER SCHEDULER
POST /tasks/schedule
DATA STORAGE
$taskRepository->getAll()
TASK QUEUE
enqueue($taskId)
Slide 49
Slide 49 text
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
...
Slide 50
Slide 50 text
LET ME SEE WHAT
YOU HAVE DONE
IT'S TIME TO SHOW DOWN
Slide 51
Slide 51 text
WHAT THE TEAM HAS DELIVERED
Slide 52
Slide 52 text
WHAT THE MANAGEMENT SEE
Slide 53
Slide 53 text
WHAT THE MANAGEMENT WANTS
Slide 54
Slide 54 text
LET'S START FROM
THE TEMPLATE
Slide 55
Slide 55 text
TWIG
Slide 56
Slide 56 text
THE FRONTEND STUFF
Slide 57
Slide 57 text
THE FRONTEND STUFF
ORDER DEPENDENT
Slide 58
Slide 58 text
THE FRONTEND STUFF
GLOBAL SCOPE
Slide 59
Slide 59 text
$('.btn').click(function(e){
e.stopPropagation();
// Do something cool!
});
NEVER TRUST THE GLOBAL SCOPE
Slide 60
Slide 60 text
A STEP
BACKWARD
Slide 61
Slide 61 text
WE ARE BACKEND DEVELOPERS
Slide 62
Slide 62 text
OUR
COMFORT ZONE
Slide 63
Slide 63 text
OOP
Slide 64
Slide 64 text
ENCAPSULATION
Slide 65
Slide 65 text
MODULES
Slide 66
Slide 66 text
DEPENDENCY
INJECTION
Slide 67
Slide 67 text
GOOD NEWS
Slide 68
Slide 68 text
No content
Slide 69
Slide 69 text
ECMASCRIPT 6
Slide 70
Slide 70 text
DEFAULT VALUES
Slide 71
Slide 71 text
CLASSES
Slide 72
Slide 72 text
INHERITANCE
Slide 73
Slide 73 text
CREATE YOUR MODULES
Slide 74
Slide 74 text
IMPORT A MODULE
Slide 75
Slide 75 text
IMPORT ONLY WHAT YOU NEED
Slide 76
Slide 76 text
WHAT ABOUT THE UI?
Slide 77
Slide 77 text
No content
Slide 78
Slide 78 text
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
$ app/console assets:install
LET'S EXPOSE TO THE WEB
Slide 97
Slide 97 text
APPLICATION ENTRYPOINT
Slide 98
Slide 98 text
IT'S A BIG WORLD OUT THERE!
Slide 99
Slide 99 text
No content
Slide 100
Slide 100 text
No content
Slide 101
Slide 101 text
No content
Slide 102
Slide 102 text
No content
Slide 103
Slide 103 text
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
Slide 104
Slide 104 text
docker-compose.yml docker-compose.dev.yml
Slide 105
Slide 105 text
THE INFRASTRUCTURE
Slide 106
Slide 106 text
THE INFRASTRUCTURE
Slide 107
Slide 107 text
THE INFRASTRUCTURE
Slide 108
Slide 108 text
THE INFRASTRUCTURE
Slide 109
Slide 109 text
THE INFRASTRUCTURE
VS
Slide 110
Slide 110 text
THE INFRASTRUCTURE
VS
Slide 111
Slide 111 text
STAGE
▸ Automate image building
▸ Copy the same structure used in dev
Slide 112
Slide 112 text
STAGE
▸ Automate image building
▸ Copy the same structure used in dev
Slide 113
Slide 113 text
AUFS: VOLUMES MIGHT BE A LITTLE HARDER THAN IT SEEMS
Slide 114
Slide 114 text
SYMFONY PARAMETERS
Slide 115
Slide 115 text
incenteev/composer-parameter-handler
Slide 116
Slide 116 text
DOCKER CLOUD REPOSITORY CONFIGURATION
Slide 117
Slide 117 text
No content
Slide 118
Slide 118 text
No content
Slide 119
Slide 119 text
DATA ONLY CONTAINER
Slide 120
Slide 120 text
DATA ONLY CONTAINER
Slide 121
Slide 121 text
DATA ONLY CONTAINER
Slide 122
Slide 122 text
DATA ONLY CONTAINER
Slide 123
Slide 123 text
FIRST DEPLOY
Slide 124
Slide 124 text
AN ELEPHANT IN THE ROOM... WE NEED
▸ Automated deploy strategy
▸ The freedom to easily scale
Slide 125
Slide 125 text
SCALE
$ docker-compose scale \
web=2 \
worker=3
Slide 126
Slide 126 text
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
Slide 127
Slide 127 text
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
Slide 128
Slide 128 text
DATA ONLY CONTAINER IS A PAIN
Slide 129
Slide 129 text
No content
Slide 130
Slide 130 text
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