SlideShare ist ein Scribd-Unternehmen logo
1 von 98
Downloaden Sie, um offline zu lesen
A Series of Fortunate Events 
Matthias Noback 
Track: PHP 
Feedback: /session/series-fortunate-events 
Twitter: @matthiasnoback
What are events, really? 
Things that happen
They trigger actions
Just now... 
Attendees arrived, 
triggered me to turn on microphone, 
which triggered you to stop talking, 
which triggered me to start talking
Events in software 
Events model what happened in a system
Other parts of the system 
can respond to what happened
Imperative programming 
Only commands 
doThis(); 
doThat(); 
updateSomething($something); 
return $something;
Extracting events 
doThis(); 
// this was done 
doThat(); 
// that was done 
updateSomething($something) 
// something was updated 
return $something;
Starting position 
class PostService 
{ 
... 
function addComment($postId, $comment) 
{ 
$post = $this­> 
fetchPost($postId); 
$post­> 
addComment($comment); 
$this­> 
save($post); 
$this­> 
logger­> 
info('New comment'); 
$this­> 
mailer­> 
send('New comment'); 
} 
}
Starting position 
class PostService 
{ 
function __construct( 
Mailer $mailer, 
Logger $logger 
) { 
$this­> 
mailer = $mailer; 
$this­> 
logger = $logger; 
} 
function addComment($postId, $comment) 
{ 
... 
} 
}
Making events explicit 
class PostService 
{ 
function addComment($postId, $comment) 
{ 
... 
$this­> 
newCommentAdded(); 
} 
function newCommentAdded() 
{ 
$this­> 
logger­> 
info('New comment'); 
$this­> 
mailer­> 
send('New comment'); 
} 
}
Dependency graph 
PoPsotstSSeerrvviicece 
Logger 
Mailer
Design issues (1) 
I don't think the PostService should 
know how to use a Mailer and a 
Logger
Design issues (2) 
I want to change the behavior of 
PostService without modifying the 
class itself
Fix the problems 
By introducing events! 
(later)
Observer pattern 
Notify other parts of the application 
when a change occurs 
class PostService 
{ 
function newCommentAdded() 
{ 
foreach ($this­> 
observers as $observer) { 
$observer­> 
notify(); 
} 
} 
}
Observer contract 
Subject knows nothing about its 
observers, except their very simple 
interface 
interface Observer 
{ 
function notify(); 
}
Concrete observers 
class LoggingObserver implements Observer 
{ 
function __construct(Logger $logger) 
{ 
$this­> 
logger = $logger; 
} 
function notify() 
{ 
$this­> 
logger­> 
info('New comment'); 
} 
}
Concrete observers 
class NotificationMailObserver implements Observer 
{ 
function __construct(Mailer $mailer) 
{ 
$this­> 
mailer = $mailer; 
} 
function notify() 
{ 
$this­> 
mailer­> 
send('New comment'); 
} 
}
Configuration 
class PostService 
{ 
function __construct(array $observers) 
{ 
$this­> 
observers = $observers; 
} 
} 
$postService = new PostService( 
array( 
new LoggingObserver($logger), 
new NotificationMailObserver($mailer) 
) 
);
Before 
PoPsotstSSeerrvviicece 
Logger 
Mailer
After 
NotificationMailObserver 
Observer 
Observer 
LoggingObserver 
Logger 
Mailer 
PostService
Design Principles Party
Single responsibility 
Each class has one small, 
well-defined responsibility
Single responsibility 
● PostService: 
“add comments to posts” 
● LoggingObserver: 
“write a line to the log” 
● NotificationMailObserver: 
“send a notification mail”
Single responsibility 
When a change is required, it can be 
isolated to just a small part of the 
application
Single responsibility 
● “Capitalize the comment!”: 
PostService 
● “Use a different logger!”: 
LoggerObserver 
● “Add a timestamp to the notification mail!”: 
NotificationMailObserver
Dependency inversion 
Depend on abstractions, not on 
concretions
Dependency inversion 
First PostService depended on 
something concrete: the Mailer, the 
Logger.
PostService Logger 
Mailer
Dependency inversion 
Now it depends on something abstract: 
an Observer
PostService 
Observer 
Observer
Dependency inversion 
Only the concrete observers depend on 
concrete things like Mailer and Logger
LoggingObserver 
NotificationMailObserver 
Logger 
Mailer
Open/closed 
A class should be open for extension and 
closed for modification
Open/closed 
You don't need to modify the class to 
change its behavior
PostService 
Observer 
Observer Observer
Open/closed 
We made it closed for modification, 
open for extension
Event data 
Mr. Boddy was murdered! 
● By Mrs. Peacock 
● In the dining room 
● With a candle stick
Currently missing! 
class LogNewCommentObserver implements Observer 
{ 
function notify() 
{ 
// we'd like to be more specific 
$this­> 
logger­> 
info('New comment'); 
} 
}
Event object 
class CommentAddedEvent 
{ 
public function __construct($postId, $comment) 
{ 
$this­> 
postId = $postId; 
$this­> 
comment = $comment; 
} 
function comment() 
{ 
return $this­> 
comment; 
} 
function postId() 
{ 
return $this­> 
postId; 
} 
}
Event object 
We use the event object 
to store the context of the event
From observer... 
interface Observer 
{ 
function notify(); 
}
… to event handler 
interface CommentAddedEventHandler 
{ 
function handle(CommentAddedEvent $event); 
}
Event handlers 
class LoggingEventHandler implements 
CommentAddedEventHandler 
{ 
function __construct(Logger $logger) 
{ 
$this­> 
logger = $logger; 
} 
public function handle(CommentAddedEvent $event) 
{ 
$this­> 
logger­> 
info( 
'New comment' . $event­> 
comment() 
); 
} 
}
Event handlers 
class NotificationMailEventHandler implements 
CommentAddedEventHandler 
{ 
function __construct(Mailer $mailer) 
{ 
$this­> 
mailer = $mailer; 
} 
public function handle(CommentAddedEvent $event) 
{ 
$this­> 
mailer­> 
send( 
'New comment: ' . $event­> 
comment(); 
); 
} 
}
Configuration 
class PostService 
{ 
function __construct(array $eventHandlers) 
{ 
$this­> 
eventHandlers = $eventHandlers; 
} 
} 
$postService = new PostService( 
array( 
new LoggingEventHandler($logger), 
new NotificationMailEventHandler($mailer) 
) 
);
Looping over event handlers 
class PostService 
{ 
public function addComment($postId, $comment) 
{ 
$this­> 
newCommentAdded($postId, $comment); 
} 
function newCommentAdded($postId, $comment) 
{ 
$event = new CommentAddedEvent( 
$postId, 
$comment 
); 
foreach ($this­> 
eventHandlers as $eventHandler) { 
$eventHandler­> 
handle($event); 
} 
} 
}
Introducing a Mediator 
Instead of talking to the event handlers 
Let's leave the talking to a mediator
Mediators for events 
● Doctrine, Zend: Event manager 
● The PHP League: Event emitter 
● Symfony: Event dispatcher
Before 
PostService 
LoggingEventHandler::handle() 
NotificationMailEventHandler::handle()
After 
PostService EventDispatcher 
LoggingEventHandler::handle() 
NotificationMailEventHandler::handle()
In code 
class PostService 
{ 
function __construct(EventDispatcherInterface $dispatcher) 
{ 
$this­> 
dispatcher = $dispatcher; 
} 
function newCommentAdded($postId, $comment) 
{ 
$event = new CommentAddedEvent($postId, $comment); 
$this­> 
dispatcher­> 
dispatch( 
'comment_added', 
$event 
); 
} 
}
Event class 
Custom event classes should extend 
Symfony Event class: 
use SymfonyComponentEventDispatcherEvent; 
class CommentAddedEvent extends Event 
{ 
... 
}
Configuration 
use SymfonyComponentEventDispatcherEvent; 
$dispatcher = new EventDispatcher(); 
$loggingEventHandler = new LoggingEventHandler($logger); 
$dispatcher­> 
addListener( 
'comment_added', 
array($loggingEventHandler, 'handle') 
); 
... 
$postService = new PostService($dispatcher);
Symfony2 - and Drupal8! 
● An event dispatcher is available as the 
event_dispatcher service 
● You can register event listeners using 
service tags
Inject the event dispatcher 
# your­module­name. 
service.yml 
services: 
post_service: 
class: PostService 
arguments: [@event_dispatcher]
Register your listeners 
# your­module­name. 
service.yml 
services: 
... 
logging_event_handler: 
class: LoggingEventHandler 
arguments: [@logger] 
tags: 
­{ 
name: kernel.event_listener 
event: comment_added 
method: handle 
}
Events and application flow 
Symfony2 uses events to generate 
response for any given HTTP request
The HttpKernel 
$request = Request::createFromGlobals(); 
// $kernel is in an instance of HttpKernelInterface 
$response = $kernel­> 
handle($request); 
$response­> 
send();
Kernel events
kernel.request 
● Route matching 
● Authentication
kernel.controller 
● Replace the controller 
● Do some access checks
kernel.view 
● Render a template
kernel.response 
● Modify the response 
● E.g. inject the Symfony toolbar
kernel.exception 
● Generate a response 
● Render a nice page with the stack trace
Special types of events 
● Kernel events are not merely 
notifications 
● They allow other parts of the 
application to step in and modify or 
override behavior
Chain of responsibility 
Some sort 
of request 
Handler 1 Handler 2 Handler 3 
Some sort 
of request 
Some sort 
of request 
Response
Symfony example 
I've got an exception! 
What should I tell the user? 
Listener 1 Listener 2 Listener 3 
Exception! Exception! 
Response
Propagation 
class HandleExceptionListener 
{ 
function onKernelException( 
GetResponseForExceptionEvent $event 
) { 
$event­> 
setResponse(new Response('Error!')); 
// this is the best response ever, don't let 
// other spoil it! 
$event­> 
stopPropagation(); 
} 
}
Priorities 
$dispatcher = new EventDispatcher(); 
$dispatcher­> 
addListener( 
'comment_added', 
array($object, $method), 
// priority 
100 
);
Concerns
Concern 1: Hard to understand 
“Click-through understanding” impossible 
$event = new CommentAddedEvent($postId, $comment); 
$this­> 
dispatcher­> 
dispatch( 
'comment_added', 
$event 
);
interface EventDispatcherInterface 
{ 
function dispatch($eventName, Event $event = null); 
... 
}
Solution 
Use Xdebug
Concern 2: Out-of-domain concepts 
● “Comment” 
● “PostId” 
● “Add comment to post” 
● “Dispatcher” (?!)
We did a good thing 
We fixed coupling issues
But this guy, Coupling, 
has a sister 
She's called Cohesion
Cohesion 
● Belonging together 
● Concepts like “dispatcher”, “event listener”, even 
“event”, don't belong in your code
Solutions (1) 
Descriptive, explicit naming: 
● NotificationMailEventListener becomes 
SendNotificationMailWhenCommentAdded 
● CommentAddedEvent becomes CommentAdded 
● onCommentAdded becomes 
whenCommentAdded
Solutions (1) 
This also hides implementation details!
Solutions (2) 
Use an event dispatcher for things 
that are not naturally cohesive anyway
Solutions (2) 
Use something else 
when an event dispatcher causes low cohesion
Example: resolving the controller 
$event = new GetResponseEvent($request); 
$dispatcher­> 
dispatch('kernel.request', $event); 
$controller = $request­> 
attributes­> 
get('_controller'); 
$controller = $controllerResolver­> 
resolve($request);
Concern 3: Loss of control 
● You rely on event listeners to do some really 
important work 
● How do you know if they are in place 
and do their job?
Solution 
● “Won't fix” 
● You have to learn to live with it
It's good
exercise 
control 
Inversion of control 
give up 
control!
Just like... 
● A router determines the right controller 
● The service container injects the right 
constructor arguments 
● And when you die, someone will bury your 
body for you
Sometimes I'm 
terrified, 
mortified, 
petrified, 
stupefied, 
by inversion of control too
But it will 
● lead to better design 
● require less change 
● make maintenance easier
PresentationFinished 
AskQuestionsWhenPresentationFinished 
SayThankYouWhenNoMoreQuestions
Symfony, service definitions, kernel events 
leanpub.com/a-year-with-symfony/c/drupalcon 
Get a 30% discount!
Class and package design principles 
leanpub.com/principles-of-php-package-design/c/drupalcon 
Get a $10 discount!
Design patterns 
● Observer 
● Mediator 
● Chain of responsibility 
● ... 
Design Patterns by “The Gang of Four”
SOLID principles 
● Single responsibility 
● Open/closed 
● Dependency inversion 
● ... 
Agile Software Development by Robert C. Martin
Images 
● www.ohiseered.com/2011_11_01_archive.html 
● Mrs. Peacock, Candlestick: 
www.cluecult.com 
● Leonardo DiCaprio: 
screenrant.com/leonardo-dicaprio-defends-wolf-wall-street-controversy/ 
● Book covers: 
Amazon 
● Party: 
todesignoffsite.com/events-2/to-do-closing-party-with-love-design/ 
● Russell Crowe: 
malinaelena.wordpress.com/2014/04/18/top-8-filme-cu-russell-crowe/
What did you think? 
https://amsterdam2014.drupal.org/session/series-fortunate-events 
Twitter: @matthiasnoback

Weitere ähnliche Inhalte

Was ist angesagt?

Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bitsChris Saylor
 
2 years after the first event - The Saga Pattern
2 years after the first event - The Saga Pattern2 years after the first event - The Saga Pattern
2 years after the first event - The Saga PatternRobert Pankowecki
 
[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert Pankowiecki[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert PankowieckiPROIDEA
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityRyan Weaver
 
Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)Samuel ROZE
 
The combine triad
The combine triadThe combine triad
The combine triadDonny Wals
 
exportDisabledUsersRemoveMailbox
exportDisabledUsersRemoveMailboxexportDisabledUsersRemoveMailbox
exportDisabledUsersRemoveMailboxDaniel Gilhousen
 
Kotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere StockholmKotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere StockholmFabio Collini
 
Graphical User Interface (GUI) - 2
Graphical User Interface (GUI) - 2Graphical User Interface (GUI) - 2
Graphical User Interface (GUI) - 2PRN USM
 
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...DevClub_lv
 
Advanced JavaScript Concepts
Advanced JavaScript ConceptsAdvanced JavaScript Concepts
Advanced JavaScript ConceptsNaresh Kumar
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeMacoscope
 
Javascript Experiment
Javascript ExperimentJavascript Experiment
Javascript Experimentwgamboa
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
Resultados
ResultadosResultados
Resultadosjbersosa
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testingVisual Engineering
 

Was ist angesagt? (20)

Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
 
2 years after the first event - The Saga Pattern
2 years after the first event - The Saga Pattern2 years after the first event - The Saga Pattern
2 years after the first event - The Saga Pattern
 
[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert Pankowiecki[4developers] The saga pattern v3- Robert Pankowiecki
[4developers] The saga pattern v3- Robert Pankowiecki
 
16 18
16 1816 18
16 18
 
Symfony2 your way
Symfony2   your waySymfony2   your way
Symfony2 your way
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
Ete programs
Ete programsEte programs
Ete programs
 
Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
The combine triad
The combine triadThe combine triad
The combine triad
 
exportDisabledUsersRemoveMailbox
exportDisabledUsersRemoveMailboxexportDisabledUsersRemoveMailbox
exportDisabledUsersRemoveMailbox
 
Kotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere StockholmKotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere Stockholm
 
Graphical User Interface (GUI) - 2
Graphical User Interface (GUI) - 2Graphical User Interface (GUI) - 2
Graphical User Interface (GUI) - 2
 
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
“SOLID principles in PHP – how to apply them in PHP and why should we care“ b...
 
Advanced JavaScript Concepts
Advanced JavaScript ConceptsAdvanced JavaScript Concepts
Advanced JavaScript Concepts
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
Javascript Experiment
Javascript ExperimentJavascript Experiment
Javascript Experiment
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Resultados
ResultadosResultados
Resultados
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 

Andere mochten auch

Sherlock deck upload to slideshare
Sherlock deck upload to slideshareSherlock deck upload to slideshare
Sherlock deck upload to slideshareBelong
 
Engineering your culture how to keep your engineers happy
Engineering your culture   how to keep your engineers happyEngineering your culture   how to keep your engineers happy
Engineering your culture how to keep your engineers happyAgilePractitionersIL
 
Basic Mandarin Chinese | Lesson 4 | Etiquette conversation
Basic Mandarin Chinese | Lesson 4 | Etiquette conversationBasic Mandarin Chinese | Lesson 4 | Etiquette conversation
Basic Mandarin Chinese | Lesson 4 | Etiquette conversationCultureAlley
 
Basic Mandarin Chinese | Lesson 5 | Greetings and pleasantries
Basic Mandarin Chinese | Lesson 5 | Greetings and pleasantriesBasic Mandarin Chinese | Lesson 5 | Greetings and pleasantries
Basic Mandarin Chinese | Lesson 5 | Greetings and pleasantriesCultureAlley
 
Basic Mandarin Chinese | Lesson 2 | Saying hello!
Basic Mandarin Chinese | Lesson 2 | Saying hello!Basic Mandarin Chinese | Lesson 2 | Saying hello!
Basic Mandarin Chinese | Lesson 2 | Saying hello!CultureAlley
 
Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!
Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!
Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!CultureAlley
 
Sherlock holmes. short stories
Sherlock holmes. short storiesSherlock holmes. short stories
Sherlock holmes. short storiesdiscoveringweather
 
Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!
Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!
Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!CultureAlley
 
Evidences for the Existence of God
Evidences for the Existence of GodEvidences for the Existence of God
Evidences for the Existence of Godbcbennet
 
Female reproductive system
Female reproductive systemFemale reproductive system
Female reproductive systemSandesh Kamdi
 
Present and Past Modals of Deduction with Sherlock Holmes
Present and Past Modals of Deduction with Sherlock HolmesPresent and Past Modals of Deduction with Sherlock Holmes
Present and Past Modals of Deduction with Sherlock HolmesDavid Mainwood
 
Oil & Gas Production and Surface Facilities
Oil & Gas Production and Surface FacilitiesOil & Gas Production and Surface Facilities
Oil & Gas Production and Surface FacilitiesMohamed Elnagar
 

Andere mochten auch (15)

Sherlock deck upload to slideshare
Sherlock deck upload to slideshareSherlock deck upload to slideshare
Sherlock deck upload to slideshare
 
Engineering your culture how to keep your engineers happy
Engineering your culture   how to keep your engineers happyEngineering your culture   how to keep your engineers happy
Engineering your culture how to keep your engineers happy
 
Basic Mandarin Chinese | Lesson 4 | Etiquette conversation
Basic Mandarin Chinese | Lesson 4 | Etiquette conversationBasic Mandarin Chinese | Lesson 4 | Etiquette conversation
Basic Mandarin Chinese | Lesson 4 | Etiquette conversation
 
Basic Mandarin Chinese | Lesson 5 | Greetings and pleasantries
Basic Mandarin Chinese | Lesson 5 | Greetings and pleasantriesBasic Mandarin Chinese | Lesson 5 | Greetings and pleasantries
Basic Mandarin Chinese | Lesson 5 | Greetings and pleasantries
 
Basic Mandarin Chinese | Lesson 2 | Saying hello!
Basic Mandarin Chinese | Lesson 2 | Saying hello!Basic Mandarin Chinese | Lesson 2 | Saying hello!
Basic Mandarin Chinese | Lesson 2 | Saying hello!
 
Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!
Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!
Basic Mandarin Chinese | Lesson 3 | Learn other useful greetings!
 
Sherlock holmes. short stories
Sherlock holmes. short storiesSherlock holmes. short stories
Sherlock holmes. short stories
 
Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!
Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!
Basic Mandarin Chinese | Lesson 1 | Grasp the tones in Mandarin!
 
Evidences for the Existence of God
Evidences for the Existence of GodEvidences for the Existence of God
Evidences for the Existence of God
 
Sherlock Holmes
Sherlock HolmesSherlock Holmes
Sherlock Holmes
 
Female reproductive system
Female reproductive systemFemale reproductive system
Female reproductive system
 
Present and Past Modals of Deduction with Sherlock Holmes
Present and Past Modals of Deduction with Sherlock HolmesPresent and Past Modals of Deduction with Sherlock Holmes
Present and Past Modals of Deduction with Sherlock Holmes
 
Oil & Gas Production and Surface Facilities
Oil & Gas Production and Surface FacilitiesOil & Gas Production and Surface Facilities
Oil & Gas Production and Surface Facilities
 
Introduction to Offshore Oil and Gas Surface Facilities
Introduction to Offshore Oil and Gas Surface FacilitiesIntroduction to Offshore Oil and Gas Surface Facilities
Introduction to Offshore Oil and Gas Surface Facilities
 
Paris ML meetup
Paris ML meetupParis ML meetup
Paris ML meetup
 

Ähnlich wie A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014

A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015Matthias Noback
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravelwajrcs
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016Kacper Gunia
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonfNataliya Patsovska
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMMario Fusco
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of ControlChad Hietala
 
EventBus for Android
EventBus for AndroidEventBus for Android
EventBus for Androidgreenrobot
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access RunbookTaha Shakeel
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
Dependency Injection in Drupal 8
Dependency Injection in Drupal 8Dependency Injection in Drupal 8
Dependency Injection in Drupal 8katbailey
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 

Ähnlich wie A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014 (20)

A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015A Series of Fortunate Events - PHP Benelux Conference 2015
A Series of Fortunate Events - PHP Benelux Conference 2015
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Declarative presentations UIKonf
Declarative presentations UIKonfDeclarative presentations UIKonf
Declarative presentations UIKonf
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Event Driven Applications in F#
Event Driven Applications in F#Event Driven Applications in F#
Event Driven Applications in F#
 
Akka
AkkaAkka
Akka
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
EventBus for Android
EventBus for AndroidEventBus for Android
EventBus for Android
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Dependency Injection in Drupal 8
Dependency Injection in Drupal 8Dependency Injection in Drupal 8
Dependency Injection in Drupal 8
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 

Mehr von Matthias Noback

Rector fireside chat - PHPMiNDS meetup
Rector fireside chat - PHPMiNDS meetupRector fireside chat - PHPMiNDS meetup
Rector fireside chat - PHPMiNDS meetupMatthias Noback
 
Service abstractions - Part 1: Queries
Service abstractions - Part 1: QueriesService abstractions - Part 1: Queries
Service abstractions - Part 1: QueriesMatthias Noback
 
Hexagonal Symfony - SymfonyCon Amsterdam 2019
Hexagonal Symfony - SymfonyCon Amsterdam 2019Hexagonal Symfony - SymfonyCon Amsterdam 2019
Hexagonal Symfony - SymfonyCon Amsterdam 2019Matthias Noback
 
Advanced web application architecture - PHP Barcelona
Advanced web application architecture  - PHP BarcelonaAdvanced web application architecture  - PHP Barcelona
Advanced web application architecture - PHP BarcelonaMatthias Noback
 
A testing strategy for hexagonal applications
A testing strategy for hexagonal applicationsA testing strategy for hexagonal applications
A testing strategy for hexagonal applicationsMatthias Noback
 
Advanced web application architecture - Talk
Advanced web application architecture - TalkAdvanced web application architecture - Talk
Advanced web application architecture - TalkMatthias Noback
 
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...Matthias Noback
 
Layers, ports and adapters
Layers, ports and adaptersLayers, ports and adapters
Layers, ports and adaptersMatthias Noback
 
Beyond design principles and patterns (muCon 2019 edition)
Beyond design principles and patterns (muCon 2019 edition)Beyond design principles and patterns (muCon 2019 edition)
Beyond design principles and patterns (muCon 2019 edition)Matthias Noback
 
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Matthias Noback
 
Advanced web application architecture Way2Web
Advanced web application architecture Way2WebAdvanced web application architecture Way2Web
Advanced web application architecture Way2WebMatthias Noback
 
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Matthias Noback
 
Beyond Design Principles and Patterns
Beyond Design Principles and PatternsBeyond Design Principles and Patterns
Beyond Design Principles and PatternsMatthias Noback
 
Building Autonomous Services
Building Autonomous ServicesBuilding Autonomous Services
Building Autonomous ServicesMatthias Noback
 
Advanced Application Architecture Symfony Live Berlin 2018
Advanced Application Architecture Symfony Live Berlin 2018Advanced Application Architecture Symfony Live Berlin 2018
Advanced Application Architecture Symfony Live Berlin 2018Matthias Noback
 
Building autonomous services
Building autonomous servicesBuilding autonomous services
Building autonomous servicesMatthias Noback
 

Mehr von Matthias Noback (20)

Rector fireside chat - PHPMiNDS meetup
Rector fireside chat - PHPMiNDS meetupRector fireside chat - PHPMiNDS meetup
Rector fireside chat - PHPMiNDS meetup
 
Service abstractions - Part 1: Queries
Service abstractions - Part 1: QueriesService abstractions - Part 1: Queries
Service abstractions - Part 1: Queries
 
Hexagonal Symfony - SymfonyCon Amsterdam 2019
Hexagonal Symfony - SymfonyCon Amsterdam 2019Hexagonal Symfony - SymfonyCon Amsterdam 2019
Hexagonal Symfony - SymfonyCon Amsterdam 2019
 
Advanced web application architecture - PHP Barcelona
Advanced web application architecture  - PHP BarcelonaAdvanced web application architecture  - PHP Barcelona
Advanced web application architecture - PHP Barcelona
 
A testing strategy for hexagonal applications
A testing strategy for hexagonal applicationsA testing strategy for hexagonal applications
A testing strategy for hexagonal applications
 
Advanced web application architecture - Talk
Advanced web application architecture - TalkAdvanced web application architecture - Talk
Advanced web application architecture - Talk
 
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...
DPC 2019, Amsterdam: Beyond design patterns and principles - writing good OO ...
 
Layers, ports and adapters
Layers, ports and adaptersLayers, ports and adapters
Layers, ports and adapters
 
Beyond design principles and patterns (muCon 2019 edition)
Beyond design principles and patterns (muCon 2019 edition)Beyond design principles and patterns (muCon 2019 edition)
Beyond design principles and patterns (muCon 2019 edition)
 
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
 
Advanced web application architecture Way2Web
Advanced web application architecture Way2WebAdvanced web application architecture Way2Web
Advanced web application architecture Way2Web
 
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...Brutal refactoring, lying code, the Churn, and other emotional stories from L...
Brutal refactoring, lying code, the Churn, and other emotional stories from L...
 
Beyond Design Principles and Patterns
Beyond Design Principles and PatternsBeyond Design Principles and Patterns
Beyond Design Principles and Patterns
 
Building Autonomous Services
Building Autonomous ServicesBuilding Autonomous Services
Building Autonomous Services
 
Advanced Application Architecture Symfony Live Berlin 2018
Advanced Application Architecture Symfony Live Berlin 2018Advanced Application Architecture Symfony Live Berlin 2018
Advanced Application Architecture Symfony Live Berlin 2018
 
Designing for Autonomy
Designing for AutonomyDesigning for Autonomy
Designing for Autonomy
 
Docker workshop
Docker workshopDocker workshop
Docker workshop
 
Docker swarm workshop
Docker swarm workshopDocker swarm workshop
Docker swarm workshop
 
Docker compose workshop
Docker compose workshopDocker compose workshop
Docker compose workshop
 
Building autonomous services
Building autonomous servicesBuilding autonomous services
Building autonomous services
 

Kürzlich hochgeladen

Online banking management system project.pdf
Online banking management system project.pdfOnline banking management system project.pdf
Online banking management system project.pdfKamal Acharya
 
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptxBSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptxfenichawla
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINESIVASHANKAR N
 
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...ranjana rawat
 
Introduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxIntroduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxupamatechverse
 
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...Christo Ananth
 
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...Call Girls in Nagpur High Profile
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...roncy bisnoi
 
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...ranjana rawat
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Dr.Costas Sachpazis
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordAsst.prof M.Gokilavani
 
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...ranjana rawat
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
Introduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptxIntroduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptxupamatechverse
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur EscortsRussian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 

Kürzlich hochgeladen (20)

Online banking management system project.pdf
Online banking management system project.pdfOnline banking management system project.pdf
Online banking management system project.pdf
 
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
 
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptxBSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
BSides Seattle 2024 - Stopping Ethan Hunt From Taking Your Data.pptx
 
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANVI) Koregaon Park Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
(SHREYA) Chakan Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Esc...
 
Introduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptxIntroduction and different types of Ethernet.pptx
Introduction and different types of Ethernet.pptx
 
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
Call for Papers - African Journal of Biological Sciences, E-ISSN: 2663-2187, ...
 
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(PRIYA) Rajgurunagar Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
 
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
Structural Analysis and Design of Foundations: A Comprehensive Handbook for S...
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
 
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
(ANJALI) Dange Chowk Call Girls Just Call 7001035870 [ Cash on Delivery ] Pun...
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
 
Introduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptxIntroduction to IEEE STANDARDS and its different types.pptx
Introduction to IEEE STANDARDS and its different types.pptx
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
 
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur EscortsRussian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
Russian Call Girls in Nagpur Grishma Call 7001035870 Meet With Nagpur Escorts
 

A Series of Fortunate Events - Drupalcon Europe, Amsterdam 2014

  • 1. A Series of Fortunate Events Matthias Noback Track: PHP Feedback: /session/series-fortunate-events Twitter: @matthiasnoback
  • 2. What are events, really? Things that happen
  • 4. Just now... Attendees arrived, triggered me to turn on microphone, which triggered you to stop talking, which triggered me to start talking
  • 5. Events in software Events model what happened in a system
  • 6. Other parts of the system can respond to what happened
  • 7. Imperative programming Only commands doThis(); doThat(); updateSomething($something); return $something;
  • 8. Extracting events doThis(); // this was done doThat(); // that was done updateSomething($something) // something was updated return $something;
  • 9. Starting position class PostService { ... function addComment($postId, $comment) { $post = $this­> fetchPost($postId); $post­> addComment($comment); $this­> save($post); $this­> logger­> info('New comment'); $this­> mailer­> send('New comment'); } }
  • 10. Starting position class PostService { function __construct( Mailer $mailer, Logger $logger ) { $this­> mailer = $mailer; $this­> logger = $logger; } function addComment($postId, $comment) { ... } }
  • 11. Making events explicit class PostService { function addComment($postId, $comment) { ... $this­> newCommentAdded(); } function newCommentAdded() { $this­> logger­> info('New comment'); $this­> mailer­> send('New comment'); } }
  • 13. Design issues (1) I don't think the PostService should know how to use a Mailer and a Logger
  • 14. Design issues (2) I want to change the behavior of PostService without modifying the class itself
  • 15. Fix the problems By introducing events! (later)
  • 16. Observer pattern Notify other parts of the application when a change occurs class PostService { function newCommentAdded() { foreach ($this­> observers as $observer) { $observer­> notify(); } } }
  • 17. Observer contract Subject knows nothing about its observers, except their very simple interface interface Observer { function notify(); }
  • 18. Concrete observers class LoggingObserver implements Observer { function __construct(Logger $logger) { $this­> logger = $logger; } function notify() { $this­> logger­> info('New comment'); } }
  • 19. Concrete observers class NotificationMailObserver implements Observer { function __construct(Mailer $mailer) { $this­> mailer = $mailer; } function notify() { $this­> mailer­> send('New comment'); } }
  • 20. Configuration class PostService { function __construct(array $observers) { $this­> observers = $observers; } } $postService = new PostService( array( new LoggingObserver($logger), new NotificationMailObserver($mailer) ) );
  • 22. After NotificationMailObserver Observer Observer LoggingObserver Logger Mailer PostService
  • 24. Single responsibility Each class has one small, well-defined responsibility
  • 25. Single responsibility ● PostService: “add comments to posts” ● LoggingObserver: “write a line to the log” ● NotificationMailObserver: “send a notification mail”
  • 26. Single responsibility When a change is required, it can be isolated to just a small part of the application
  • 27. Single responsibility ● “Capitalize the comment!”: PostService ● “Use a different logger!”: LoggerObserver ● “Add a timestamp to the notification mail!”: NotificationMailObserver
  • 28. Dependency inversion Depend on abstractions, not on concretions
  • 29. Dependency inversion First PostService depended on something concrete: the Mailer, the Logger.
  • 31. Dependency inversion Now it depends on something abstract: an Observer
  • 33. Dependency inversion Only the concrete observers depend on concrete things like Mailer and Logger
  • 35. Open/closed A class should be open for extension and closed for modification
  • 36. Open/closed You don't need to modify the class to change its behavior
  • 38. Open/closed We made it closed for modification, open for extension
  • 39. Event data Mr. Boddy was murdered! ● By Mrs. Peacock ● In the dining room ● With a candle stick
  • 40. Currently missing! class LogNewCommentObserver implements Observer { function notify() { // we'd like to be more specific $this­> logger­> info('New comment'); } }
  • 41. Event object class CommentAddedEvent { public function __construct($postId, $comment) { $this­> postId = $postId; $this­> comment = $comment; } function comment() { return $this­> comment; } function postId() { return $this­> postId; } }
  • 42. Event object We use the event object to store the context of the event
  • 43. From observer... interface Observer { function notify(); }
  • 44. … to event handler interface CommentAddedEventHandler { function handle(CommentAddedEvent $event); }
  • 45. Event handlers class LoggingEventHandler implements CommentAddedEventHandler { function __construct(Logger $logger) { $this­> logger = $logger; } public function handle(CommentAddedEvent $event) { $this­> logger­> info( 'New comment' . $event­> comment() ); } }
  • 46. Event handlers class NotificationMailEventHandler implements CommentAddedEventHandler { function __construct(Mailer $mailer) { $this­> mailer = $mailer; } public function handle(CommentAddedEvent $event) { $this­> mailer­> send( 'New comment: ' . $event­> comment(); ); } }
  • 47. Configuration class PostService { function __construct(array $eventHandlers) { $this­> eventHandlers = $eventHandlers; } } $postService = new PostService( array( new LoggingEventHandler($logger), new NotificationMailEventHandler($mailer) ) );
  • 48. Looping over event handlers class PostService { public function addComment($postId, $comment) { $this­> newCommentAdded($postId, $comment); } function newCommentAdded($postId, $comment) { $event = new CommentAddedEvent( $postId, $comment ); foreach ($this­> eventHandlers as $eventHandler) { $eventHandler­> handle($event); } } }
  • 49. Introducing a Mediator Instead of talking to the event handlers Let's leave the talking to a mediator
  • 50. Mediators for events ● Doctrine, Zend: Event manager ● The PHP League: Event emitter ● Symfony: Event dispatcher
  • 51. Before PostService LoggingEventHandler::handle() NotificationMailEventHandler::handle()
  • 52. After PostService EventDispatcher LoggingEventHandler::handle() NotificationMailEventHandler::handle()
  • 53. In code class PostService { function __construct(EventDispatcherInterface $dispatcher) { $this­> dispatcher = $dispatcher; } function newCommentAdded($postId, $comment) { $event = new CommentAddedEvent($postId, $comment); $this­> dispatcher­> dispatch( 'comment_added', $event ); } }
  • 54. Event class Custom event classes should extend Symfony Event class: use SymfonyComponentEventDispatcherEvent; class CommentAddedEvent extends Event { ... }
  • 55. Configuration use SymfonyComponentEventDispatcherEvent; $dispatcher = new EventDispatcher(); $loggingEventHandler = new LoggingEventHandler($logger); $dispatcher­> addListener( 'comment_added', array($loggingEventHandler, 'handle') ); ... $postService = new PostService($dispatcher);
  • 56. Symfony2 - and Drupal8! ● An event dispatcher is available as the event_dispatcher service ● You can register event listeners using service tags
  • 57. Inject the event dispatcher # your­module­name. service.yml services: post_service: class: PostService arguments: [@event_dispatcher]
  • 58. Register your listeners # your­module­name. service.yml services: ... logging_event_handler: class: LoggingEventHandler arguments: [@logger] tags: ­{ name: kernel.event_listener event: comment_added method: handle }
  • 59. Events and application flow Symfony2 uses events to generate response for any given HTTP request
  • 60. The HttpKernel $request = Request::createFromGlobals(); // $kernel is in an instance of HttpKernelInterface $response = $kernel­> handle($request); $response­> send();
  • 62. kernel.request ● Route matching ● Authentication
  • 63. kernel.controller ● Replace the controller ● Do some access checks
  • 65. kernel.response ● Modify the response ● E.g. inject the Symfony toolbar
  • 66. kernel.exception ● Generate a response ● Render a nice page with the stack trace
  • 67. Special types of events ● Kernel events are not merely notifications ● They allow other parts of the application to step in and modify or override behavior
  • 68. Chain of responsibility Some sort of request Handler 1 Handler 2 Handler 3 Some sort of request Some sort of request Response
  • 69. Symfony example I've got an exception! What should I tell the user? Listener 1 Listener 2 Listener 3 Exception! Exception! Response
  • 70. Propagation class HandleExceptionListener { function onKernelException( GetResponseForExceptionEvent $event ) { $event­> setResponse(new Response('Error!')); // this is the best response ever, don't let // other spoil it! $event­> stopPropagation(); } }
  • 71. Priorities $dispatcher = new EventDispatcher(); $dispatcher­> addListener( 'comment_added', array($object, $method), // priority 100 );
  • 73. Concern 1: Hard to understand “Click-through understanding” impossible $event = new CommentAddedEvent($postId, $comment); $this­> dispatcher­> dispatch( 'comment_added', $event );
  • 74. interface EventDispatcherInterface { function dispatch($eventName, Event $event = null); ... }
  • 76. Concern 2: Out-of-domain concepts ● “Comment” ● “PostId” ● “Add comment to post” ● “Dispatcher” (?!)
  • 77. We did a good thing We fixed coupling issues
  • 78. But this guy, Coupling, has a sister She's called Cohesion
  • 79. Cohesion ● Belonging together ● Concepts like “dispatcher”, “event listener”, even “event”, don't belong in your code
  • 80. Solutions (1) Descriptive, explicit naming: ● NotificationMailEventListener becomes SendNotificationMailWhenCommentAdded ● CommentAddedEvent becomes CommentAdded ● onCommentAdded becomes whenCommentAdded
  • 81. Solutions (1) This also hides implementation details!
  • 82. Solutions (2) Use an event dispatcher for things that are not naturally cohesive anyway
  • 83. Solutions (2) Use something else when an event dispatcher causes low cohesion
  • 84. Example: resolving the controller $event = new GetResponseEvent($request); $dispatcher­> dispatch('kernel.request', $event); $controller = $request­> attributes­> get('_controller'); $controller = $controllerResolver­> resolve($request);
  • 85. Concern 3: Loss of control ● You rely on event listeners to do some really important work ● How do you know if they are in place and do their job?
  • 86. Solution ● “Won't fix” ● You have to learn to live with it
  • 88. exercise control Inversion of control give up control!
  • 89. Just like... ● A router determines the right controller ● The service container injects the right constructor arguments ● And when you die, someone will bury your body for you
  • 90. Sometimes I'm terrified, mortified, petrified, stupefied, by inversion of control too
  • 91. But it will ● lead to better design ● require less change ● make maintenance easier
  • 93. Symfony, service definitions, kernel events leanpub.com/a-year-with-symfony/c/drupalcon Get a 30% discount!
  • 94. Class and package design principles leanpub.com/principles-of-php-package-design/c/drupalcon Get a $10 discount!
  • 95. Design patterns ● Observer ● Mediator ● Chain of responsibility ● ... Design Patterns by “The Gang of Four”
  • 96. SOLID principles ● Single responsibility ● Open/closed ● Dependency inversion ● ... Agile Software Development by Robert C. Martin
  • 97. Images ● www.ohiseered.com/2011_11_01_archive.html ● Mrs. Peacock, Candlestick: www.cluecult.com ● Leonardo DiCaprio: screenrant.com/leonardo-dicaprio-defends-wolf-wall-street-controversy/ ● Book covers: Amazon ● Party: todesignoffsite.com/events-2/to-do-closing-party-with-love-design/ ● Russell Crowe: malinaelena.wordpress.com/2014/04/18/top-8-filme-cu-russell-crowe/
  • 98. What did you think? https://amsterdam2014.drupal.org/session/series-fortunate-events Twitter: @matthiasnoback