DDD in PHPon example of Symfony
cystbearSymfony expert
MongoDB adept
Erlang fun
OSS doer
KNPer
https://twitter.com/1cdecoderhttps://github.com/cystbearhttp://knplabs.com/
Learning Pyramid
PHP? ORLY?
What this talk about?
About useful tool/lib?
About success story?
No! It’s about idea
Motivation!
MVC
Where to store business logic?
ModelViewController
Where to store business logic?
ModelViewController
Where to store business logic?
ModelViewController
Where to store business logic?
ModelViewController -- YEAH!
Welcome to
Fat Stupid Ugly ControllersFSUC/FUC
http://blog.astrumfutura.com/2008/12/the-m-in-mvc-why-models-are-misunderstood-and-unappreciated/http://zendframework.ru/anonses/model-with-mvc
http://habrahabr.ru/post/175465/
Anemic (Domain) Model
http://www.martinfowler.com/bliki/AnemicDomainModel.htmlhttp://habrahabr.ru/post/224879/
“In essence the problem with anemic domain models is that they incur all of the costs of a domain model, without yielding any of the benefits.”
Martin Fowler
Persistence Layer
Model
What is
Not MVC (phew!)
Request / Response FrameworkHTTP Framework
http://fabien.potencier.org/article/49/what-is-symfony2
What about model,persistence layer?
Meet Doctrine
http://www.doctrine-project.org/
SQL -- DBAL + ORMMongoDBCouchDBOrientDBPHPCR ODMOXM
What is
Inversion of controlService LocatorDependency Injection Container
http://www.martinfowler.com/articles/injection.htmlhttp://fabien.potencier.org/article/11/what-is-dependency-injection
Services
http://groovy.codehaus.org/https://grails.org/
Single ClassWith its Deps (min) setEasy to ReplaceEasy to Test
MVC(S)!
Controller’s pray
https://twitter.com/ornicar
Get RequestSubmit form if anyCall one Service methodReturn Response
Rendering HTML far away
Managers Managers Managers
http://blog.codinghorror.com/i-shall-call-it-somethingmanager/http://stackoverflow.com/questions/1866794/naming-classes-how-to-
avoid-calling-everything-a-whatevermanager
<SmtManager><WhatEverManager><MyManager><EtcManager>
Real Painclass BackendUserProgramsPossessionFormHandler{ protected $dep1; // deps holder props
public function __construct(DepsClass $dep1 /*, ...*/) { $this->dep1 = $dep1; }
public function process(Form $form) { $this->dep1->makeHappy($form); // ... }
How Kris writes Symfony apps#44
https://twitter.com/kriswallsmithhttp://www.slideshare.net/kriswallsmith/how-kris-writessymfonyapps
https://twitter.com/kriswallsmithhttp://www.slideshare.net/kriswallsmith/how-kris-writessymfonyapps
How Kris writes Symfony apps#44
Domain Logic Patterns
http://martinfowler.com/books/eaa.html
Domain Logic Patterns
http://martinfowler.com/books/eaa.html
Transaction ScriptDomain ModelTable ModuleService Layer
Transaction Script
Domain Model
Table Module
Domain Logic&
Application logic
Service Layer
What is next?RADDDD PatternsExamplesLayersGoodies
DDD != RADCode FirstDo not Care about persistence (yet)
Domain ModelRepositoryValue ObjectDTOStrategyState
Patterns & Code
Domain Model
Domain Model<?php
namespace MegaCorp\Core\Product;
class Product{ private $id; private $name; private $recognitionStrategy;
public function __construct( ProductId $id, $name, $recognitionStrategy ) { $this->id = $id; $this->name = $name; $this->recognitionStrategy = $recognitionStrategy; }
Repository<?php
namespace MegaCorp\Core\Product;
interface ProductRepository{ public function find(ProductId $productId);
public function findAll();
public function add(Product $product);
public function remove(Product $product);}
Value Object<?php
namespace MegaCorp\Core;
class ProductId{ private $value;
public function __construct($value) { $this->value = (string) $value; }
public function getValue() { return $this->value; }}
Value Object DateRange
Value Object DateRange<?php
public function findByDateRange( \DateTime $from, \DateTime $to )
class DateRange{ private $from; private $to; public function __construct(\DateTime $from, \DateTime $to) { $this->from = $from; $this->to = $to; }}
public function findByDateRange(\DateRange $range)
Value Object Money
<?php
class Money{ private $amount; private $currency;
public function __construct($amount, Currency $currency) { // ... }}
Value Object Money
<?php
class ProfileData{ public $firstName; public $lastName; public $birthday;}
DTO
Strategy
______ ______ _______ _______ / | / __ \ | \ | ____|| ,----'| | | | | .--. || |__ | | | | | | | | | || __| | `----.| `--' | | '--' || |____ \______| \______/ |_______/ |_______|
src└── MegaCorp ├── ApiBundle │ ├── Controller │ │ └── ... │ └── MegaCorpApiBundle.php ├── Core │ └── Product │ ├── Product.php │ ├── ProductId.php │ └── ProductRepository.php └── CoreBundle ├── Controller │ └── ... ├── Repository │ ├── InMemoryProductRepository.php │ └── MongoDbProductRepository.php └── MegaCorpCoreBundle.php
Directory structure
Layers
LayersDomain Layer -- heart of your application, Entities and Repositories
Application Layer -- ControllersPresentation Layer -- Templates / DTOs for serializerInfrastructure Layer -- framework, persistence, concrete implementations of Domain Layer
Useful goodies
BBB DDD by Eric Evans
http://amzn.com/0321125215/
DDD Quickly by InfoQ
http://www.infoq.com/minibooks/domain-driven-design-quickly
PoEAA by Martin Fowler
http://amzn.com/B008OHVDFM/
DDD and Patterns by Jimmy Nilsson
http://amzn.com/B0054KOKQQ/
Linkshttp://dddcommunity.org/
http://williamdurand.fr/http://welcometothebundle.com/http://verraes.net/http://jimmynilsson.com/blog/http://www.martinfowler.com/
http://elephantintheroom.io/ -- podcast
http://msdn.microsoft.com/en-us/magazine/dd419654.aspxhttp://www.martinfowler.com/bliki/AnemicDomainModel.htmlhttp://martinfowler.com/bliki/CQRS.html