DDD in PHP
on example of Symfony
cystbear
Symfony expert
MongoDB adept
Erlang fun
OSS doer
KNPer
https://twitter.com/1cdecoder
https://github.com/cystbear
http://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?
Model
View
Controller
Where to store business logic?
Model
View
Controller
Where to store business logic?
Model
View
Controller
Where to store business logic?
Model
View
Controller -- YEAH!
Welcome to
Fat Stupid Ugly Controllers
FSUC/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.html
http://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 Framework
HTTP Framework
http://fabien.potencier.org/article/49/what-is-symfony2
What about model,
persistence layer?
Meet Doctrine
http://www.doctrine-project.org/
SQL -- DBAL + ORM
MongoDB
CouchDB
OrientDB
PHPCR ODM
OXM
What is
Inversion of control
Service Locator
Dependency Injection Container
http://www.martinfowler.com/articles/injection.html
http://fabien.potencier.org/article/11/what-is-dependency-injection
Services
http://groovy.codehaus.org/
https://grails.org/
Single Class
With its Deps (min) set
Easy to Replace
Easy to Test
MVC(S)!
Controller’s pray
https://twitter.com/ornicar
Get Request
Submit form if any
Call one Service method
Return 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 Pain
class 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/kriswallsmith
http://www.slideshare.net/kriswallsmith/how-kris-writessymfonyapps
https://twitter.com/kriswallsmith
http://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 Script
Domain Model
Table Module
Service Layer
Transaction Script
Domain Model
Table Module
Domain Logic
&
Application logic
Service Layer
What is next?
RAD
DDD Patterns
Examples
Layers
Goodies
DDD != RAD
Code First
Do not Care about persistence (yet)
Domain Model
Repository
Value Object
DTO
Strategy
State
Patterns & Code
Domain Model
Domain Model
<?php
namespace MegaCorpCoreProduct;
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 MegaCorpCoreProduct;
interface ProductRepository
{
public function find(ProductId $productId);
public function findAll();
public function add(Product $product);
public function remove(Product $product);
}
Value Object
<?php
namespace MegaCorpCore;
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
Layers
Domain Layer -- heart of your application, Entities and Repositories
Application Layer -- Controllers
Presentation Layer -- Templates / DTOs for serializer
Infrastructure 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 Patternsby Jimmy Nilsson
http://amzn.com/B0054KOKQQ/
Links
http://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.aspx
http://www.martinfowler.com/bliki/AnemicDomainModel.html
http://martinfowler.com/bliki/CQRS.html
https://joind.in/11576
Thanks!

DDD on example of Symfony (Webcamp Odessa 2014)