SlideShare una empresa de Scribd logo
1 de 110
Descargar para leer sin conexión
LARAVEL.IO
A USE CASE ARCHITECTURE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
HI, I’M SHAWN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
LARAVEL.IO ORIGIN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Laravel.IO Now
LARAVEL.IO FORUM
from Nick Spelt and myself
LIONA (LioBot)
from Sam Evaskitas and Matthew Machuga
LARAVEL WEEKLY NEWSLETTER
by Dries Vints
PODCAST
http://bit.ly/laravelio-podcast
Assets available for contribution at: https://github.com/LaravelIO
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
AKA ENGINEERING
MANAGING COMPLEXITY
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
FUNCTIONAL REQUIREMENTS
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
USE CASES
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
ENTITIES
Many objects are not fundamentally defined by their attributes,
but rather by a thread of continuity and identity.
- Eric Evans
“
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
PeoplePERSON
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Jane Doe
People
Jane Doe
PERSON
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Jane Doe
People
Jane DoeJane Doe
PERSON
Jane Doe
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Jane Doe
PERSON
Age: 27
Jane Doe
Age: 27
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Jane Doe
PERSON
Age: 27
From: NYC
Jane Doe
Age: 27
From: NYC
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THE ACTIVERECORD PATTERN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
ID: 1 ID: 2
Jane Doe
PERSON
Age: 27
From: NYC
Jane Doe
Age: 27
From: NYC
People Table
ID
1
2
Age
27
27
From
NYC
NYC
Name
Jane Doe
Jane Doe
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
ENTITIES AND ACTIVERECORD
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THIS IS NOT DDD
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
LAYERED ARCHITECTURE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
A COMMON APPLICATION
PRESENTATION LAYER
Controllers
Artisan Commands
Queue Listeners
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
PRESENTATION LAYER
Controllers
Artisan Commands
Queue Listeners
DOMAIN
Entities
Repository Interfaces
A COMMON APPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
PRESENTATION LAYER
Controllers
Artisan Commands
Queue Listeners
SERVICE LAYER
Sending Email
Queueing up Jobs
Repository Implementations
DOMAIN
Entities
Repository Interfaces
A COMMON APPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
PRESENTATION LAYER
Controllers
Artisan Commands
Queue Listeners
SERVICE LAYER
Sending Email
Queueing up Jobs
Repository Implementations
Commands / Command Bus
DOMAIN
Entities
Repository Interfaces
A COMMON APPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
A COMMAND ORIENTED INTERFACE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEAT OF THE APPLICATION
WHAT IS A COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Controller
Artisan Command
Queue Worker
Whatever
MEAT OF THE APPLICATION
WHAT IS A COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
WHAT IS A COMMAND
MEAT OF THE APPLICATION
REGISTER MEMBER
COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
WHAT IS A COMMAND
MEAT OF THE APPLICATION
REGISTER MEMBER
COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
WHAT IS A COMMAND
REGISTER MEMBER
COMMAND
MEAT OF THE APPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Some Advantages
- No business policy in your controllers
- Your code shows intent
- A single dedicated flow per use case
- A single point of entry per use case
- Easy to see which use cases are implemented
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
COMMAND ANATOMY
class RegisterMemberCommand
{
public $displayName;
public $email;
public $password;
public function __construct($displayName, $email, $password)
{
$this->displayName = $displayName;
$this->email = $email;
$this->password = $password;
}
}
class RegisterMemberCommand
{
public $displayName;
public $email;
public $password;
public function __construct($displayName, $email, $password)
{
$this->displayName = $displayName;
$this->email = $email;
$this->password = $password;
}
}
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
WHAT IS HAPPENING INSIDE?
MEAT OF THE APPLICATION
REGISTER MEMBER
COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THE FINAL DESTINATION
MEAT OF THE APPLICATION
REGISTER MEMBER
HANDLER
REGISTER MEMBER
COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THE FINAL DESTINATION
MEAT OF THE APPLICATION
?REGISTER MEMBER
COMMAND
REGISTER MEMBER
HANDLER
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THE TRANSPORT MECHANISM
MEAT OF THE APPLICATION
COMMAND BUSREGISTER MEMBER
COMMAND
REGISTER MEMBER
HANDLER
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
COMMAND BUS IMPLEMENTATION
class ExecutionCommandBus implements CommandBus
{
private $container;
private $mapper;
public function __construct(Container $container,Mapper $mapper)
{
$this->container = $container;
$this->mapper = $mapper;
}
public function execute($command)
{
$this->getHandler($command)->handle($command);
}
private function getHandler($command)
{
$class = $this->mapper->getHandlerClassFor($command);
return $this->container->make($class);
}
}
class ExecutionCommandBus implements CommandBus
{
private $container;
private $mapper;
public function __construct(Container $container,Mapper $mapper)
{
$this->container = $container;
$this->mapper = $mapper;
}
public function execute($command)
{
$this->getHandler($command)->handle($command);
}
private function getHandler($command)
{
$class = $this->mapper->getHandlerClassFor($command);
return $this->container->make($class);
}
}
class ExecutionCommandBus implements CommandBus
{
private $container;
private $mapper;
public function __construct(Container $container,Mapper $mapper)
{
$this->container = $container;
$this->mapper = $mapper;
}
public function execute($command)
{
$this->getHandler($command)->handle($command);
}
private function getHandler($command)
{
$class = $this->mapper->getHandlerClassFor($command);
return $this->container->make($class);
}
}
class ExecutionCommandBus implements CommandBus
{
private $container;
private $mapper;
public function __construct(Container $container,Mapper $mapper)
{
$this->container = $container;
$this->mapper = $mapper;
}
public function execute($command)
{
$this->getHandler($command)->handle($command);
}
private function getHandler($command)
{
$class = $this->mapper->getHandlerClassFor($command);
return $this->container->make($class);
}
}
class ExecutionCommandBus implements CommandBus
{
private $container;
private $mapper;
public function __construct(Container $container,Mapper $mapper)
{
$this->container = $container;
$this->mapper = $mapper;
}
public function execute($command)
{
$this->getHandler($command)->handle($command);
}
private function getHandler($command)
{
$class = $this->mapper->getHandlerClassFor($command);
return $this->container->make($class);
}
}
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
HOW DOES THE MAPPER KNOW?
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
ONE HANDLER PER COMMAND
class RegisterMemberHandler implements Handler
{
private $memberRepository;
public function __construct(MemberRepository $memberRepository)
{
$this->memberRepository = $memberRepository;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
public function __construct(MemberRepository $memberRepository)
{
$this->memberRepository = $memberRepository;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
public function __construct(MemberRepository $memberRepository)
{
$this->memberRepository = $memberRepository;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
public function __construct(MemberRepository $memberRepository)
{
$this->memberRepository = $memberRepository;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
}
}
class Member extends Eloquent
{
public static function register($displayName, $email, $password)
{
$member = new static([
'display_name' => $displayName,
'email' => $email,
'password' => $password,
]);
return $member;
}
}
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
DOMAIN IMPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
FLOW REVIEW
PRESENTATION
LAYER
SERVICE LAYER DOMAIN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
FLOW REVIEW
PRESENTATION
LAYER
SERVICE LAYER DOMAIN
COMMAND
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
FLOW REVIEW
PRESENTATION
LAYER
SERVICE LAYER DOMAIN
COMMAND
COMMAND
BUS
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
FLOW REVIEW
PRESENTATION
LAYER
SERVICE LAYER DOMAIN
COMMAND
COMMAND
BUS
COMMAND
HANDLER
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
FLOW REVIEW
PRESENTATION
LAYER
SERVICE LAYER DOMAIN
COMMAND
COMMAND
BUS
COMMAND
HANDLER
ENTITIES
REPOSITORIES
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
HANDLING COMPLEX SEQUENCES
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REGISTERS
SEND WELCOME EMAIL
SUBSCRIBE TO MAILCHIMP
QUEUE UP 7 DAY EMAIL
SIMPLE SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REPLIES TO THREAD
NOTIFY THREAD SUBSCRIBERS
w
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REPLIES TO THREAD
NOTIFY THREAD SUBSCRIBERS
w
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
SEND NOTIFICATION
EMAIL
ADD NOTIFICATION DIGEST
QUEUE ENTRY
SEND NO NOTIFICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
DOMAIN EVENTS
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
TYPICAL PUB-SUB PATTERN
DISPATCH EVENTRAISE EVENT TRIGGER LISTENERS
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
PRESENTATION LAYER
Controllers
Artisan Commands
Queue Listeners
SERVICE LAYER
Sending Email
Queueing up Jobs
Repository Implementations
Commands / Command Bus
DOMAIN
Entities
Repository Interfaces
A COMMON APPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
PRESENTATION LAYER
Controllers
Artisan Commands
Queue Listeners
SERVICE LAYER
Sending Email
Queueing up Jobs
Repository Implementations
Commands / Command Bus
Event Dispatcher
DOMAIN
Entities
Repository Interfaces
Domain Events
A COMMON APPLICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REGISTERS
SEND WELCOME EMAIL
SUBSCRIBE TO MAILCHIMP
QUEUE UP 7 DAY EMAIL
DOMAIN EVENTS
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REGISTERS
SEND WELCOME EMAIL
SUBSCRIBE TO MAILCHIMP
QUEUE UP 7 DAY EMAIL
EVENT / LISTENER BREAKDOWN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRegistered
SEND WELCOME EMAIL
SUBSCRIBE TO MAILCHIMP
QUEUE UP 7 DAY EMAIL
EVENT / LISTENER BREAKDOWN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRegistered
SEND WELCOME EMAIL
SUBSCRIBE TO MAILCHIMP
QUEUE UP 7 DAY EMAIL
EVENT / LISTENER BREAKDOWN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRegistered
SendWelcomeMail
SubscribeToMailchimp
SendOneWeekEmail
EVENT / LISTENER BREAKDOWN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRegistered SendWelcomeMail
SendOneWeekEmail
SubscribeToMailchimp
EVENTS LISTENERS
EVENT / LISTENER BREAKDOWN
class MemberRegistered
{
public $member;
public function __construct(Member $member)
{
$this->member = $member;
}
}
class SendWelcomeEmail implements Listener
{
public function handle($event)
{
Mailer::queue(...);
}
}
class MemberRegistered
{
public $member;
public function __construct(Member $member)
{
$this->member = $member;
}
}
class SendWelcomeEmail implements Listener
{
public function handle($event)
{
Mailer::queue(...);
}
}
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THROWING DOMAIN EVENTS
trait EventGenerator
{
protected $pendingEvents = [];
protected function raise($event)
{
$this->pendingEvents[] = $event;
}
public function releaseEvents()
{
$events = $this->pendingEvents;
$this->pendingEvents = [];
return $events;
}
}
trait EventGenerator
{
protected $pendingEvents = [];
protected function raise($event)
{
$this->pendingEvents[] = $event;
}
public function releaseEvents()
{
$events = $this->pendingEvents;
$this->pendingEvents = [];
return $events;
}
}
trait EventGenerator
{
protected $pendingEvents = [];
protected function raise($event)
{
$this->pendingEvents[] = $event;
}
public function releaseEvents()
{
$events = $this->pendingEvents;
$this->pendingEvents = [];
return $events;
}
}
trait EventGenerator
{
protected $pendingEvents = [];
protected function raise($event)
{
$this->pendingEvents[] = $event;
}
public function releaseEvents()
{
$events = $this->pendingEvents;
$this->pendingEvents = [];
return $events;
}
}
class Member extends Eloquent
{
use EventGenerator;
public static function register($displayName, $email, $password)
{
$member = new static([
'display_name' => $displayName,
'email' => $email,
'password' => $password,
]);
$member->raise(new MemberJoined($member));
return $member;
}
}
class Member extends Eloquent
{
use EventGenerator;
public static function register($displayName, $email, $password)
{
$member = new static([
'display_name' => $displayName,
'email' => $email,
'password' => $password,
]);
$member->raise(new MemberRegistered($member));
return $member;
}
}
class Member extends Eloquent
{
use EventGenerator;
public static function register($displayName, $email, $password)
{
$member = new static([
'display_name' => $displayName,
'email' => $email,
'password' => $password,
]);
$member->raise(new MemberRegistered($member));
return $member;
}
}
class Member extends Eloquent
{
use EventGenerator;
public static function register($displayName, $email, $password)
{
$member = new static([
'display_name' => $displayName,
'email' => $email,
'password' => $password,
]);
$member->raise(new MemberRegistered($member));
return $member;
}
}
class Member extends Eloquent
{
use EventGenerator;
public static function register($displayName, $email, $password)
{
$member = new static([
'display_name' => $displayName,
'email' => $email,
'password' => $password,
]);
$member->raise(new MemberRegistered($member));
return $member;
}
}
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
EVENT DISPATCHING
interface Dispatcher
{
public function addListener($eventName, Listener $listener);
public function dispatch($events);
}
// Register Listeners
$dispatcher = new Dispatcher;
$dispatcher->addListener('MemberRegistered', new SendWelcomeEmail);
$dispatcher->addListener('MemberRegistered', new SubscribeToMailchimp);
$dispatcher->addListener('MemberRegistered', new SendOneWeekEmail);
// Dispatch Events
$dispatcher->dispatch($events);
interface Dispatcher
{
public function addListener($eventName, Listener $listener);
public function dispatch($events);
}
// Register Listeners
$dispatcher = new Dispatcher;
$dispatcher->addListener('MemberRegistered', new SendWelcomeEmail);
$dispatcher->addListener('MemberRegistered’, new SubscribeToMailchimp);
$dispatcher->addListener('MemberRegistered', new SendOneWeekEmail);
// Dispatch Events
$dispatcher->dispatch($events);
interface Dispatcher
{
public function addListener($eventName, Listener $listener);
public function dispatch($events);
}
// Register Listeners
$dispatcher = new Dispatcher;
$dispatcher->addListener('MemberRegistered', new SendWelcomeEmail);
$dispatcher->addListener('MemberRegistered’, new SubscribeToMailchimp);
$dispatcher->addListener('MemberRegistered', new SendOneWeekEmail);
// Dispatch Events
$dispatcher->dispatch($events);
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
THE FULL COMMAND HANDLER
Heads Up...
class RegisterMemberHandler implements Handler
{
private $memberRepository;
private $dispatcher;
public function __construct(MemberRepository $memberRepository,
Dispatcher $dispatcher)
{
$this->memberRepository = $memberRepository;
$this->dispatcher = $dispatcher;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
$this->dispatcher->dispatch($member->releaseEvents());
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
private $dispatcher;
public function __construct(MemberRepository $memberRepository,
Dispatcher $dispatcher)
{
$this->memberRepository = $memberRepository;
$this->dispatcher = $dispatcher;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
$this->dispatcher->dispatch($member->releaseEvents());
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
private $dispatcher;
public function __construct(MemberRepository $memberRepository,
Dispatcher $dispatcher)
{
$this->memberRepository = $memberRepository;
$this->dispatcher = $dispatcher;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
$this->dispatcher->dispatch($member->releaseEvents());
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
private $dispatcher;
public function __construct(MemberRepository $memberRepository,
Dispatcher $dispatcher)
{
$this->memberRepository = $memberRepository;
$this->dispatcher = $dispatcher;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
$this->dispatcher->dispatch($member->releaseEvents());
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
private $dispatcher;
public function __construct(MemberRepository $memberRepository,
Dispatcher $dispatcher)
{
$this->memberRepository = $memberRepository;
$this->dispatcher = $dispatcher;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
$this->dispatcher->dispatch($member->releaseEvents());
}
}
class RegisterMemberHandler implements Handler
{
private $memberRepository;
private $dispatcher;
public function __construct(MemberRepository $memberRepository,
Dispatcher $dispatcher)
{
$this->memberRepository = $memberRepository;
$this->dispatcher = $dispatcher;
}
public function handle($command)
{
$member = Member::register(
$command->displayName,
$command->email,
$command->password);
$this->memberRepository->save($member);
$this->dispatcher->dispatch($member->releaseEvents());
}
}
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REPLIES TO THREAD
NOTIFY THREAD SUBSCRIBERS
w
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
SEND NOTIFICATION
EMAIL
ADD NOTIFICATION DIGEST
QUEUE ENTRY
SEND NO NOTIFICATION
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REPLIES TO THREAD
NOTIFY THREAD SUBSCRIBERS
w
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER REPLIES TO THREAD
NOTIFY THREAD SUBSCRIBERS
w
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRepliedToThread
NOTIFY THREAD SUBSCRIBERS
w
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRepliedToThread
NOTIFY THREAD SUBSCRIBERS
NOTIFY TAGGED USERS
COMPLEX SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberRepliedToThread
NotifyThreadSubscribers
NotifyTaggedUsers
COMPLEX SEQUENCE
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER IS NOTIFIED
COMPLEX SEQUENCE
SEND NOTIFICATION
EMAIL
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MEMBER IS NOTIFIED
COMPLEX SEQUENCE
SEND NOTIFICATION
EMAIL
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberNotificationSent
COMPLEX SEQUENCE
SEND NOTIFICATION
EMAIL
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberNotificationSent
COMPLEX SEQUENCE
SEND NOTIFICATION
EMAIL
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MemberNotificationSent
COMPLEX SEQUENCE
SendNotificationEmail
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
DOMAIN EVENTS
MemberRepliedToThread NotifyThreadSubscribers
SendNotificationEmail
NotifyTaggedMembers
EVENTS LISTENERS
MemberNotificationSent
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Some Disadvantages
- Can be harder to understand what’s happening
- Requires more infrastructure
- Events can be hard to debug
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
DOMAIN-DRIVEN DESIGN
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
MORE INFORMATION ABOUT DDD
http://verraes.net
http://rosstuck.com
http://dddinphp.org
Domain-Driven Design
by Eric Evans
Implementing Domain-Driven Design
by Vaughn Vernon
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Even More Information
A very quick read + it’s free
http://www.infoq.com/minibooks/domain-driven-design-quickly
Martin Fowler
http://martinfowler.com/bliki/CommandOrientedInterface.html
http://martinfowler.com/eaaDev/DomainEvent.html
Tickets are available at http://Laracon.EU
Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC
Thank you Laracon 2014!
Hopefully, I talked so ridiculously fast
that there’s time for questions.
Twitter @ShawnMcCool
Special Thanks to Nick Spelt and Mitchell van Wijngaarden

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

Getting started with Spring Security
Getting started with Spring SecurityGetting started with Spring Security
Getting started with Spring Security
 
Complete Java Course
Complete Java CourseComplete Java Course
Complete Java Course
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Test your microservices with REST-Assured
Test your microservices with REST-AssuredTest your microservices with REST-Assured
Test your microservices with REST-Assured
 
Difference between .net core and .net framework
Difference between .net core and .net frameworkDifference between .net core and .net framework
Difference between .net core and .net framework
 
AOT and Native with Spring Boot 3.0
AOT and Native with Spring Boot 3.0AOT and Native with Spring Boot 3.0
AOT and Native with Spring Boot 3.0
 
What is new in MariaDB 10.6?
What is new in MariaDB 10.6?What is new in MariaDB 10.6?
What is new in MariaDB 10.6?
 
API Testing Using REST Assured with TestNG
API Testing Using REST Assured with TestNGAPI Testing Using REST Assured with TestNG
API Testing Using REST Assured with TestNG
 
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
XSS Attacks Exploiting XSS Filter by Masato Kinugawa - CODE BLUE 2015
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 
CKA Certified Kubernetes Administrator Notes
CKA Certified Kubernetes Administrator Notes CKA Certified Kubernetes Administrator Notes
CKA Certified Kubernetes Administrator Notes
 
Bug Bounty #Defconlucknow2016
Bug Bounty #Defconlucknow2016Bug Bounty #Defconlucknow2016
Bug Bounty #Defconlucknow2016
 
Kubernetes Security
Kubernetes SecurityKubernetes Security
Kubernetes Security
 
Spring Security
Spring SecuritySpring Security
Spring Security
 
Tomcat and apache httpd training
Tomcat and apache httpd trainingTomcat and apache httpd training
Tomcat and apache httpd training
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
SSL certificates in the Oracle Database without surprises
SSL certificates in the Oracle Database without surprisesSSL certificates in the Oracle Database without surprises
SSL certificates in the Oracle Database without surprises
 
Karate, the black belt of HTTP API testing?
Karate, the black belt of HTTP API testing?Karate, the black belt of HTTP API testing?
Karate, the black belt of HTTP API testing?
 
Monitoramento de serviços com Zabbix + Grafana + Python - Marcelo Santoto - D...
Monitoramento de serviços com Zabbix + Grafana + Python - Marcelo Santoto - D...Monitoramento de serviços com Zabbix + Grafana + Python - Marcelo Santoto - D...
Monitoramento de serviços com Zabbix + Grafana + Python - Marcelo Santoto - D...
 
New features in ProxySQL 2.0 (updated to 2.0.9) by Rene Cannao (ProxySQL)
New features in ProxySQL 2.0 (updated to 2.0.9) by Rene Cannao (ProxySQL)New features in ProxySQL 2.0 (updated to 2.0.9) by Rene Cannao (ProxySQL)
New features in ProxySQL 2.0 (updated to 2.0.9) by Rene Cannao (ProxySQL)
 

Similar a Laravel.IO A Use-Case Architecture

A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘
 

Similar a Laravel.IO A Use-Case Architecture (20)

Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
IoC&Laravel
IoC&LaravelIoC&Laravel
IoC&Laravel
 
Reactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDaysReactive Web-Applications @ LambdaDays
Reactive Web-Applications @ LambdaDays
 
Beyond MVC: from Model to Domain
Beyond MVC: from Model to DomainBeyond MVC: from Model to Domain
Beyond MVC: from Model to Domain
 
The curious Life of JavaScript - Talk at SI-SE 2015
The curious Life of JavaScript - Talk at SI-SE 2015The curious Life of JavaScript - Talk at SI-SE 2015
The curious Life of JavaScript - Talk at SI-SE 2015
 
WDB005.1 - JavaScript for Java Developers (Lecture 1)
WDB005.1 - JavaScript for Java Developers (Lecture 1)WDB005.1 - JavaScript for Java Developers (Lecture 1)
WDB005.1 - JavaScript for Java Developers (Lecture 1)
 
Laravel for Web Artisans
Laravel for Web ArtisansLaravel for Web Artisans
Laravel for Web Artisans
 
Donetconf2016: The Future of C#
Donetconf2016: The Future of C#Donetconf2016: The Future of C#
Donetconf2016: The Future of C#
 
Beyond MVC: from Model to Domain
Beyond MVC: from Model to DomainBeyond MVC: from Model to Domain
Beyond MVC: from Model to Domain
 
BOF2644 Developing Java EE 7 Scala apps
BOF2644 Developing Java EE 7 Scala appsBOF2644 Developing Java EE 7 Scala apps
BOF2644 Developing Java EE 7 Scala apps
 
Clean Code - Design Patterns and Best Practices for Bay.NET SF User Group (01...
Clean Code - Design Patterns and Best Practices for Bay.NET SF User Group (01...Clean Code - Design Patterns and Best Practices for Bay.NET SF User Group (01...
Clean Code - Design Patterns and Best Practices for Bay.NET SF User Group (01...
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
 
StackEngine Problem Space Demo
StackEngine Problem Space DemoStackEngine Problem Space Demo
StackEngine Problem Space Demo
 
Why Laravel?
Why Laravel?Why Laravel?
Why Laravel?
 
Clean Code for East Bay .NET User Group
Clean Code for East Bay .NET User GroupClean Code for East Bay .NET User Group
Clean Code for East Bay .NET User Group
 
OOP in PHP
OOP in PHPOOP in PHP
OOP in PHP
 
Laravel 101
Laravel 101Laravel 101
Laravel 101
 
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
Clean Code at Silicon Valley Code Camp 2011 (02/17/2012)
 
Play framework
Play frameworkPlay framework
Play framework
 

Último

If this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New NigeriaIf this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New Nigeria
Kayode Fayemi
 
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
amilabibi1
 
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
Sheetaleventcompany
 
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptxChiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
raffaeleoman
 
Uncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac FolorunsoUncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac Folorunso
Kayode Fayemi
 

Último (20)

If this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New NigeriaIf this Giant Must Walk: A Manifesto for a New Nigeria
If this Giant Must Walk: A Manifesto for a New Nigeria
 
lONG QUESTION ANSWER PAKISTAN STUDIES10.
lONG QUESTION ANSWER PAKISTAN STUDIES10.lONG QUESTION ANSWER PAKISTAN STUDIES10.
lONG QUESTION ANSWER PAKISTAN STUDIES10.
 
Introduction to Prompt Engineering (Focusing on ChatGPT)
Introduction to Prompt Engineering (Focusing on ChatGPT)Introduction to Prompt Engineering (Focusing on ChatGPT)
Introduction to Prompt Engineering (Focusing on ChatGPT)
 
Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...
Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...
Aesthetic Colaba Mumbai Cst Call girls 📞 7738631006 Grant road Call Girls ❤️-...
 
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
Bring back lost lover in USA, Canada ,Uk ,Australia ,London Lost Love Spell C...
 
Busty Desi⚡Call Girls in Sector 51 Noida Escorts >༒8448380779 Escort Service-...
Busty Desi⚡Call Girls in Sector 51 Noida Escorts >༒8448380779 Escort Service-...Busty Desi⚡Call Girls in Sector 51 Noida Escorts >༒8448380779 Escort Service-...
Busty Desi⚡Call Girls in Sector 51 Noida Escorts >༒8448380779 Escort Service-...
 
The workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdf
The workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdfThe workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdf
The workplace ecosystem of the future 24.4.2024 Fabritius_share ii.pdf
 
My Presentation "In Your Hands" by Halle Bailey
My Presentation "In Your Hands" by Halle BaileyMy Presentation "In Your Hands" by Halle Bailey
My Presentation "In Your Hands" by Halle Bailey
 
BDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 97 Noida Escorts >༒8448380779 Escort Service
 
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
No Advance 8868886958 Chandigarh Call Girls , Indian Call Girls For Full Nigh...
 
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptxChiulli_Aurora_Oman_Raffaele_Beowulf.pptx
Chiulli_Aurora_Oman_Raffaele_Beowulf.pptx
 
Dreaming Music Video Treatment _ Project & Portfolio III
Dreaming Music Video Treatment _ Project & Portfolio IIIDreaming Music Video Treatment _ Project & Portfolio III
Dreaming Music Video Treatment _ Project & Portfolio III
 
BDSM⚡Call Girls in Sector 93 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 93 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 93 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 93 Noida Escorts >༒8448380779 Escort Service
 
ICT role in 21st century education and it's challenges.pdf
ICT role in 21st century education and it's challenges.pdfICT role in 21st century education and it's challenges.pdf
ICT role in 21st century education and it's challenges.pdf
 
Dreaming Marissa Sánchez Music Video Treatment
Dreaming Marissa Sánchez Music Video TreatmentDreaming Marissa Sánchez Music Video Treatment
Dreaming Marissa Sánchez Music Video Treatment
 
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdfAWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
AWS Data Engineer Associate (DEA-C01) Exam Dumps 2024.pdf
 
Thirunelveli call girls Tamil escorts 7877702510
Thirunelveli call girls Tamil escorts 7877702510Thirunelveli call girls Tamil escorts 7877702510
Thirunelveli call girls Tamil escorts 7877702510
 
Air breathing and respiratory adaptations in diver animals
Air breathing and respiratory adaptations in diver animalsAir breathing and respiratory adaptations in diver animals
Air breathing and respiratory adaptations in diver animals
 
Causes of poverty in France presentation.pptx
Causes of poverty in France presentation.pptxCauses of poverty in France presentation.pptx
Causes of poverty in France presentation.pptx
 
Uncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac FolorunsoUncommon Grace The Autobiography of Isaac Folorunso
Uncommon Grace The Autobiography of Isaac Folorunso
 

Laravel.IO A Use-Case Architecture

  • 1. LARAVEL.IO A USE CASE ARCHITECTURE
  • 2. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC HI, I’M SHAWN
  • 3. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC LARAVEL.IO ORIGIN
  • 4. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Laravel.IO Now LARAVEL.IO FORUM from Nick Spelt and myself LIONA (LioBot) from Sam Evaskitas and Matthew Machuga LARAVEL WEEKLY NEWSLETTER by Dries Vints PODCAST http://bit.ly/laravelio-podcast Assets available for contribution at: https://github.com/LaravelIO
  • 5. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC AKA ENGINEERING MANAGING COMPLEXITY
  • 6. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC FUNCTIONAL REQUIREMENTS
  • 7. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC USE CASES
  • 8. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC ENTITIES Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity. - Eric Evans “
  • 9. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC PeoplePERSON
  • 10. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Jane Doe People Jane Doe PERSON
  • 11. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Jane Doe People Jane DoeJane Doe PERSON Jane Doe
  • 12. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Jane Doe PERSON Age: 27 Jane Doe Age: 27
  • 13. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Jane Doe PERSON Age: 27 From: NYC Jane Doe Age: 27 From: NYC
  • 14. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THE ACTIVERECORD PATTERN
  • 15. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC ID: 1 ID: 2 Jane Doe PERSON Age: 27 From: NYC Jane Doe Age: 27 From: NYC People Table ID 1 2 Age 27 27 From NYC NYC Name Jane Doe Jane Doe
  • 16. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC ENTITIES AND ACTIVERECORD
  • 17. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THIS IS NOT DDD
  • 18. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC LAYERED ARCHITECTURE
  • 19. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC A COMMON APPLICATION PRESENTATION LAYER Controllers Artisan Commands Queue Listeners
  • 20. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC PRESENTATION LAYER Controllers Artisan Commands Queue Listeners DOMAIN Entities Repository Interfaces A COMMON APPLICATION
  • 21. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC PRESENTATION LAYER Controllers Artisan Commands Queue Listeners SERVICE LAYER Sending Email Queueing up Jobs Repository Implementations DOMAIN Entities Repository Interfaces A COMMON APPLICATION
  • 22. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC PRESENTATION LAYER Controllers Artisan Commands Queue Listeners SERVICE LAYER Sending Email Queueing up Jobs Repository Implementations Commands / Command Bus DOMAIN Entities Repository Interfaces A COMMON APPLICATION
  • 23. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC A COMMAND ORIENTED INTERFACE
  • 24. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEAT OF THE APPLICATION WHAT IS A COMMAND
  • 25. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Controller Artisan Command Queue Worker Whatever MEAT OF THE APPLICATION WHAT IS A COMMAND
  • 26. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC WHAT IS A COMMAND MEAT OF THE APPLICATION REGISTER MEMBER COMMAND
  • 27. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC WHAT IS A COMMAND MEAT OF THE APPLICATION REGISTER MEMBER COMMAND
  • 28. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC WHAT IS A COMMAND REGISTER MEMBER COMMAND MEAT OF THE APPLICATION
  • 29. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Some Advantages - No business policy in your controllers - Your code shows intent - A single dedicated flow per use case - A single point of entry per use case - Easy to see which use cases are implemented
  • 30. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC COMMAND ANATOMY
  • 31. class RegisterMemberCommand { public $displayName; public $email; public $password; public function __construct($displayName, $email, $password) { $this->displayName = $displayName; $this->email = $email; $this->password = $password; } }
  • 32. class RegisterMemberCommand { public $displayName; public $email; public $password; public function __construct($displayName, $email, $password) { $this->displayName = $displayName; $this->email = $email; $this->password = $password; } }
  • 33. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC WHAT IS HAPPENING INSIDE? MEAT OF THE APPLICATION REGISTER MEMBER COMMAND
  • 34. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THE FINAL DESTINATION MEAT OF THE APPLICATION REGISTER MEMBER HANDLER REGISTER MEMBER COMMAND
  • 35. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THE FINAL DESTINATION MEAT OF THE APPLICATION ?REGISTER MEMBER COMMAND REGISTER MEMBER HANDLER
  • 36. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THE TRANSPORT MECHANISM MEAT OF THE APPLICATION COMMAND BUSREGISTER MEMBER COMMAND REGISTER MEMBER HANDLER
  • 37. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC COMMAND BUS IMPLEMENTATION
  • 38. class ExecutionCommandBus implements CommandBus { private $container; private $mapper; public function __construct(Container $container,Mapper $mapper) { $this->container = $container; $this->mapper = $mapper; } public function execute($command) { $this->getHandler($command)->handle($command); } private function getHandler($command) { $class = $this->mapper->getHandlerClassFor($command); return $this->container->make($class); } }
  • 39. class ExecutionCommandBus implements CommandBus { private $container; private $mapper; public function __construct(Container $container,Mapper $mapper) { $this->container = $container; $this->mapper = $mapper; } public function execute($command) { $this->getHandler($command)->handle($command); } private function getHandler($command) { $class = $this->mapper->getHandlerClassFor($command); return $this->container->make($class); } }
  • 40. class ExecutionCommandBus implements CommandBus { private $container; private $mapper; public function __construct(Container $container,Mapper $mapper) { $this->container = $container; $this->mapper = $mapper; } public function execute($command) { $this->getHandler($command)->handle($command); } private function getHandler($command) { $class = $this->mapper->getHandlerClassFor($command); return $this->container->make($class); } }
  • 41. class ExecutionCommandBus implements CommandBus { private $container; private $mapper; public function __construct(Container $container,Mapper $mapper) { $this->container = $container; $this->mapper = $mapper; } public function execute($command) { $this->getHandler($command)->handle($command); } private function getHandler($command) { $class = $this->mapper->getHandlerClassFor($command); return $this->container->make($class); } }
  • 42. class ExecutionCommandBus implements CommandBus { private $container; private $mapper; public function __construct(Container $container,Mapper $mapper) { $this->container = $container; $this->mapper = $mapper; } public function execute($command) { $this->getHandler($command)->handle($command); } private function getHandler($command) { $class = $this->mapper->getHandlerClassFor($command); return $this->container->make($class); } }
  • 43. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC HOW DOES THE MAPPER KNOW?
  • 44. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC ONE HANDLER PER COMMAND
  • 45. class RegisterMemberHandler implements Handler { private $memberRepository; public function __construct(MemberRepository $memberRepository) { $this->memberRepository = $memberRepository; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); } }
  • 46. class RegisterMemberHandler implements Handler { private $memberRepository; public function __construct(MemberRepository $memberRepository) { $this->memberRepository = $memberRepository; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); } }
  • 47. class RegisterMemberHandler implements Handler { private $memberRepository; public function __construct(MemberRepository $memberRepository) { $this->memberRepository = $memberRepository; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); } }
  • 48. class RegisterMemberHandler implements Handler { private $memberRepository; public function __construct(MemberRepository $memberRepository) { $this->memberRepository = $memberRepository; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); } }
  • 49. class Member extends Eloquent { public static function register($displayName, $email, $password) { $member = new static([ 'display_name' => $displayName, 'email' => $email, 'password' => $password, ]); return $member; } }
  • 50. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC DOMAIN IMPLICATION
  • 51. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC FLOW REVIEW PRESENTATION LAYER SERVICE LAYER DOMAIN
  • 52. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC FLOW REVIEW PRESENTATION LAYER SERVICE LAYER DOMAIN COMMAND
  • 53. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC FLOW REVIEW PRESENTATION LAYER SERVICE LAYER DOMAIN COMMAND COMMAND BUS
  • 54. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC FLOW REVIEW PRESENTATION LAYER SERVICE LAYER DOMAIN COMMAND COMMAND BUS COMMAND HANDLER
  • 55. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC FLOW REVIEW PRESENTATION LAYER SERVICE LAYER DOMAIN COMMAND COMMAND BUS COMMAND HANDLER ENTITIES REPOSITORIES
  • 56. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC HANDLING COMPLEX SEQUENCES
  • 57. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REGISTERS SEND WELCOME EMAIL SUBSCRIBE TO MAILCHIMP QUEUE UP 7 DAY EMAIL SIMPLE SEQUENCE
  • 58. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REPLIES TO THREAD NOTIFY THREAD SUBSCRIBERS w NOTIFY TAGGED USERS COMPLEX SEQUENCE
  • 59. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REPLIES TO THREAD NOTIFY THREAD SUBSCRIBERS w NOTIFY TAGGED USERS COMPLEX SEQUENCE SEND NOTIFICATION EMAIL ADD NOTIFICATION DIGEST QUEUE ENTRY SEND NO NOTIFICATION
  • 60. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC DOMAIN EVENTS
  • 61. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC TYPICAL PUB-SUB PATTERN DISPATCH EVENTRAISE EVENT TRIGGER LISTENERS
  • 62. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC PRESENTATION LAYER Controllers Artisan Commands Queue Listeners SERVICE LAYER Sending Email Queueing up Jobs Repository Implementations Commands / Command Bus DOMAIN Entities Repository Interfaces A COMMON APPLICATION
  • 63. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC PRESENTATION LAYER Controllers Artisan Commands Queue Listeners SERVICE LAYER Sending Email Queueing up Jobs Repository Implementations Commands / Command Bus Event Dispatcher DOMAIN Entities Repository Interfaces Domain Events A COMMON APPLICATION
  • 64. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REGISTERS SEND WELCOME EMAIL SUBSCRIBE TO MAILCHIMP QUEUE UP 7 DAY EMAIL DOMAIN EVENTS
  • 65. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REGISTERS SEND WELCOME EMAIL SUBSCRIBE TO MAILCHIMP QUEUE UP 7 DAY EMAIL EVENT / LISTENER BREAKDOWN
  • 66. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRegistered SEND WELCOME EMAIL SUBSCRIBE TO MAILCHIMP QUEUE UP 7 DAY EMAIL EVENT / LISTENER BREAKDOWN
  • 67. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRegistered SEND WELCOME EMAIL SUBSCRIBE TO MAILCHIMP QUEUE UP 7 DAY EMAIL EVENT / LISTENER BREAKDOWN
  • 68. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRegistered SendWelcomeMail SubscribeToMailchimp SendOneWeekEmail EVENT / LISTENER BREAKDOWN
  • 69. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRegistered SendWelcomeMail SendOneWeekEmail SubscribeToMailchimp EVENTS LISTENERS EVENT / LISTENER BREAKDOWN
  • 70. class MemberRegistered { public $member; public function __construct(Member $member) { $this->member = $member; } } class SendWelcomeEmail implements Listener { public function handle($event) { Mailer::queue(...); } }
  • 71. class MemberRegistered { public $member; public function __construct(Member $member) { $this->member = $member; } } class SendWelcomeEmail implements Listener { public function handle($event) { Mailer::queue(...); } }
  • 72. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THROWING DOMAIN EVENTS
  • 73. trait EventGenerator { protected $pendingEvents = []; protected function raise($event) { $this->pendingEvents[] = $event; } public function releaseEvents() { $events = $this->pendingEvents; $this->pendingEvents = []; return $events; } }
  • 74. trait EventGenerator { protected $pendingEvents = []; protected function raise($event) { $this->pendingEvents[] = $event; } public function releaseEvents() { $events = $this->pendingEvents; $this->pendingEvents = []; return $events; } }
  • 75. trait EventGenerator { protected $pendingEvents = []; protected function raise($event) { $this->pendingEvents[] = $event; } public function releaseEvents() { $events = $this->pendingEvents; $this->pendingEvents = []; return $events; } }
  • 76. trait EventGenerator { protected $pendingEvents = []; protected function raise($event) { $this->pendingEvents[] = $event; } public function releaseEvents() { $events = $this->pendingEvents; $this->pendingEvents = []; return $events; } }
  • 77. class Member extends Eloquent { use EventGenerator; public static function register($displayName, $email, $password) { $member = new static([ 'display_name' => $displayName, 'email' => $email, 'password' => $password, ]); $member->raise(new MemberJoined($member)); return $member; } }
  • 78. class Member extends Eloquent { use EventGenerator; public static function register($displayName, $email, $password) { $member = new static([ 'display_name' => $displayName, 'email' => $email, 'password' => $password, ]); $member->raise(new MemberRegistered($member)); return $member; } }
  • 79. class Member extends Eloquent { use EventGenerator; public static function register($displayName, $email, $password) { $member = new static([ 'display_name' => $displayName, 'email' => $email, 'password' => $password, ]); $member->raise(new MemberRegistered($member)); return $member; } }
  • 80. class Member extends Eloquent { use EventGenerator; public static function register($displayName, $email, $password) { $member = new static([ 'display_name' => $displayName, 'email' => $email, 'password' => $password, ]); $member->raise(new MemberRegistered($member)); return $member; } }
  • 81. class Member extends Eloquent { use EventGenerator; public static function register($displayName, $email, $password) { $member = new static([ 'display_name' => $displayName, 'email' => $email, 'password' => $password, ]); $member->raise(new MemberRegistered($member)); return $member; } }
  • 82. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC EVENT DISPATCHING
  • 83. interface Dispatcher { public function addListener($eventName, Listener $listener); public function dispatch($events); } // Register Listeners $dispatcher = new Dispatcher; $dispatcher->addListener('MemberRegistered', new SendWelcomeEmail); $dispatcher->addListener('MemberRegistered', new SubscribeToMailchimp); $dispatcher->addListener('MemberRegistered', new SendOneWeekEmail); // Dispatch Events $dispatcher->dispatch($events);
  • 84. interface Dispatcher { public function addListener($eventName, Listener $listener); public function dispatch($events); } // Register Listeners $dispatcher = new Dispatcher; $dispatcher->addListener('MemberRegistered', new SendWelcomeEmail); $dispatcher->addListener('MemberRegistered’, new SubscribeToMailchimp); $dispatcher->addListener('MemberRegistered', new SendOneWeekEmail); // Dispatch Events $dispatcher->dispatch($events);
  • 85. interface Dispatcher { public function addListener($eventName, Listener $listener); public function dispatch($events); } // Register Listeners $dispatcher = new Dispatcher; $dispatcher->addListener('MemberRegistered', new SendWelcomeEmail); $dispatcher->addListener('MemberRegistered’, new SubscribeToMailchimp); $dispatcher->addListener('MemberRegistered', new SendOneWeekEmail); // Dispatch Events $dispatcher->dispatch($events);
  • 86. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC THE FULL COMMAND HANDLER Heads Up...
  • 87. class RegisterMemberHandler implements Handler { private $memberRepository; private $dispatcher; public function __construct(MemberRepository $memberRepository, Dispatcher $dispatcher) { $this->memberRepository = $memberRepository; $this->dispatcher = $dispatcher; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); $this->dispatcher->dispatch($member->releaseEvents()); } }
  • 88. class RegisterMemberHandler implements Handler { private $memberRepository; private $dispatcher; public function __construct(MemberRepository $memberRepository, Dispatcher $dispatcher) { $this->memberRepository = $memberRepository; $this->dispatcher = $dispatcher; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); $this->dispatcher->dispatch($member->releaseEvents()); } }
  • 89. class RegisterMemberHandler implements Handler { private $memberRepository; private $dispatcher; public function __construct(MemberRepository $memberRepository, Dispatcher $dispatcher) { $this->memberRepository = $memberRepository; $this->dispatcher = $dispatcher; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); $this->dispatcher->dispatch($member->releaseEvents()); } }
  • 90. class RegisterMemberHandler implements Handler { private $memberRepository; private $dispatcher; public function __construct(MemberRepository $memberRepository, Dispatcher $dispatcher) { $this->memberRepository = $memberRepository; $this->dispatcher = $dispatcher; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); $this->dispatcher->dispatch($member->releaseEvents()); } }
  • 91. class RegisterMemberHandler implements Handler { private $memberRepository; private $dispatcher; public function __construct(MemberRepository $memberRepository, Dispatcher $dispatcher) { $this->memberRepository = $memberRepository; $this->dispatcher = $dispatcher; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); $this->dispatcher->dispatch($member->releaseEvents()); } }
  • 92. class RegisterMemberHandler implements Handler { private $memberRepository; private $dispatcher; public function __construct(MemberRepository $memberRepository, Dispatcher $dispatcher) { $this->memberRepository = $memberRepository; $this->dispatcher = $dispatcher; } public function handle($command) { $member = Member::register( $command->displayName, $command->email, $command->password); $this->memberRepository->save($member); $this->dispatcher->dispatch($member->releaseEvents()); } }
  • 93. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REPLIES TO THREAD NOTIFY THREAD SUBSCRIBERS w NOTIFY TAGGED USERS COMPLEX SEQUENCE SEND NOTIFICATION EMAIL ADD NOTIFICATION DIGEST QUEUE ENTRY SEND NO NOTIFICATION
  • 94. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REPLIES TO THREAD NOTIFY THREAD SUBSCRIBERS w NOTIFY TAGGED USERS COMPLEX SEQUENCE
  • 95. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER REPLIES TO THREAD NOTIFY THREAD SUBSCRIBERS w NOTIFY TAGGED USERS COMPLEX SEQUENCE
  • 96. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRepliedToThread NOTIFY THREAD SUBSCRIBERS w NOTIFY TAGGED USERS COMPLEX SEQUENCE
  • 97. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRepliedToThread NOTIFY THREAD SUBSCRIBERS NOTIFY TAGGED USERS COMPLEX SEQUENCE
  • 98. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberRepliedToThread NotifyThreadSubscribers NotifyTaggedUsers COMPLEX SEQUENCE
  • 99. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER IS NOTIFIED COMPLEX SEQUENCE SEND NOTIFICATION EMAIL
  • 100. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MEMBER IS NOTIFIED COMPLEX SEQUENCE SEND NOTIFICATION EMAIL
  • 101. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberNotificationSent COMPLEX SEQUENCE SEND NOTIFICATION EMAIL
  • 102. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberNotificationSent COMPLEX SEQUENCE SEND NOTIFICATION EMAIL
  • 103. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MemberNotificationSent COMPLEX SEQUENCE SendNotificationEmail
  • 104. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC DOMAIN EVENTS MemberRepliedToThread NotifyThreadSubscribers SendNotificationEmail NotifyTaggedMembers EVENTS LISTENERS MemberNotificationSent
  • 105. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Some Disadvantages - Can be harder to understand what’s happening - Requires more infrastructure - Events can be hard to debug
  • 106. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC DOMAIN-DRIVEN DESIGN
  • 107. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC MORE INFORMATION ABOUT DDD http://verraes.net http://rosstuck.com http://dddinphp.org Domain-Driven Design by Eric Evans Implementing Domain-Driven Design by Vaughn Vernon
  • 108. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Even More Information A very quick read + it’s free http://www.infoq.com/minibooks/domain-driven-design-quickly Martin Fowler http://martinfowler.com/bliki/CommandOrientedInterface.html http://martinfowler.com/eaaDev/DomainEvent.html
  • 109. Tickets are available at http://Laracon.EU
  • 110. Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC Thank you Laracon 2014! Hopefully, I talked so ridiculously fast that there’s time for questions. Twitter @ShawnMcCool Special Thanks to Nick Spelt and Mitchell van Wijngaarden