Skip to content

Commit

Permalink
Version22
Browse files Browse the repository at this point in the history
The main thing I did in this commit was to add an event dispatcher. I
throw a domain event in my model when entering a room and needed the
dispatcher in place to support that.

As I am using Symfony it made sense to me to use the Symfony event
dispatcher. However, it is a bit of a pain because it expects to have a
name and to be `Symfony\Component\EventDispatcher\Event`, as I was
trying to follow the clean architecture and have no outer dependencies I
didn't want to have my event extend
`Symfony\Component\EventDispatcher\Event`. Therefore, I needed to create
an adapter. Going back to the Raspberry Pi analogy made in a previous
version. I needed a serial to usb adapter, or something like that.

I also wanted to use my own Dispatcher interface, because what if I
wanted to stop using the Symfony dispatcher and replace it with
something else? I want to be able to continue using the same interface
but just add a new adapter and change my DI. You can see how I achieved
this from the code within this commit.

Finally, I added a `HandlerInterface` so that I can swap out handlers
using DI should I need to.
  • Loading branch information
jenkoian committed Jan 20, 2015
1 parent 73bb68c commit 2c2ec90
Show file tree
Hide file tree
Showing 16 changed files with 235 additions and 17 deletions.
2 changes: 1 addition & 1 deletion spec/Jenko/House/Factory/HomeAloneHouseFactorySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class HomeAloneHouseFactorySpec extends ObjectBehavior
function it_is_initializable()
{
$this->shouldHaveType('Jenko\House\Factory\HomeAloneHouseFactory');
$this->shouldHaveType('Jenko\House\Factory\HouseFactory');
$this->shouldHaveType('Jenko\House\Factory\HouseFactoryInterface');
}

function it_should_return_a_house()
Expand Down
34 changes: 34 additions & 0 deletions spec/Jenko/House/Handler/EnterRoomHandlerSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace spec\Jenko\House\Handler;

use Jenko\House\Command\EnterRoomCommand;
use Jenko\House\Event\EventDispatcherInterface;
use Jenko\House\Factory\HomeAloneHouseFactory;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class EnterRoomHandlerSpec extends ObjectBehavior
{
function let(EventDispatcherInterface $dispatcher)
{
$this->beConstructedWith($dispatcher);
}

function it_is_initializable()
{
$this->shouldHaveType('Jenko\House\Handler\EnterRoomHandler');
}

function it_dispatches_events(EventDispatcherInterface $dispatcher)
{
$house = HomeAloneHouseFactory::getHouse();
$house->enterRoom('hallway');

$command = new EnterRoomCommand();
$command->room = 'kitchen';

$dispatcher->dispatch(Argument::any())->shouldBeCalled();
$this->handle($command);
}
}
34 changes: 34 additions & 0 deletions spec/Jenko/House/Handler/ExitRoomHandlerSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace spec\Jenko\House\Handler;

use Jenko\House\Command\ExitRoomCommand;
use Jenko\House\Event\EventDispatcherInterface;
use Jenko\House\Factory\HomeAloneHouseFactory;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

class ExitRoomHandlerSpec extends ObjectBehavior
{
function let(EventDispatcherInterface $dispatcher)
{
$this->beConstructedWith($dispatcher);
}

function it_is_initializable()
{
$this->shouldHaveType('Jenko\House\Handler\ExitRoomHandler');
}

function it_dispatches_events(EventDispatcherInterface $dispatcher)
{
$house = HomeAloneHouseFactory::getHouse();
$house->enterRoom('hallway');

$command = new ExitRoomCommand();
$command->room = 'kitchen';

$dispatcher->dispatch(Argument::any())->shouldBeCalled();
$this->handle($command);
}
}
10 changes: 10 additions & 0 deletions src/Jenko/House/Adapter/SymfonyEventAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Jenko\House\Adapter;

use Symfony\Component\EventDispatcher\Event;

class SymfonyEventAdapter extends Event
{

}
30 changes: 30 additions & 0 deletions src/Jenko/House/Adapter/SymfonyEventDispatcherAdapter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Jenko\House\Adapter;

use Jenko\House\Event\EventDispatcherInterface as LocalEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class SymfonyEventDispatcherAdapter implements LocalEventDispatcherInterface
{
/**
* @var EventDispatcherInterface
*/
protected $dispatcher;
/**
* @param EventDispatcherInterface $dispatcher
*/
public function __construct(EventDispatcherInterface $dispatcher)
{
$this->dispatcher = $dispatcher;
}
/**
* {@inheritdoc}
*/
public function dispatch(array $events)
{
foreach ($events as $event) {
$this->dispatcher->dispatch($event::NAME, $event);
}
}
}
6 changes: 5 additions & 1 deletion src/Jenko/House/Event/EnteredRoomEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

namespace Jenko\House\Event;

class EnteredRoomEvent
use Jenko\House\Adapter\SymfonyEventAdapter;

class EnteredRoomEvent extends SymfonyEventAdapter
{
const NAME = 'house.room-entered';

public $roomName;
public $enteredOn;

Expand Down
12 changes: 12 additions & 0 deletions src/Jenko/House/Event/EventDispatcherInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Jenko\House\Event;

interface EventDispatcherInterface
{
/**
* @param array $events
* @return mixed
*/
public function dispatch(array $events);
}
32 changes: 32 additions & 0 deletions src/Jenko/House/Event/EventGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Jenko\House\Event;

trait EventGenerator
{
/**
* @var array
*/
protected $pendingEvents = [];

/**
* Raise a new event
*
* @param $event
*/
public function raiseEvent($event)
{
$this->pendingEvents[] = $event;
}

/**
* @return array
*/
public function releaseEvents()
{
$events = $this->pendingEvents;
$this->pendingEvents = [];

return $events;
}
}
2 changes: 1 addition & 1 deletion src/Jenko/House/Factory/HomeAloneHouseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* Note: Usually you would have some kind of persistence mechanism. However, in our case a static factory (essentially
* a singleton) is fine, as the house itself won't change.
*/
final class HomeAloneHouseFactory implements HouseFactory
final class HomeAloneHouseFactory implements HouseFactoryInterface
{
/**
* @var House $house
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Jenko\House\House;
use Jenko\House\Location;

interface HouseFactory
interface HouseFactoryInterface
{
/**
* @param Location|string|null $currentLocation
Expand Down
22 changes: 18 additions & 4 deletions src/Jenko/House/Handler/EnterRoomHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@

namespace Jenko\House\Handler;

use Jenko\House\Event\EventDispatcherInterface;
use Jenko\House\Factory\HomeAloneHouseFactory;
use Jenko\House\House;

final class EnterRoomHandler
final class EnterRoomHandler implements HandlerInterface
{
/**
* @var House $house
*/
private $house;

public function __construct()
/**
* @var EventDispatcherInterface
*/
private $dispatcher;

public function __construct(EventDispatcherInterface $dispatcher)
{
$this->house = HomeAloneHouseFactory::getHouse();
$this->dispatcher = $dispatcher;
}

/**
Expand All @@ -19,6 +30,9 @@ public function __construct()
*/
public function handle($command)
{
return $this->house->enterRoom($command->room);
$house = $this->house->enterRoom($command->room);
$this->dispatcher->dispatch($house->releaseEvents());

return $house;
}
}
}
22 changes: 18 additions & 4 deletions src/Jenko/House/Handler/ExitRoomHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,26 @@

namespace Jenko\House\Handler;

use Jenko\House\Event\EventDispatcherInterface;
use Jenko\House\Factory\HomeAloneHouseFactory;
use Jenko\House\House;

final class ExitRoomHandler
final class ExitRoomHandler implements HandlerInterface
{
/**
* @var House $house
*/
private $house;

public function __construct()
/**
* @var EventDispatcherInterface
*/
private $dispatcher;

public function __construct(EventDispatcherInterface $dispatcher)
{
$this->house = HomeAloneHouseFactory::getHouse();
$this->dispatcher = $dispatcher;
}

/**
Expand All @@ -19,6 +30,9 @@ public function __construct()
*/
public function handle($command)
{
return $this->house->exitToRoom($command->room);
$house = $this->house->exitToRoom($command->room);
$this->dispatcher->dispatch($house->releaseEvents());

return $house;
}
}
}
12 changes: 12 additions & 0 deletions src/Jenko/House/Handler/HandlerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Jenko\House\Handler;

interface HandlerInterface
{
/**
* @param $command
* @return mixed
*/
public function handle($command);
}
6 changes: 6 additions & 0 deletions src/Jenko/House/House.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

namespace Jenko\House;

use Jenko\House\Event\EnteredRoomEvent;
use Jenko\House\Event\EventGenerator;
use Jenko\House\Exception\LocationDoesNotExistException;

final class House
{
use EventGenerator;

/**
* @var array
*/
Expand Down Expand Up @@ -80,6 +84,8 @@ public function enterRoom($room)
$this->previousLocation = $this->currentLocation;
$this->currentLocation = $room;

$this->raiseEvent(new EnteredRoomEvent($this->currentLocation->getName()));

return $this;
}

Expand Down
13 changes: 9 additions & 4 deletions src/Jenko/HouseBundle/Controller/EnterRoomController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Jenko\HouseBundle\Controller;

use Jenko\House\Command\EnterRoomCommand;
use Jenko\House\Handler\EnterRoomHandler;
use Jenko\House\Handler\HandlerInterface;
use Jenko\House\House;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Request;
Expand All @@ -16,12 +16,18 @@ class EnterRoomController
*/
private $templating;

/**
* @var HandlerInterface $handler
*/
private $handler;

/**
* @param EngineInterface $templating
*/
public function __construct(EngineInterface $templating)
public function __construct(EngineInterface $templating, HandlerInterface $handler)
{
$this->templating = $templating;
$this->handler = $handler;
}

/**
Expand All @@ -34,9 +40,8 @@ public function enterAction(Request $request)
$command = new EnterRoomCommand();
$command->room = $request->get('location');

$handler = new EnterRoomHandler();
/** @var House $house */
$house = $handler->handle($command);
$house = $this->handler->handle($command);

return $this->templating->renderResponse(
'JenkoHouseBundle::room.html.twig',
Expand Down
13 changes: 12 additions & 1 deletion src/Jenko/HouseBundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,15 @@ services:
jenko.house.controllers.enter_room:
class: %jenko.house.controllers.enter_room.class%
arguments:
- @templating
- @templating
- @jenko.house.handlers.enter_room_handler

jenko.house.handlers.enter_room_handler:
class: Jenko\House\Handler\EnterRoomHandler
arguments:
- @jenko.house.adapters.symfony_event_dispatcher

jenko.house.adapters.symfony_event_dispatcher:
class: Jenko\House\Adapter\SymfonyEventDispatcherAdapter
arguments:
- @event_dispatcher

0 comments on commit 2c2ec90

Please sign in to comment.