what is ddd and how could it help you

Post on 14-Apr-2017

112 Views

Category:

Software

3 Downloads

Preview:

Click to see full reader

TRANSCRIPT

What isDDD

and how could it help you

Luis Henrique Mulinariluismulinari

luis.mulinari@gmail.com

Frameworks PHPSymphony

CakePHP

CodeIgniter

LarvalSilex

Yii

PhalconZend Framework Nette

Kohana

SGBD and others SQLite

Eloquent

NoSQL

Larval

Doctrine

SQL

SybaseMySQLMongoDB

PDO

Interfaces Command Line Web Browser APIs

ORMActive Record

What do they all have in common?

and

All these tools were/are/will be the “best choice”

Your domain should not worry about that

Domain-driven design

BasketWasCreated or BasketWasPickedUp

Concept created by Eric Evans (2003)

It is an approach of software development, designed to work with complex and large scaled software

It proposes an Ubiquitous language between business and software (developers and business experts)

It focuses on domain and business

When should we use it?

When should we not use it?

Complex domain with many business rules

Iterative process with a long lifecycle

Growth forecast of complexity

Simple domains (like CRUDs)

Why do we use it?

Agile, iterative and continuous modelling

Less coupling, more cohesive, flexible and extensible code

Testable Code

Agreement between domain experts and developers

BDD tests close to the code

Software for everyone to understand

Domain-driven design

DDD and PHP

ORM

Dependency Injection

UUID

Frameworks

Other tools

EntitiesHave an identity that endures over the time

1 class User { 2 private $username; 3 private $password; 4 5 public function getUsername() : string { 6 return $this->username; 7 } 8 9 public function setUsername(string $username) { 10 $this->username = $username; 11 } 12 13 public function getPassword() : string { 14 return $this->password; 15 } 16 17 public function setPassword(string $password) { 18 $this->password = $password; 19 } 20 }

Don’t forget the PSR-1 :P

EntitiesEntities have behaviour Entities aren't typed arrays (getters e setters)

1 class User { 2 private $banned; 3 private $username; 4 private $passwordHash; 5 6 public function toNickname() : string { 7 return $this->username; 8 } 9 10 public function authenticate(string $pass, callable $checkHash) : bool { 11 return $checkHash($pass, $this->passwordHash) 12 && ! $this->hasActiveBans(); 13 } 14 15 public function changePass(string $pass, callable $hash) { 16 $this->passwordHash = $hash($pass); 17 } 18 }

beberlei/assert - Thin assertion library for use in libraries and business-model

EntitiesKeep collections hidden in your entities

Disallow Collection access from outside the entity

1 public function banUser(Uuid $userId) 2 { 3 $user = $this->repository->find($userId); 4 5 $user->getBans()->add(new Ban($user)); 6 }

1 class User 2 { 3 private $bans; 4 5 public function getBans() : Collection { 6 return $this->bans; 7 } 8 }

1 class User 2 { 3 private $roles; 4 5 public function promote(Role $role) { 6 $this->roles[] = $role; 7 } 8 9 public function is(Role $role) : bool { 10 return $this->roles->has($role); 11 } 12 }

Entities 1 class User { 2 private $id; 3 private $username; 4 5 public function __construct(string $username) { 6 $this->id = Uuid::uuid4(); 7 $this->username = $username; 8 } 9 }

Your db operations will block each other

You are denying bulk inserts

You cannot make multi-request transactions

Your object is invalid until saved

Your object does not work without the DB

Immutable data is simple

Immutable data is cacheable (forever)

Immutable data is predictable

Immutable data enables historical analysis Or append-only data-structures

Avoid Auto-generated Identifiers Stay valid after __construct

Avoid Soft-deletes Avoid setters

DateTimeImmutable

More expressive

Easier to test

Less coupling

More flexible

Easier to refactor

Value ObjectsMartin Fowler defines a Value Object as a small object such as money or a date range object.

Examples: numbers, text strings, dates, times, a person’s full name (composed of first, middle, last name, and title), currencies, colours, phone numbers, and postal code.

1 class Email { 2 public function __construct($email) { 3 if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { 4 throw new InvalidArgumentException('...'); 5 } 6 7 $this->email = $email; 8 } 9 10 public function __toString() : string { 11 return $this->email; 12 } 13 }

ValueObjects ensure consistency Immutability Validate your data

AggregatesMartin Fowler defines Aggregates as a cluster of domain objects that can be treated as a

single unit.Aggregates are all about transactions.

1 class Order { 2 function __construct( 3 Customer $customer, 4 ProductList $productList 5 ) { 6 $this->id = Uuid::uuid4(); 7 $this->customer = $customer; 8 $this->productList = $productList; 9 $this->status = Status::open(); 10 } 11 12 public function getTotal() { 13 // ... 14 } 15 16 // ... 17 }

Repositories

1 interface OrderRepository { 2 public function findById($id) : Order; 3 4 public function findByUser(User $user) : ArrayCollection; 5 }

Repositories act as storage locations, where a retrieved object is returned in the exact same state it was persisted

1 class DoctrineOrderRepository implements OrderRepository { } 2 3 class FileOrderRepository implements OrderRepository { } 4 5 class InMemoryOrderRepository implements OrderRepository { }

Infrastructure Layer

Prefer Query Functions

FactoriesFactories help in decoupling the client from knowing how to build complex

objects and Aggregates

1 class ComplexObjectFactory { 2 3 public function create ( 4 User $user, 5 ProductList $productList, 6 ShipAddress $shipAddress 7 ) { 8 $object = new Object(...); 9 10 // complex logic 11 12 return $object; 13 } 14 } 15

Services

When there are operations that need to be represented, we can consider them to be

services

1 class OrderCreator { 2 3 /** 4 * @var EntityManagerInterface 5 */ 6 private $entityManager; 7 8 /** 9 * @var EventDispatcherInterface 10 */ 11 private $eventDispatcher; 12 13 public function create( 14 Customer $customer, 15 ProductList $productList 16 ) : Order { 17 $order = $this->factory->create(...); 18 19 // ... some domain validations 20 21 $this->entityManager->persist($order); 22 23 $this->eventDispatcher->dispatch( 24 OrderEvent::CREATED, 25 new OrderEvent($order) 26 ); 27 28 // ... 29 30 return $order; 31 } 32 }

CouponDiscount = null

Prefer NullObject Pattern

Command PatterUbiquitous Language

1 $command = new SuspendCustomer($customer); 2 3 $commandBus->handle($command);

Commands express intend (user actions)Commands are simple

Commands are Value Objects

CQRSCommand-Query Responsibility Segregation

Read Write

90% 10%

ViewModels / Flexible

Eventually consistent

Validation / Business rules

Coherence (ACID)

CQRS

Overview

and

All those tools were/are/will be the “best choice”

Your domain should not worry about that

Thanks!

Questions?

Credits and References

Luís Otávio Cobucci Oblonczyk

Domain-driven Design - Eric Evans

Patterns of Enterprise Application Architecture - Martin Folwer

Mathias Verraes

Domain-Driven Design in PHP Carlos Buenosvinos, Christian Soronellas and Keyvan Akbary

Marco Pivetta

Isabel Janke <3

top related