SlideShare a Scribd company logo
Command Bus To
DPC 2015
Awesome Town
Ross Tuck
Command Bus To Awesome Town
This is a story...
...about a refactoring.
$store->purchaseGame($gameId, $customerId);
Domain Model
Service
Controller
View
$store->purchaseGame($gameId, $customerId);
class BUYBUYBUYController
{
public function buyAction(Request $request)
{
$form = $this->getForm();
$form->bindTo($request);
if ($form->isTotallyValid()) {
$store->purchaseGame($gameId, $customerId);
return $this->redirect('thanks_for_money');
}
return ['so_many_errors' => $form->getAllTheErrors()];
}
}
class Store
{
public function purchaseGame($gameId, $customerId)
{
Assert::notNull($gameId);
Assert::notNull($customerId);
$this->security->allowsPurchase($customerId);
$this->logging->debug('purchasing game');
try {
$this->db->beginTransaction();
$purchase = new Purchase($gameId, $customerId);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
class Store
{
public function purchaseGame($gameId, $customerId)
{
$purchase = new Purchase($gameId, $customerId);
$this->repository->add($purchase);
}
}
$store->purchaseGame($gameId, $customerId);
->purchaseGame($gameId, $customerId);
$store
purchaseGame($gameId, $customerId);
$store->
purchaseGame $gameId, $customerId ;
$store-> ( )
purchaseGame $gameId $customerId
$store-> ( , );
purchaseGame $gameId $customerId
Data
purchaseGame $gameId $customerId
Intent
Information
purchaseGame $gameId $customerId
PurchaseGame $gameId $customerId
PurchaseGame($gameId, $customerId);
new PurchaseGame($gameId, $customerId);
new PurchaseGame($gameId, $customerId);
->getGameId();
->getCustomerId();
new PurchaseGame($gameId, $customerId);
Object
Message
People Paperwork→
Machines Messages→
Different types of messages
Command
Reserve Seat
Reserve Seat
Schedule Appointment
new PurchaseGame($gameId, $customerId);
Reserve Seat
Schedule Appointment
Data Structure
Why object?
+------------+--------------+
| Field | Type |
+------------+--------------+
| id | varchar(60) |
| indication | varchar(255) |
| arrived | tinyint(1) |
| firstName | varchar(255) |
| lastName | varchar(255) |
| birthDate | datetime |
+------------+--------------+
struct purchase_game {
int game_id;
int customer_id;
}
Map[Int, Int]
Tuple[Int, Int]
[
'game_id' => 42,
'customer_id' => 11
]
class PurchaseGame
{
public $gameId;
public $customerId;
}
class PurchaseGame
{
private $gameId;
private $customerId;
public function __construct($gameId, $customerId)
{
$this->gameId = $gameId;
$this->customerId = $customerId;
}
public function getGameId()
{
return $this->gameId;
}
public function getCustomerId()
{
return $this->customerId;
}
}
class PurchaseController
{
public function purchaseGameAction(Request $request)
{
$form = $this->createForm('purchase_game');
$form->bind($request);
if ($form->isValid()) {
$command = $form->getData();
}
}
}
We have intent...
...but no ability to carry out.
Command Handlers
Handlers handle commands
1:1 Command to Handler
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
Assert::notNull($command->getGameId());
Assert::notNull($command->getCustomerId());
$this->security->allowsPurchase($command->getCustomerId());
$this->logging->debug('purchasing game');
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
$this->logging->debug('purchasing game');
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
Command + Handler
$handler->handle(new PurchaseGame($gameId, $customerId));
$store->purchaseGame($gameId, $customerId);
“Extract To Message”
Command Message vs Command Pattern
$command = new PurchaseGame($gameId, $customerId);
$handler->handle($command);
Handler version
$command = new PurchaseGame($gameId, $customerId);
$command = new PurchaseGame($gameId, $customerId);
$command->execute();
Classical version
$command = new PurchaseGame($gameId, $customerId, $repository,
$db, $logger, $security);
$command->execute();
Classical version
●
Game ID
●
Customer ID
Purchase THIS game Purchase ANY game
●
Repository
●
Security
●
Logger
●
DB
I generally advocate Handlers
Connecting the Dots
Command Handler
class PurchaseController
{
public function purchaseGameAction()
{
// form stuff lol
$command = $form->getData();
$this->handler->handle($command);
}
}
Controller
Must be
the RIGHT handler
Mailman
Enter the Bus
Command Bus
Handler
Command Bus
Command
Handler
Command Bus
Command
Handler
Command Bus
Command
♥♥
♥
♥
♥
So, what is this command bus?
new CommandBus(
[
PurchaseGame::class => $purchaseGameHandler,
RegisterUser::class => $registerUserHandler
]
);
$command = new PurchaseGame($gameId, $customerId);
$commandBus->handle($command);
●
Over the Network
●
In a queue
●
Execute in process
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->handle($command);
}
}
Easier to Wire
Handler Freedom
It's just conventions
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->handle($command);
}
}
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->execute($command);
}
}
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->__invoke($command);
}
}
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$methodName = 'handle'.$name;
$this->handlers[$name]->{$methodName}($command);
}
}
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->handle($command);
}
}
class CommandBus
{
private $container = [];
public function __construct($container) {
$this->container = $container;
}
public function handle($command)
{
$name = get_class($command)."Handler";
if (!$this->container->has($name)) {
throw new Exception("No handler for $name");
}
$this->container->get($name)->handle($command);
}
}
It's just conventions
Plugins
Command Bus Uniform Interface→
->handle($command);
Decorator Pattern
Command Bus 3
Command Bus 2
Command Bus
Command Bus 1
Command Bus 3
Command Bus 2
Command Bus 3
Command Bus 2
Command Bus
Command Bus 3
Logging Command Bus
Command Bus
Transaction Command Bus
Logging Command Bus
Command Bus
interface CommandBus
{
public function handle($command);
}
class CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->handle($command);
}
}
class MyCommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->handle($command);
}
}
class MyCommandBus implements CommandBus
{
private $handlers = [];
public function __construct($handlers) {
$this->handlers = $handlers;
}
public function handle($command)
{
$name = get_class($command);
if (!isset($this->handlers[$name])) {
throw new Exception("No handler for $name");
}
$this->handlers[$name]->handle($command);
}
}
What to refactor out?
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
$this->logging->debug('purchasing game');
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
class LoggingDecorator implements CommandBus
{
private $logger;
private $innerBus;
public function __construct(Logger $logger, CommandBus $innerBus)
{
$this->logger = $logger;
$this->innerBus = $innerBus;
}
public function handle($command)
{
$this->logger->debug('Handling command '.get_class($command));
$this->innerBus->handle($command);
}
}
class LoggingDecorator implements CommandBus
{
private $logger;
private $innerBus;
public function __construct(Logger $logger, CommandBus $innerBus)
{
$this->logger = $logger;
$this->innerBus = $innerBus;
}
public function handle($command)
{
$this->innerBus->handle($command);
$this->logger->debug('Executed command '.get_class($command));
}
}
class LoggingDecorator implements CommandBus
{
private $logger;
private $innerBus;
public function __construct(Logger $logger, CommandBus $innerBus)
{
$this->logger = $logger;
$this->innerBus = $innerBus;
}
public function handle($command)
{
$this->logger->debug('Handling command '.get_class($command));
$this->innerBus->handle($command);
$this->logger->debug('Executed command '.get_class($command));
}
}
$commandBus = new LoggingDecorator(
$logger,
new MyCommandBus(...)
);
$commandBus->handle($command);
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
$this->logging->debug('purchasing game');
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
Ridiculously Powerful
Redonkulously Powerful
Why not Events?
Cohesion
Execution
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
Let's Decoratorize
TM
class TransactionDecorator implements CommandBus
{
private $db;
private $innerBus;
public function __construct($db, $innerBus)
{
$this->db = $db;
$this->innerBus = $innerBus;
}
public function handle($command)
{
try {
$this->db->beginTransaction();
$this->innerBus->handle($command);
$this->db->commitTransaction();
} catch (Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
The Handler?
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
try {
$this->db->beginTransaction();
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
$this->db->commitTransaction();
} catch(Exception $e) {
$this->db->rollbackTransaction();
throw $e;
}
}
}
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
}
}
...Wait, all the Commands?
Limiting which decorators run
Marker Interface
$this->security->allowsPurchase($command->getCustomerId());
interface PurchaseCommand
{
public function getCustomerId();
}
class PurchaseGame
{
private $gameId;
private $customerId;
// constructors, getters, etc
}
class PurchaseGame implements PurchaseCommand
{
private $gameId;
private $customerId;
// constructors, getters, etc
}
class AllowedPurchaseDecorator implements CommandBus
{
private $security;
private $innerBus;
public function __construct($security, $innerBus)
{
$this->security = $security;
$this->innerBus = $innerBus;
}
public function handle($command)
{
if ($command instanceof PurchaseCommand) {
$this->security->allowPurchase($command->getCustomerId());
}
$this->innerBus->handle($command);
}
}
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$this->security->allowsPurchase($command->getCustomerId());
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
}
}
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
}
}
class PurchaseGameHandler
{
public function handle(PurchaseGame $command)
{
$purchase = new Purchase(
$command->getGameId(),
$command->getCustomerId()
);
$this->repository->add($purchase);
}
}
Stop cutting!
Beyond Decorators
new AllowedPurchaseDecorator(
$security,
new TransactionDecorator(
$db,
new LoggingDecorator(
$logger,
new MyCommandBus(
[
PurchaseGame::class => $purchaseGameHandler
]
)
)
)
)
Constructor Parameter
Method
interface Middleware {
public function handle($command, callable $next);
}
class LoggingMiddleware implements Middleware
{
private $logger;
public function __construct($logger)
{
$this->logger = $logger;
}
public function handle($command, callable $next)
{
$this->logger->debug('handling '.get_class($command));
next($command);
}
}
new CommandBus(
[
new AllowedPurchaseMiddleware($security),
new TransactionMiddleware($db),
new LoggingMiddleware($logger),
new CommandHandlerMiddleware($handlerMapping),
]
);
5 Things That I Have Seen
Thing #1
Handling Commands in Commands
Domain Model
Service
Controller
View
PurchaseGameSendConfirmation
If it needs to happen with the command…
JUST CALL IT
If it needs to happen after the command…
Wait for a domain event
Thing #2
Reading From Commands
Or the lack thereof
“Command Bus should never return anything.”
Command Bus != CQRS
$commandBus->handle(new PurchaseGame($gameId, $customerId));
$store->purchaseGame($gameId, $customerId);
$commandBus->handle(new PurchaseGame($gameId, $customerId));
$id = $this
->domainEvents
->waitFor(GamePurchased::class)
->getId();
Thing #3
Reading with a Command Bus
$handler->handle(new PurchaseGame($gameId, $customerId));
$this->repository->findPurchaseById($id);
$this->readService->findPurchaseVerification($id);
$this->queryBus->find(new PurchaseById($id));
Thing #4
Command Buses Work Great in JS
commandBus.handle({
"command": "purchase_game",
"game_id": gameId,
"customer_id": customerId
});
Thing #5
Single Endpoint “REST”
/commands
/purchase-game
The Meta of Command Buses
Why are there 50 of them?
μ
function createBus($handlers) {
return function ($command) use ($handlers) {
$handlers[get_class($command)]($command);
};
}
$bus = createBus(
[
FooCommand::class => $someClosure,
BarCommand::class => $someOtherClosure
]
);
$cmd = new FooCommand();
$bus($cmd);
But you should use my library.
Command Bus Libraries are useless
...but the plugins aren't.
Me
tactician-doctrine
tactician-logger
named commands
locking
@sagikazarmark
tactician-bernard
tactician-command-events
@boekkooi tactician-amqp
@rdohms
@xtrasmal
@Richard_Tuin
tactician-bundle
@GeeH
@mike_kowalsky
tactician-module
Prasetyo Wicaksono
Eugene Terentev
Jildert Miedema
Nigel Greenway
Frank de Jonge
Ivan Habunek
tactician-service-provider
yii2-tactician
laravel-tactician
tactician-container
tactician-awesome-advice
tactician-pimple
Shared Interfaces
The Future of Tactician
● Simplify Interfaces
● Metadata
● Tracking
● RAD
Domain Model
Service
Controller
View
SimpleBus
Broadway
Command
Handler
Bus
Decorators
executes
connects extends
Command Handler
The End
Images
● http://bj-o23.deviantart.com/art/NOT-Rocket-Science-324795055
● sambabulli.blogsport.de
● https://www.youtube.com/watch?v=XHa6LIUJTPw
● http://khongthe.com/wallpapers/animals/puppy-bow-227081.jpg
● https://www.flickr.com/photos/emptyhighway/7173454/sizes/l
● https://www.flickr.com/photos/jronaldlee/5566380424
domcode.org
Ross Tuck
@rosstuck
joind.in/14219
PHPArchitectureTour.com

More Related Content

What's hot

Chap 4 PHP.pdf
Chap 4 PHP.pdfChap 4 PHP.pdf
Chap 4 PHP.pdf
HASENSEID
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
Rafael Dohms
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
Scott Wlaschin
 
Introdução a JPA (2010)
Introdução a JPA (2010)Introdução a JPA (2010)
Introdução a JPA (2010)
Helder da Rocha
 
Poo encapsulamento
Poo encapsulamentoPoo encapsulamento
Poo encapsulamento
Sedu
 
Clean code slide
Clean code slideClean code slide
Clean code slide
Anh Huan Miu
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
Scott Wlaschin
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytv
CodelyTV
 
Clean code
Clean codeClean code
Clean code
Arturo Herrero
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
Scott Wlaschin
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
Mario Fusco
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
Broadleaf Commerce
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
Vineet Kumar Saini
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
Kent Huang
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
Scott Wlaschin
 
Java if else condition - powerpoint persentation
Java if else condition - powerpoint persentationJava if else condition - powerpoint persentation
Java if else condition - powerpoint persentation
Maneesha Caldera
 
Kotlin coroutines
Kotlin coroutinesKotlin coroutines
Kotlin coroutines
Robert Levonyan
 

What's hot (20)

Chap 4 PHP.pdf
Chap 4 PHP.pdfChap 4 PHP.pdf
Chap 4 PHP.pdf
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 
Introdução a JPA (2010)
Introdução a JPA (2010)Introdução a JPA (2010)
Introdução a JPA (2010)
 
Poo encapsulamento
Poo encapsulamentoPoo encapsulamento
Poo encapsulamento
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytv
 
Php 101: PDO
Php 101: PDOPhp 101: PDO
Php 101: PDO
 
Clean code
Clean codeClean code
Clean code
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Broadleaf Presents Thymeleaf
Broadleaf Presents ThymeleafBroadleaf Presents Thymeleaf
Broadleaf Presents Thymeleaf
 
Php Tutorials for Beginners
Php Tutorials for BeginnersPhp Tutorials for Beginners
Php Tutorials for Beginners
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Oop concepts
Oop conceptsOop concepts
Oop concepts
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
 
Java if else condition - powerpoint persentation
Java if else condition - powerpoint persentationJava if else condition - powerpoint persentation
Java if else condition - powerpoint persentation
 
File Uploading in PHP
File Uploading in PHPFile Uploading in PHP
File Uploading in PHP
 
Kotlin coroutines
Kotlin coroutinesKotlin coroutines
Kotlin coroutines
 

Viewers also liked

Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
Ryan Weaver
 
Composer in monolithic repositories
Composer in monolithic repositoriesComposer in monolithic repositories
Composer in monolithic repositories
Sten Hiedel
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
Ross Tuck
 
Hexagonal architecture message-oriented software design
Hexagonal architecture   message-oriented software designHexagonal architecture   message-oriented software design
Hexagonal architecture message-oriented software design
Matthias Noback
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
Ross Tuck
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
Jean-Pierre Vincent
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsDavey Shafik
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
julien pauli
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
Rajat Pandit
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
Mark Baker
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
Matthias Noback
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
Marcello Duarte
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
afup Paris
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!tlrx
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
Marcello Duarte
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
Gabriele Bartolini
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Bruno Boucard
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
Arnauld Loyer
 

Viewers also liked (20)

Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
 
Composer in monolithic repositories
Composer in monolithic repositoriesComposer in monolithic repositories
Composer in monolithic repositories
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Hexagonal architecture message-oriented software design
Hexagonal architecture   message-oriented software designHexagonal architecture   message-oriented software design
Hexagonal architecture message-oriented software design
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Elastic Searching With PHP
Elastic Searching With PHPElastic Searching With PHP
Elastic Searching With PHP
 
Diving deep into twig
Diving deep into twigDiving deep into twig
Diving deep into twig
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
 

Similar to Command Bus To Awesome Town

Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
Sam Hennessy
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
Hugo Hamon
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
Krzysztof Menżyk
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
David Stockton
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
Hugo Hamon
 
The command dispatcher pattern
The command dispatcher patternThe command dispatcher pattern
The command dispatcher pattern
olvlvl
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
Abbas Ali
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
Arnaud Langlade
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
Yuya Takeyama
 
Functional programming with php7
Functional programming with php7Functional programming with php7
Functional programming with php7
Sérgio Rafael Siqueira
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
Konstantin Kudryashov
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
Rafael Dohms
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
Leonardo Proietti
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
Luiz Messias
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
eugenio pombi
 
Smelling your code
Smelling your codeSmelling your code
Smelling your code
Raju Mazumder
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
XSolve
 

Similar to Command Bus To Awesome Town (20)

Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
 
Symfony2 - extending the console component
Symfony2 - extending the console componentSymfony2 - extending the console component
Symfony2 - extending the console component
 
The command dispatcher pattern
The command dispatcher patternThe command dispatcher pattern
The command dispatcher pattern
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
Functional programming with php7
Functional programming with php7Functional programming with php7
Functional programming with php7
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Command-Oriented Architecture
Command-Oriented ArchitectureCommand-Oriented Architecture
Command-Oriented Architecture
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Smelling your code
Smelling your codeSmelling your code
Smelling your code
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
linieaire regressie
linieaire regressielinieaire regressie
linieaire regressie
 

Recently uploaded

Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
RinaMondal9
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
nkrafacyberclub
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Aggregage
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
Vlad Stirbu
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 

Recently uploaded (20)

Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Free Complete Python - A step towards Data Science
Free Complete Python - A step towards Data ScienceFree Complete Python - A step towards Data Science
Free Complete Python - A step towards Data Science
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptxSecstrike : Reverse Engineering & Pwnable tools for CTF.pptx
Secstrike : Reverse Engineering & Pwnable tools for CTF.pptx
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
Generative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionGenerative AI Deep Dive: Advancing from Proof of Concept to Production
Generative AI Deep Dive: Advancing from Proof of Concept to Production
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
Quantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIsQuantum Computing: Current Landscape and the Future Role of APIs
Quantum Computing: Current Landscape and the Future Role of APIs
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 

Command Bus To Awesome Town