Laravel.IO A Use-Case Architecture

Post on 23-Aug-2014

2.987 views 4 download

Tags:

description

A simple architecture is perfect for a simple application. But, as the application grows in its complexity, the architecture must become more complex in order to prevent it from becoming unmaintainable. In this talk we discuss some ideas for simplifying complex code bases. We also discuss the important distinctions between presentation, service, and domain layers and strategies for separating high-level business policy from implementation. Some Domain-Driven Design topics are discussed, but this is not a talk about DDD. DDD is not about design patterns, but rather is about business analysis, communication, and much more.

Transcript of Laravel.IO A Use-Case Architecture

LARAVEL.IOA 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 ENGINEERINGMANAGING 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 APPLICATIONREGISTER MEMBER COMMAND

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

WHAT IS A COMMAND

MEAT OF THE APPLICATIONREGISTER 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

Service Layer DomainPresentation Layer

Flow Review

FLOW REVIEW

PRESENTATION LAYER

SERVICE LAYER DOMAIN

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Service Layer DomainPresentation Layer

Command

FLOW REVIEW

PRESENTATION LAYER

SERVICE LAYER DOMAIN

COMMAND

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Service Layer DomainPresentation Layer

Command Command Bus

FLOW REVIEW

PRESENTATION LAYER

SERVICE LAYER DOMAIN

COMMAND COMMAND BUS

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Service Layer DomainPresentation Layer

Command Command Bus

Command Handler

FLOW REVIEW

PRESENTATION LAYER

SERVICE LAYER DOMAIN

COMMAND COMMAND BUS

COMMANDHANDLER

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

FLOW REVIEW

PRESENTATION LAYER

SERVICE LAYER DOMAIN

COMMAND COMMAND BUS

COMMANDHANDLER

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 Joins

Send Welcome Email

Subscribe to MailChimp

Queue up 7 day Email

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 Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER REPLIES TO THREAD

NOTIFY THREAD SUBSCRIBERS

wNOTIFY TAGGED USERS

COMPLEX SEQUENCE

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER REPLIES TO THREAD

NOTIFY THREAD SUBSCRIBERS

wNOTIFY 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 Joins

Send Welcome Email

Subscribe to MailChimp

Queue up 7 day Email

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 Joins

Send Welcome Email

Subscribe to MailChimp

Queue up 7 day Email

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

MemberJoined

Send Welcome Email

Subscribe to MailChimp

Queue up 7 day Email

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

MemberJoined

Send Welcome Email

Subscribe to MailChimp

Queue up 7 day Email

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

MemberJoined

SendWelcomeEmail

SubscribeToMailChimp

SendOneWeekEmail

MemberRegistered

SendWelcomeMail

SubscribeToMailchimp

SendOneWeekEmail

EVENT / LISTENER BREAKDOWN

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

MemberJoined SendWelcomeEmail

SubscribeToMailChimp

SendOneWeekEmail

Events Listeners

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 HANDLERHeads 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 Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER REPLIES TO THREAD

NOTIFY THREAD SUBSCRIBERS

wNOTIFY 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 Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER REPLIES TO THREAD

NOTIFY THREAD SUBSCRIBERS

wNOTIFY TAGGED USERS

COMPLEX SEQUENCE

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER REPLIES TO THREAD

NOTIFY THREAD SUBSCRIBERS

wNOTIFY TAGGED USERS

COMPLEX SEQUENCE

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MemberRepliedToThread

NOTIFY THREAD SUBSCRIBERS

wNOTIFY TAGGED USERS

COMPLEX SEQUENCE

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MemberRepliedToThread

NOTIFY THREAD SUBSCRIBERS

NOTIFY TAGGED USERS

COMPLEX SEQUENCE

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MemberRepliedToThread

NotifyThreadSubscribers

NotifyTaggedUsers

COMPLEX SEQUENCE

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER IS NOTIFIED

COMPLEX SEQUENCE

SEND NOTIFICATION

EMAIL

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MEMBER IS NOTIFIED

COMPLEX SEQUENCE

SEND NOTIFICATION

EMAIL

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MemberNotificationSent

COMPLEX SEQUENCE

SEND NOTIFICATION

EMAIL

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MemberNotificationSent

COMPLEX SEQUENCE

SEND NOTIFICATION

EMAIL

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

Member Replies to Thread

Notify Subscribers

Parse for @username Tags

Send Notification Email

Add Notification Digest Queue Entry

Send No NotificationNotify Tagged Users

MemberNotificationSent

COMPLEX SEQUENCE

SendNotificationEmail

Laravel.IO, A Use Case Architecture By Shawn McCool Laracon 2014 in NYC

MemberJoined SendWelcomeEmail

SubscribeToMailChimp

SendOneWeekEmail

Events ListenersDOMAIN 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 Designby Eric Evans

Implementing Domain-Driven Designby 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