SlideShare a Scribd company logo
1 of 46
Download to read offline
DOMAIN DRIVEN DESIGN
TACKLING COMPLEXITY
@pascallarocque
○ TRUSTCHARGE TEAM
○ BEHAT GUY
○ TDD GUY
○ SOLID GUY

○ PATTERN GUY
○ FATHER OF 3
○ STAR WARS GEEK
SOFTWARE IS COMPLICATED
CURRENT ARCHITECTURE

APPLICATION
CONTROLLER

DATA ACCESS /
BUSINESS OBJECT/
PERSISTENCE

BZ
ORM

●
●
●

DATA STORE

DATABASE

BUSINESS LOGIC IN
CONTROLLER AND IN DATA
ACCESS OBJECTS
FRAMEWORK COUPLED TO
CONTROLLER
DIRECT ACCESS TO DATA
OBJECT FROM CONTROLLER
PROBLEM
○ DEVELOPERS / ARCHITECTS ARE ONLY THINKING ABOUT THE
FRAMEWORK (DB, ORM, CACHING)
○ MOST OF OUR DEVELOPMENT TIME IS SPENT WRITING PLUMPING
FOR THE FRAMWORK INSTEAD OF REAL BUSINESS LOGIC

○ THE MEANING OF OOP IS LOST
DOMAIN DRIVEN DESIGN
WHAT
○ DOMAIN DRIVEN DESIGN IS ABOUT MAPPING BUSINESS DOMAIN
CONCEPT INTO CODE
WHY
○ TO CREATE SOFTWARE THAT REFLECT THE BUSINESS RATHER
THAN THE FRAMEWORK
DOMAIN DRIVEN ARCHITECTURE
CONTROLLER

APPLICATION
SERVICE

FRAMEWORK
●
●
●
●
●
●
●

HTTP
SESSION MANAGEMENT
RPC
PERSISTENCE
CACHING
SECURITY
MESSAGING

DOMAIN
DOMAIN
●
●
●
●

DATA ACCESS /
PERSISTENCE
DATA STORE

DAO

DATABASE

●
●

ALL LAYERS SUPPORT POPO BASED DESIGN
CONTROLLERS AND SERVICES ARE
CONSUMERS OF DOMAIN OBJECTS
BUSINESS LOGIC ONLY IN DOMAIN OBJECTS
NO DIRECT ACCESS TO DAO EXCEPT FROM
DOMAIN OBJECT
DOMAIN FIRST, FRAMEWORK SECOND
FRAMEWORK CONCERNS ARE
IMPLEMENTED BY DI
ADVANTAGES
○ PROMOTES HIGH COHESION AND LOW COUPLING
○ EASY TO TEST DOMAIN COMPONENTS
○ BUSINESS (DOMAIN) LOGIC IS ISOLATED FROM NON-DOMAIN AND
FRAMEWORK CODE
○ ADDING / CHANGING SERVICES DOES NOT INFLUENCE THE
DOMAIN OR OTHER SERVICES
DEVELOPMENT IMPACT
TRANSACTION
SCRIPTS

TABLE MODULES

DOMAIN MODEL

EFFORT TO
ENHANCE /
MAINTAIN

COMPLEXITY TO IMPLEMENT
SOURCE: PATTERNS OF ENTERPRISE APPLICATION ARCHITECTURE, MARTIN FOWLER
HOW TO DO DDD
THE UBIQUITOUS LANGUAGE
UBIQUITOUS LANGUAGE
○ SHARED TEAM LANGUAGE (DEVELOPERS AND DOMAIN EXPERTS)
○ UBIQUITOUS IS NOT AN ATTEMPT TO DESCRIBE ENTERPRISE-WIDE
DOMAIN LANGUAGE
○ ONE UBIQUITOUS LANGUAGE PER BOUNDED CONTEXT (CODE
BASE)

○ IF YOU TRY TO APPLY A SINGLE UBIQUITOUS LANGUAGE TO AN
ENTIRE ENTERPRISE, YOU WILL FAIL
public function chargeCustomer(ChargecodeData $chargecode, Transaction $transaction) {
if($chargecode->getEmail() === $transaction->getCustomerEmail()
&& $transaction->getCustomerCreditCardExpiration > date(‘Y-m’)
&& in_array($transaction->getStatus(), [‘SALE’, ‘REBILL’, ‘AUTHORISE’])
&& $chargecode->isUsed() === false) {
// Do charge
}
throw new ChargeCustomerException();
}

/**
* @Inject
* @var ChargeCodeValidationPolicy
*/
protected $oneClickPolicy;
public function chargeCustomer(ChargecodeData $chargecode, Transaction $transaction) {
if($this->oneClickPolicy->isAllowed($chargecode, $transaction)) {
// Do charge
}
throw new ChargeCustomerException();
}
DOMAIN OBJECTS

DOMAIN OBJECTS ARE INSTANCES OF REAL ENTITIES THAT HOLD THE
BUSINESS LOGIC.
MAIN ELEMENTS OF DDD
ENTITIES
○ DESIGN A CONCEPT AS AN ENTITY WHEN YOU CARE ABOUT ITS
INDIVIDUALITY, WHEN DISTINGUISHING IT FROM ALL OTHER
OBJECTS IN A SYSTEM IS A MANDATORY CONSTRAINT
(CUSTOMER, MEMBERSHIP)
○ THE ENTITY SHOULD NOT BE BOUND TO ANY FRAMEWORK (ORM),
IT SHOULD BE A PLAIN OLD PHP OBJECT (POPO)
/** @Entity */class Membership{
/** @Id @Column(type="integer") @GeneratedValue */
private $id;
/** @Column(type="string") */
private $status;
/** @ManyToOne(targetEntity="Customer") */
private $customer;
/** @OneToMany(targetEntity="Transaction", mappedBy="membership") */
private $transactions;
public function __construct {
$this->transactions = new ArrayCollection();
}
public function getCustomer() { return $this->customer; }
public function getTransactions() { return $this->transactions;}}

POPO
VALUE OBJECT
○ STRIVE TO MODEL USING VALUE OBJECTS INSTEAD OF ENTITIES
WHEREVER POSSIBLE

○ IMMUTABLE, AFTER THE OBJECT HAS BEEN INSTANTIATED, NONE
OF ITS METHODS WILL CAUSE ITS STATE TO CHANGE
○ INSTEAD OF CHANGING THE ATTRIBUTES, WOULD OBJECT
REPLACEMENT WORK INSTEAD?
$factory = new ChargeCodeGenerationDataFactory();
$chargeCodeData = $factory->generateFromArray($data);
class ChargeCodeGenerationData{
private $transactionId;
private $emailAddress;
private $accountId;
public function __construct($transactionId, $emailAddress, $accountId) {
$this->transactionId = $transactionId;
$this->emailAddress = $emailAddress;
$this->accountId = $accountId;
}
public function toArray() { return [‘transactionId’ => $this->transactionId,
‘emailAddress’ => $this->emailAddress,
‘accountId’
=> $this->accountId]; }
public function toJSON() { return json_encode($this->toArray());}}
VO BASED ON BOUNDED CONTEXT
○ IN A CUSTOMER MANAGEMENT CONTEXT CUSTOMER SHOULD BE
AN ENTITY

○ IN A MEMBERSHIP CONTEXT CUSTOMER SHOULD BE A VALUE
OBJECT
SERVICES
○ PROVIDES FUNCTIONALITIES FOR THE DOMAIN
○ STATELESS
○ DOMAIN SERVICES != APPLICATION SERVICES != CONTROLLER
○ DOMAIN SERVICES CAN HOST DOMAIN LOGIC
○

PERFORM A SIGNIFICANT BUSINESS PROCESS

○

TRANSFORM A DOMAIN OBJECT FROM ONE COMPOSITION TO ANOTHER

○

CALCULATE A VALUE REQUIRING INPUT FROM MORE THAN ONE DOMAIN OBJECT
class OneClickService{
/**
* @var ChargecodeAuthcodeValidatorInterface
*/
protected $_dataAccessor; /**
* @var Tc_Bz_HashGenerator_Interface
*/
protected $_hashGenerator;
/**
* @var ChargecodeAuthcodeValidationResponseDataFactoryInterface
*/
protected $_factoryResponceValidate;
public function __construct($dataAccessor, $hashGenerator, $factory) {
>_dataAccessor = $dataAccessor;
$this->_hashGenerator = $hashGenerator;
$this->_factoryResponceValidate = $factory;
}

/**
* validate chargecode By Authcode
*
* @param ChargecodeAuthcodeDataInterface $chargecodeAuthcodeValidationData
* @return ChargecodeAuthcodeValidationResponseData
* @throws ChargecodeAuthcodeValidationDataException
*/
public function validateChargecodeByAuthcode(ChargecodeAuthcodeDataInterface $data)
{
$decryptedData = $this->_hashGenerator->decipher( $data>getCryptedString());
if ($decryptedData === false) {
throw new ChargecodeAuthcodeValidationDataException('Not decipherable');
$this}
$this->_validateEmailLinkedToAuthcode($data->getEmailAddress(),
$data->getTransactionId());
$this->_validateCustomCodeIdLinkedToEnterprise($data->getAccountIdDestination(),
$data->getEnterpriseId());
$this->_validateCustomerIs1Clickable($data->getTransactionId());
$this->_validateCodeNotUsed($data->getAccountIdDestination(),
$data->getEmailAddress());
$reponseData = $data->toArray();
$reponseData['chargecode'] = $decryptedData['hash'];
$response = $this->_factoryResponseValidate->generateResponse($reponseData);
return $response;
}
}
AGGREGATES
○ GROUP OF ASSOCIATED ENTITIES AND VALUE OBJECTS TREATED
AS A UNIT FOR THE PURPOSE OF DATA EXCHANGE

○ ENTITY AS ROOT ELEMENT
○ ONLY THE ROOT IS OBTAINED THROUGH QUERIES
○ THE ENTITY IS RESPONSIBLE FOR MAINTAINING THE INVARIANCE
○ DELETE OPERATION MUST REMOVE EVERYTHING WITHIN THE
AGGREGATE BOUNDARY AT ONCE (CASCADE DELETE)
AGGREGATE
MEMBERSHIP

SITE

CUSTOMER

TRANSACTION

CREDIT CARD

EMAIL

TRANSACTION

CREDIT CARD

EMAIL

TRANSACTION
FACTORIES
○ PROVIDES ENCAPSULATION FOR OBJECT / AGGREGATE CREATION
○ PRODUCES AN OBJECT IN A CONSISTENT STATE
class ChargecodeAuthcodeGenerationResponseDataFactory
{
/**
* Factory method to generate chargecode validation data by authcode
*
* @param array $data Data used to generate
* @throws ChargecodeAuthcodeValidationDataException
* @return ChargecodeAuthcodeGenerationResponseData
*/
public function generateFromArray(array $data)
{
$this->_validateParameters($data);
$chargecodeData = $this->_generateDataAccessObject($data);
$data = $this->_unsetUnusedParameters($data);
$chargecodeData->setParams($data);
return $chargecodeData;
}
protected function _sendException()
{
throw new ChargecodeAuthcodeGenerationResponseDataException('Could not Generate a response');
}
protected function _generateDataAccessObject(array $data)
{
return new ChargecodeAuthcodeGenerationResponseData($data['authCode'], $data['account_id_destination'], $data['email_address'],
$data['crypted_string'], null);
}
}
REPOSITORIES
○ PATTERN FOR RETRIEVING AND SAVING OBJECTS IN THE DB
○ SHOULD NOT BE TIED TO SPECIFIC FRAMEWORK (ORM)
○ EASY SUBSTITUTION FOR TESTING
class SubEnterpriseRepository
{
/**
* @Inject
* @var SubEnterpriseDataAccessorInterface
*/
private $_dataAccessor;
/**
* @Inject
* @var SubEnterpriseParserInterface
*/
private $_dataParsor;
/**
* @Inject
* @var SubEnterpriseFactoryInterface
*/
private $_dataFactory;
/**
* @param $account
* @return mixed
*/
public function findSubEnterpriseByAccount(Account $account)
{
$results
= $this->_dataAccessor->findSubEnterpriseByAccount($account);
$parsedResults = $this->_dataParsor->parseResults($results);
return $this->_dataFactory->create($parsedResults);
}
}
DEPENDENCY INJECTION
○ OBJECTS SHOULD NOT DEPEND ON CONCRETE CONSTRUCTOR
VARIABLES, INSTEAD TO SHOULD USE INTERFACES

○ OBJECTS SHOULD NOT HAVE TO CONFIGURE ITS INSTANCE
VARIABLES IN THE CONSTRUCTOR OR INIT FUNCTION, INSTEAD
THEY SHOULD RECEIVE THEM ALREADY PRE-CONFIGURED
“

"Dependency Injection" is a 25-dollar
term for a 5-cent concept. [...]
Dependency injection means giving
an object its instance variables. [...].
- James Shore

”
class SubEnterpriseRepository
{
/**
* @Inject
* @var SubEnterpriseDataAccessorInterface
*/
private $_dataAccessor;
/**
* @Inject
* @var SubEnterpriseParserInterface
*/
private $_dataParsor;
/**
* @Inject
* @var SubEnterpriseFactoryInterface
*/
private $_dataFactory;
/**
* @param $account
* @return mixed
*/
public function findSubEnterpriseByAccount(Account $account)
{
$results
= $this->_dataAccessor->findSubEnterpriseByAccount($account);
$parsedResults = $this->_dataParsor->parseResults($results);
return $this->_dataFactory->create($parsedResults);
}
}

// Load the container
$container = new DIContainer();
$container->addDefinitionsByFile(new ArrayDefinitionFile(‘di.php’));
// Create the object
$repository = new SubEnterpriseRepository();
// Inject the dependencies
$container->injectOn($repository);

// di.php
return [
‘SubEnterpriseDataAccessorInterface’
=> [ ‘class’ : ‘DoctrineSubEnterpriseAccessor’,
‘methods’ => [
‘setHydrator’ => DOCTRINE_CORE::HYDRATE_SCALAR
]
],
‘SubEnterpriseParserInterface’
=> new SubEnterpriseDoctrineToArrayParser(),
‘SubEnterpriseFactoryInterface’
=> new SubEnterpriseResultFactory()
];

PHP-DI
class Tc_Application_Resource_DependencyInjectionContainerResource extends
Zend_Application_Resource_ResourceAbstract
{
public function init()
{
$this->_container = new DIContainer();
foreach($this->_definitionFilePath as $DIResourceFile) {
$file = $this->_loadDefinitionFile(realpath($DIResourceFile));
$this->_container->addDefinitionsFromFile($file);
}
return $this->_container;
}
private function _loadDefinitionFile($DIResourceFile)
{
$file = null;
if (0 === substr_compare($DIResourceFile, 'php', -3, 3, true)) {
$file = new DIDefinitionFileLoaderArrayDefinitionFileLoader($DIResourceFile);
}
if (0 === substr_compare($DIResourceFile, 'yml', -3, 3, true)) {
$file = new DIDefinitionFileLoaderYamlDefinitionFileLoader($DIResourceFile);
}

/**
* Initialize the dependency injection container
*/
protected function _initDependencyInjection()
{
$this->bootstrap('DependencyInjectionContainerResource');
$container = $this->getResource('DependencyInjectionContainerResource');
$dispatcher = new DIZendFramework1Dispatcher();
$dispatcher->setContainer($container);
$frontController = Zend_Controller_Front::getInstance();
$frontController->setDispatcher($dispatcher);
}

if (0 === substr_compare($DIResourceFile, 'json', -4, 4, true)) {
$file = new DIDefinitionFileLoaderJsonDefinitionFileLoader($DIResourceFile);
}
if($file === null) {
throw new Gamma_Application_Resource_Exception('Invalid Definition File Type');
}
return $file;
}

PHP-DI-ZF1
class Direct_FollowController extends Zend_Controller_Action
{
/**
* @Inject(lazy=true)
* @var TcServiceChargeCodeService
*/
private $_oneClickService;
/**
* @Inject(lazy=true)
* @var TcChargeCodeDataChargecodeAuthcodeGenerationDataFactory
*/
private $_factory;
public function generateChargeCodeByAuthcodeAction()
{
$request = $this->getRequest();
$this->getResponse()->setHeader('Content-Type', 'application/json', true);
try {
$chargeCodeGenerationData = $this->_factory->generate($request->getParams());
$this->view->answer = $this->_oneClickService->generate($chargeCodeGenerationData);
$this->render('generate-charge-code');
} catch (TcChargeCodeDataExceptionChargeCodeGenerationDataException $chargeCodeException) {
$this->view->requiredParameters = $chargeCodeException;
$this->render('charge-code-generation-authcode-invalid-parameters');
} catch (TcChargeCodeDataExceptionChargecodeAuthcodeGenerationResponseDataException $chargeCodeException) {
$this->view->requiredParameters = $chargeCodeException;
$this->render('charge-code-generation-authcode-invalid-parameters');
}
}

PHP-DI-ZF1
DOMAIN & SUB-DOMAIN
THE HEART OF DDD
DOMAIN vs DOMAIN MODEL
○ THE DOMAIN IS THE PROBLEM TO BE ADDRESSED IN SOFTWARE
○ A DOMAIN MODEL IS THE REPRESENTATION OF IN CODE OF THE
SOLUTION FOR THE DOMAIN PROBLEM
○ HAS TO BE CREATED WITH THE COOPERATION OF DEVELOPERS
AND DOMAIN EXPERTS

○ THE GOAL OF DOMAIN DRIVEN DESIGN IS TO CREATE OBJECT IN
CODE THAT REFLECT THE DOMAIN
SUB-DOMAIN vs BOUNDED CONTEXT
○ DOMAIN CAN BE DECOMPOSED INTO SUB-DOMAINS (PRODUCTS,
BILLING, MEMBERSHIP)

○ SUB-DOMAIN SPLIT THE DOMAIN INTO DIFFERENT UNIQUE
SECTIONS
○ BOUNDED CONTEXT SPLIT THE CODE INTO DIFFERENT CODE
BASES
○ SUB-DOMAIN CAN BE IMPLEMENTED BY MULTIPLE BOUNDED
CONTEXTS (MEMBERSHIP AND MEMBERSHIP REBILL)
“

ORGANIZATIONS WHICH DESIGN
SYSTEMS ARE CONSTRAINED TO
PRODUCE DESIGNS WHICH ARE
COPIES OF THE COMMUNICATION
STRUCTURES OF THESE
ORGANIZATIONS
- Melvin Conway

”
CONWAY’S LAW

SUB-DOMAIN BOUNDARIES ARE DETERMINED IN PART BY THE
COMMUNICATION STRUCTURES WITHIN AN ORGANIZATION
BOUNDED CONTEXTS
○ CODE BASE FOR DOMAIN MODEL CONTEXT
○ EVERY MODEL’S PROPERTIES AND OPERATIONS HAS SPECIAL
MEANING WITHIN THE SPECIFIC CONTEXT
ENTITY
VALUE OBJECT
CONTEXT MAPPING
○ PARTNERSHIP
○
○

○

○

SUCCEED OR FAIL TOGETHER
COORDINATED PLANNING
JOINT MANAGEMENT OF
INTEGRATION
SCHEDULED COMPLETION

○ SHARED KERNEL
○
○
○

INTIMATE INTERDEPENDENCIES
KEEP IT SMALL
CAN’T BE CHANGED WITHOUT
CONSULTATION

○ CUSTOMER-SUPPLIER
○

○

○

UPSTREAM / DOWNSTREAM
RELATIONSHIP
DOWNSTREAM PRIORITIES FACTOR
INTO UPSTREAM PLANNING
NEGOTIATED SCHEDULE

○ CONFORMIST
○

○

UPSTREAM / DOWNSTREAM
RELATIONSHIP
UPSTREAM HAS NO MOTIVATION TO
PROVIDE FOR DOWNSTREAM
CONTEXT MAPPING
○ ANTICORRUPTION LAYER
○
○

TRANSLATION LAYER
LAYER TRANSLATES IN ONE OR BOTH
DIRECTIONS BETWEEN THE TWO
MODELS

○ OPEN HOST SERVICE
○
○

SOA
PROTOCOL TO GIVE ACCESS TO
YOUR SUBSYSTEM

○ PUBLISHED LANGUAGE
○

WELL-DOCUMENTED SHARED
LANGUAGE

○ SEPARATE WAYS
○

○

COMPLETELY CUT LOOSE FROM
EACH OTHER
INTEGRATION IS EXPENSIVE WITH
SMALL BENEFITS

○ BIG BALL OF MUD
○
○
○

○

MIXED MODELS
INCONSISTENT BOUNDARIES
DRAW A BOUNDARY AROUND THE
MESS
DO NOT TRY TO APPLY
SOPHISTICATED MODELING
“

Any 3rd party system
that I have to integrate
with, was written by
a drunken monkey
typing with his feet
- Oren Eini

”
SUB-DOMAIN

ANTICORRUPTION
LAYER THAT
TRANSLATES
USER/ROLES
BETWEEN SUBDOMAINS

SUB-DOMAIN
“

Any fool can write code that a
computer can understand. Good
programmers write code that humans
can understand.
- Martin Fowler

”
REFERENCES
DOMAIN-DRIVEN DESIGN
BY ERIC EVANS

IMPLEMENTING DOMAIN-DRIVEN
DESIGN
BY VAUGHN VERNON

More Related Content

What's hot

Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right wayThibaud Desodt
 
Flink on Kubernetes operator
Flink on Kubernetes operatorFlink on Kubernetes operator
Flink on Kubernetes operatorEui Heo
 
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Steve Pember
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvCodelyTV
 
Domain Driven Design (DDD)
Domain Driven Design (DDD)Domain Driven Design (DDD)
Domain Driven Design (DDD)Tom Kocjan
 
Introduction au Domain Driven Design
Introduction au Domain Driven DesignIntroduction au Domain Driven Design
Introduction au Domain Driven DesignDNG Consulting
 
CQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDDCQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDDDennis Doomen
 
톰캣 운영 노하우
톰캣 운영 노하우톰캣 운영 노하우
톰캣 운영 노하우jieunsys
 
Hexagonal architecture: how, why and when
Hexagonal architecture: how, why and whenHexagonal architecture: how, why and when
Hexagonal architecture: how, why and whenXoubaman
 
Kafka Streams: What it is, and how to use it?
Kafka Streams: What it is, and how to use it?Kafka Streams: What it is, and how to use it?
Kafka Streams: What it is, and how to use it?confluent
 
Async Messaging in CQRS: Part 1 - Masstransit + DDD Intro
Async Messaging in CQRS: Part 1 - Masstransit + DDD IntroAsync Messaging in CQRS: Part 1 - Masstransit + DDD Intro
Async Messaging in CQRS: Part 1 - Masstransit + DDD IntroGeorge Tourkas
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software designMatthias Noback
 
Event Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQEvent Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQAraf Karsh Hamid
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Scott Wlaschin
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Alan Christensen
 
Domain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and MicroservicesDomain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and MicroservicesRadosław Maziarka
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven developmentDmitry Geyzersky
 

What's hot (20)

Hexagonal symfony
Hexagonal symfonyHexagonal symfony
Hexagonal symfony
 
Dependency injection - the right way
Dependency injection - the right wayDependency injection - the right way
Dependency injection - the right way
 
Flink on Kubernetes operator
Flink on Kubernetes operatorFlink on Kubernetes operator
Flink on Kubernetes operator
 
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
 
Architecture: Microservices
Architecture: MicroservicesArchitecture: Microservices
Architecture: Microservices
 
From framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytvFrom framework coupled code to #microservices through #DDD /by @codelytv
From framework coupled code to #microservices through #DDD /by @codelytv
 
Domain Driven Design (DDD)
Domain Driven Design (DDD)Domain Driven Design (DDD)
Domain Driven Design (DDD)
 
Introduction au Domain Driven Design
Introduction au Domain Driven DesignIntroduction au Domain Driven Design
Introduction au Domain Driven Design
 
CQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDDCQRS and Event Sourcing, An Alternative Architecture for DDD
CQRS and Event Sourcing, An Alternative Architecture for DDD
 
톰캣 운영 노하우
톰캣 운영 노하우톰캣 운영 노하우
톰캣 운영 노하우
 
Hexagonal architecture: how, why and when
Hexagonal architecture: how, why and whenHexagonal architecture: how, why and when
Hexagonal architecture: how, why and when
 
Kafka Streams: What it is, and how to use it?
Kafka Streams: What it is, and how to use it?Kafka Streams: What it is, and how to use it?
Kafka Streams: What it is, and how to use it?
 
Async Messaging in CQRS: Part 1 - Masstransit + DDD Intro
Async Messaging in CQRS: Part 1 - Masstransit + DDD IntroAsync Messaging in CQRS: Part 1 - Masstransit + DDD Intro
Async Messaging in CQRS: Part 1 - Masstransit + DDD Intro
 
Hexagonal architecture - message-oriented software design
Hexagonal architecture  - message-oriented software designHexagonal architecture  - message-oriented software design
Hexagonal architecture - message-oriented software design
 
Express JS
Express JSExpress JS
Express JS
 
Event Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQEvent Sourcing & CQRS, Kafka, Rabbit MQ
Event Sourcing & CQRS, Kafka, Rabbit MQ
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated
 
Domain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and MicroservicesDomain Driven Design - Strategic Patterns and Microservices
Domain Driven Design - Strategic Patterns and Microservices
 
Domain driven design and model driven development
Domain driven design and model driven developmentDomain driven design and model driven development
Domain driven design and model driven development
 

Viewers also liked

Leveraging more then DDD Lite in the startup project
Leveraging more then DDD Lite in the startup projectLeveraging more then DDD Lite in the startup project
Leveraging more then DDD Lite in the startup projectThomas Jaskula
 
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
 
Php Conf08 Enterprise Patterns
Php Conf08 Enterprise PatternsPhp Conf08 Enterprise Patterns
Php Conf08 Enterprise PatternsWildtech
 
Functional programming in C#
Functional programming in C#Functional programming in C#
Functional programming in C#Thomas Jaskula
 
Domain Driven Design Development Spring Portfolio
Domain Driven Design Development Spring PortfolioDomain Driven Design Development Spring Portfolio
Domain Driven Design Development Spring PortfolioSrini Penchikala
 
CQRS recipes or how to cook your architecture
CQRS recipes or how to cook your architectureCQRS recipes or how to cook your architecture
CQRS recipes or how to cook your architectureThomas Jaskula
 
CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорAlexander Byndyu
 

Viewers also liked (7)

Leveraging more then DDD Lite in the startup project
Leveraging more then DDD Lite in the startup projectLeveraging more then DDD Lite in the startup project
Leveraging more then DDD Lite in the startup project
 
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
 
Php Conf08 Enterprise Patterns
Php Conf08 Enterprise PatternsPhp Conf08 Enterprise Patterns
Php Conf08 Enterprise Patterns
 
Functional programming in C#
Functional programming in C#Functional programming in C#
Functional programming in C#
 
Domain Driven Design Development Spring Portfolio
Domain Driven Design Development Spring PortfolioDomain Driven Design Development Spring Portfolio
Domain Driven Design Development Spring Portfolio
 
CQRS recipes or how to cook your architecture
CQRS recipes or how to cook your architectureCQRS recipes or how to cook your architecture
CQRS recipes or how to cook your architecture
 
CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафор
 

Similar to Domain Driven Design Tackles Complexity

Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...Mateusz Zalewski
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using CodeceptionJeroen van Dijk
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsMichelangelo van Dam
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJSWei Ru
 
Serverless Functions and Vue.js
Serverless Functions and Vue.jsServerless Functions and Vue.js
Serverless Functions and Vue.jsSarah Drasner
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceIvan Chepurnyi
 
"Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze...
"Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze..."Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze...
"Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze...Mateusz Zalewski
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fabio Akita
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Scriptccherubino
 

Similar to Domain Driven Design Tackles Complexity (20)

Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
SOLID Principles
SOLID PrinciplesSOLID Principles
SOLID Principles
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
 
Serverless Functions and Vue.js
Serverless Functions and Vue.jsServerless Functions and Vue.js
Serverless Functions and Vue.js
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
"Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze...
"Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze..."Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze...
"Kto to pisał?!... A, to ja.", czyli sposoby, żeby znienawidzić siebie z prze...
 
Postman On Steroids
Postman On SteroidsPostman On Steroids
Postman On Steroids
 
Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009Fórum de Software Livre do Serpro RJ 2009
Fórum de Software Livre do Serpro RJ 2009
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Script
 

Recently uploaded

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 

Recently uploaded (20)

DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 

Domain Driven Design Tackles Complexity

  • 2. @pascallarocque ○ TRUSTCHARGE TEAM ○ BEHAT GUY ○ TDD GUY ○ SOLID GUY ○ PATTERN GUY ○ FATHER OF 3 ○ STAR WARS GEEK
  • 4. CURRENT ARCHITECTURE APPLICATION CONTROLLER DATA ACCESS / BUSINESS OBJECT/ PERSISTENCE BZ ORM ● ● ● DATA STORE DATABASE BUSINESS LOGIC IN CONTROLLER AND IN DATA ACCESS OBJECTS FRAMEWORK COUPLED TO CONTROLLER DIRECT ACCESS TO DATA OBJECT FROM CONTROLLER
  • 5. PROBLEM ○ DEVELOPERS / ARCHITECTS ARE ONLY THINKING ABOUT THE FRAMEWORK (DB, ORM, CACHING) ○ MOST OF OUR DEVELOPMENT TIME IS SPENT WRITING PLUMPING FOR THE FRAMWORK INSTEAD OF REAL BUSINESS LOGIC ○ THE MEANING OF OOP IS LOST
  • 6. DOMAIN DRIVEN DESIGN WHAT ○ DOMAIN DRIVEN DESIGN IS ABOUT MAPPING BUSINESS DOMAIN CONCEPT INTO CODE WHY ○ TO CREATE SOFTWARE THAT REFLECT THE BUSINESS RATHER THAN THE FRAMEWORK
  • 7. DOMAIN DRIVEN ARCHITECTURE CONTROLLER APPLICATION SERVICE FRAMEWORK ● ● ● ● ● ● ● HTTP SESSION MANAGEMENT RPC PERSISTENCE CACHING SECURITY MESSAGING DOMAIN DOMAIN ● ● ● ● DATA ACCESS / PERSISTENCE DATA STORE DAO DATABASE ● ● ALL LAYERS SUPPORT POPO BASED DESIGN CONTROLLERS AND SERVICES ARE CONSUMERS OF DOMAIN OBJECTS BUSINESS LOGIC ONLY IN DOMAIN OBJECTS NO DIRECT ACCESS TO DAO EXCEPT FROM DOMAIN OBJECT DOMAIN FIRST, FRAMEWORK SECOND FRAMEWORK CONCERNS ARE IMPLEMENTED BY DI
  • 8. ADVANTAGES ○ PROMOTES HIGH COHESION AND LOW COUPLING ○ EASY TO TEST DOMAIN COMPONENTS ○ BUSINESS (DOMAIN) LOGIC IS ISOLATED FROM NON-DOMAIN AND FRAMEWORK CODE ○ ADDING / CHANGING SERVICES DOES NOT INFLUENCE THE DOMAIN OR OTHER SERVICES
  • 9. DEVELOPMENT IMPACT TRANSACTION SCRIPTS TABLE MODULES DOMAIN MODEL EFFORT TO ENHANCE / MAINTAIN COMPLEXITY TO IMPLEMENT SOURCE: PATTERNS OF ENTERPRISE APPLICATION ARCHITECTURE, MARTIN FOWLER
  • 10. HOW TO DO DDD THE UBIQUITOUS LANGUAGE
  • 11. UBIQUITOUS LANGUAGE ○ SHARED TEAM LANGUAGE (DEVELOPERS AND DOMAIN EXPERTS) ○ UBIQUITOUS IS NOT AN ATTEMPT TO DESCRIBE ENTERPRISE-WIDE DOMAIN LANGUAGE ○ ONE UBIQUITOUS LANGUAGE PER BOUNDED CONTEXT (CODE BASE) ○ IF YOU TRY TO APPLY A SINGLE UBIQUITOUS LANGUAGE TO AN ENTIRE ENTERPRISE, YOU WILL FAIL
  • 12. public function chargeCustomer(ChargecodeData $chargecode, Transaction $transaction) { if($chargecode->getEmail() === $transaction->getCustomerEmail() && $transaction->getCustomerCreditCardExpiration > date(‘Y-m’) && in_array($transaction->getStatus(), [‘SALE’, ‘REBILL’, ‘AUTHORISE’]) && $chargecode->isUsed() === false) { // Do charge } throw new ChargeCustomerException(); } /** * @Inject * @var ChargeCodeValidationPolicy */ protected $oneClickPolicy; public function chargeCustomer(ChargecodeData $chargecode, Transaction $transaction) { if($this->oneClickPolicy->isAllowed($chargecode, $transaction)) { // Do charge } throw new ChargeCustomerException(); }
  • 13. DOMAIN OBJECTS DOMAIN OBJECTS ARE INSTANCES OF REAL ENTITIES THAT HOLD THE BUSINESS LOGIC.
  • 15. ENTITIES ○ DESIGN A CONCEPT AS AN ENTITY WHEN YOU CARE ABOUT ITS INDIVIDUALITY, WHEN DISTINGUISHING IT FROM ALL OTHER OBJECTS IN A SYSTEM IS A MANDATORY CONSTRAINT (CUSTOMER, MEMBERSHIP) ○ THE ENTITY SHOULD NOT BE BOUND TO ANY FRAMEWORK (ORM), IT SHOULD BE A PLAIN OLD PHP OBJECT (POPO)
  • 16. /** @Entity */class Membership{ /** @Id @Column(type="integer") @GeneratedValue */ private $id; /** @Column(type="string") */ private $status; /** @ManyToOne(targetEntity="Customer") */ private $customer; /** @OneToMany(targetEntity="Transaction", mappedBy="membership") */ private $transactions; public function __construct { $this->transactions = new ArrayCollection(); } public function getCustomer() { return $this->customer; } public function getTransactions() { return $this->transactions;}} POPO
  • 17. VALUE OBJECT ○ STRIVE TO MODEL USING VALUE OBJECTS INSTEAD OF ENTITIES WHEREVER POSSIBLE ○ IMMUTABLE, AFTER THE OBJECT HAS BEEN INSTANTIATED, NONE OF ITS METHODS WILL CAUSE ITS STATE TO CHANGE ○ INSTEAD OF CHANGING THE ATTRIBUTES, WOULD OBJECT REPLACEMENT WORK INSTEAD?
  • 18. $factory = new ChargeCodeGenerationDataFactory(); $chargeCodeData = $factory->generateFromArray($data); class ChargeCodeGenerationData{ private $transactionId; private $emailAddress; private $accountId; public function __construct($transactionId, $emailAddress, $accountId) { $this->transactionId = $transactionId; $this->emailAddress = $emailAddress; $this->accountId = $accountId; } public function toArray() { return [‘transactionId’ => $this->transactionId, ‘emailAddress’ => $this->emailAddress, ‘accountId’ => $this->accountId]; } public function toJSON() { return json_encode($this->toArray());}}
  • 19. VO BASED ON BOUNDED CONTEXT ○ IN A CUSTOMER MANAGEMENT CONTEXT CUSTOMER SHOULD BE AN ENTITY ○ IN A MEMBERSHIP CONTEXT CUSTOMER SHOULD BE A VALUE OBJECT
  • 20. SERVICES ○ PROVIDES FUNCTIONALITIES FOR THE DOMAIN ○ STATELESS ○ DOMAIN SERVICES != APPLICATION SERVICES != CONTROLLER ○ DOMAIN SERVICES CAN HOST DOMAIN LOGIC ○ PERFORM A SIGNIFICANT BUSINESS PROCESS ○ TRANSFORM A DOMAIN OBJECT FROM ONE COMPOSITION TO ANOTHER ○ CALCULATE A VALUE REQUIRING INPUT FROM MORE THAN ONE DOMAIN OBJECT
  • 21. class OneClickService{ /** * @var ChargecodeAuthcodeValidatorInterface */ protected $_dataAccessor; /** * @var Tc_Bz_HashGenerator_Interface */ protected $_hashGenerator; /** * @var ChargecodeAuthcodeValidationResponseDataFactoryInterface */ protected $_factoryResponceValidate; public function __construct($dataAccessor, $hashGenerator, $factory) { >_dataAccessor = $dataAccessor; $this->_hashGenerator = $hashGenerator; $this->_factoryResponceValidate = $factory; } /** * validate chargecode By Authcode * * @param ChargecodeAuthcodeDataInterface $chargecodeAuthcodeValidationData * @return ChargecodeAuthcodeValidationResponseData * @throws ChargecodeAuthcodeValidationDataException */ public function validateChargecodeByAuthcode(ChargecodeAuthcodeDataInterface $data) { $decryptedData = $this->_hashGenerator->decipher( $data>getCryptedString()); if ($decryptedData === false) { throw new ChargecodeAuthcodeValidationDataException('Not decipherable'); $this} $this->_validateEmailLinkedToAuthcode($data->getEmailAddress(), $data->getTransactionId()); $this->_validateCustomCodeIdLinkedToEnterprise($data->getAccountIdDestination(), $data->getEnterpriseId()); $this->_validateCustomerIs1Clickable($data->getTransactionId()); $this->_validateCodeNotUsed($data->getAccountIdDestination(), $data->getEmailAddress()); $reponseData = $data->toArray(); $reponseData['chargecode'] = $decryptedData['hash']; $response = $this->_factoryResponseValidate->generateResponse($reponseData); return $response; } }
  • 22. AGGREGATES ○ GROUP OF ASSOCIATED ENTITIES AND VALUE OBJECTS TREATED AS A UNIT FOR THE PURPOSE OF DATA EXCHANGE ○ ENTITY AS ROOT ELEMENT ○ ONLY THE ROOT IS OBTAINED THROUGH QUERIES ○ THE ENTITY IS RESPONSIBLE FOR MAINTAINING THE INVARIANCE ○ DELETE OPERATION MUST REMOVE EVERYTHING WITHIN THE AGGREGATE BOUNDARY AT ONCE (CASCADE DELETE)
  • 24. FACTORIES ○ PROVIDES ENCAPSULATION FOR OBJECT / AGGREGATE CREATION ○ PRODUCES AN OBJECT IN A CONSISTENT STATE
  • 25. class ChargecodeAuthcodeGenerationResponseDataFactory { /** * Factory method to generate chargecode validation data by authcode * * @param array $data Data used to generate * @throws ChargecodeAuthcodeValidationDataException * @return ChargecodeAuthcodeGenerationResponseData */ public function generateFromArray(array $data) { $this->_validateParameters($data); $chargecodeData = $this->_generateDataAccessObject($data); $data = $this->_unsetUnusedParameters($data); $chargecodeData->setParams($data); return $chargecodeData; } protected function _sendException() { throw new ChargecodeAuthcodeGenerationResponseDataException('Could not Generate a response'); } protected function _generateDataAccessObject(array $data) { return new ChargecodeAuthcodeGenerationResponseData($data['authCode'], $data['account_id_destination'], $data['email_address'], $data['crypted_string'], null); } }
  • 26. REPOSITORIES ○ PATTERN FOR RETRIEVING AND SAVING OBJECTS IN THE DB ○ SHOULD NOT BE TIED TO SPECIFIC FRAMEWORK (ORM) ○ EASY SUBSTITUTION FOR TESTING
  • 27. class SubEnterpriseRepository { /** * @Inject * @var SubEnterpriseDataAccessorInterface */ private $_dataAccessor; /** * @Inject * @var SubEnterpriseParserInterface */ private $_dataParsor; /** * @Inject * @var SubEnterpriseFactoryInterface */ private $_dataFactory; /** * @param $account * @return mixed */ public function findSubEnterpriseByAccount(Account $account) { $results = $this->_dataAccessor->findSubEnterpriseByAccount($account); $parsedResults = $this->_dataParsor->parseResults($results); return $this->_dataFactory->create($parsedResults); } }
  • 28. DEPENDENCY INJECTION ○ OBJECTS SHOULD NOT DEPEND ON CONCRETE CONSTRUCTOR VARIABLES, INSTEAD TO SHOULD USE INTERFACES ○ OBJECTS SHOULD NOT HAVE TO CONFIGURE ITS INSTANCE VARIABLES IN THE CONSTRUCTOR OR INIT FUNCTION, INSTEAD THEY SHOULD RECEIVE THEM ALREADY PRE-CONFIGURED
  • 29. “ "Dependency Injection" is a 25-dollar term for a 5-cent concept. [...] Dependency injection means giving an object its instance variables. [...]. - James Shore ”
  • 30. class SubEnterpriseRepository { /** * @Inject * @var SubEnterpriseDataAccessorInterface */ private $_dataAccessor; /** * @Inject * @var SubEnterpriseParserInterface */ private $_dataParsor; /** * @Inject * @var SubEnterpriseFactoryInterface */ private $_dataFactory; /** * @param $account * @return mixed */ public function findSubEnterpriseByAccount(Account $account) { $results = $this->_dataAccessor->findSubEnterpriseByAccount($account); $parsedResults = $this->_dataParsor->parseResults($results); return $this->_dataFactory->create($parsedResults); } } // Load the container $container = new DIContainer(); $container->addDefinitionsByFile(new ArrayDefinitionFile(‘di.php’)); // Create the object $repository = new SubEnterpriseRepository(); // Inject the dependencies $container->injectOn($repository); // di.php return [ ‘SubEnterpriseDataAccessorInterface’ => [ ‘class’ : ‘DoctrineSubEnterpriseAccessor’, ‘methods’ => [ ‘setHydrator’ => DOCTRINE_CORE::HYDRATE_SCALAR ] ], ‘SubEnterpriseParserInterface’ => new SubEnterpriseDoctrineToArrayParser(), ‘SubEnterpriseFactoryInterface’ => new SubEnterpriseResultFactory() ]; PHP-DI
  • 31. class Tc_Application_Resource_DependencyInjectionContainerResource extends Zend_Application_Resource_ResourceAbstract { public function init() { $this->_container = new DIContainer(); foreach($this->_definitionFilePath as $DIResourceFile) { $file = $this->_loadDefinitionFile(realpath($DIResourceFile)); $this->_container->addDefinitionsFromFile($file); } return $this->_container; } private function _loadDefinitionFile($DIResourceFile) { $file = null; if (0 === substr_compare($DIResourceFile, 'php', -3, 3, true)) { $file = new DIDefinitionFileLoaderArrayDefinitionFileLoader($DIResourceFile); } if (0 === substr_compare($DIResourceFile, 'yml', -3, 3, true)) { $file = new DIDefinitionFileLoaderYamlDefinitionFileLoader($DIResourceFile); } /** * Initialize the dependency injection container */ protected function _initDependencyInjection() { $this->bootstrap('DependencyInjectionContainerResource'); $container = $this->getResource('DependencyInjectionContainerResource'); $dispatcher = new DIZendFramework1Dispatcher(); $dispatcher->setContainer($container); $frontController = Zend_Controller_Front::getInstance(); $frontController->setDispatcher($dispatcher); } if (0 === substr_compare($DIResourceFile, 'json', -4, 4, true)) { $file = new DIDefinitionFileLoaderJsonDefinitionFileLoader($DIResourceFile); } if($file === null) { throw new Gamma_Application_Resource_Exception('Invalid Definition File Type'); } return $file; } PHP-DI-ZF1
  • 32. class Direct_FollowController extends Zend_Controller_Action { /** * @Inject(lazy=true) * @var TcServiceChargeCodeService */ private $_oneClickService; /** * @Inject(lazy=true) * @var TcChargeCodeDataChargecodeAuthcodeGenerationDataFactory */ private $_factory; public function generateChargeCodeByAuthcodeAction() { $request = $this->getRequest(); $this->getResponse()->setHeader('Content-Type', 'application/json', true); try { $chargeCodeGenerationData = $this->_factory->generate($request->getParams()); $this->view->answer = $this->_oneClickService->generate($chargeCodeGenerationData); $this->render('generate-charge-code'); } catch (TcChargeCodeDataExceptionChargeCodeGenerationDataException $chargeCodeException) { $this->view->requiredParameters = $chargeCodeException; $this->render('charge-code-generation-authcode-invalid-parameters'); } catch (TcChargeCodeDataExceptionChargecodeAuthcodeGenerationResponseDataException $chargeCodeException) { $this->view->requiredParameters = $chargeCodeException; $this->render('charge-code-generation-authcode-invalid-parameters'); } } PHP-DI-ZF1
  • 33. DOMAIN & SUB-DOMAIN THE HEART OF DDD
  • 34. DOMAIN vs DOMAIN MODEL ○ THE DOMAIN IS THE PROBLEM TO BE ADDRESSED IN SOFTWARE ○ A DOMAIN MODEL IS THE REPRESENTATION OF IN CODE OF THE SOLUTION FOR THE DOMAIN PROBLEM ○ HAS TO BE CREATED WITH THE COOPERATION OF DEVELOPERS AND DOMAIN EXPERTS ○ THE GOAL OF DOMAIN DRIVEN DESIGN IS TO CREATE OBJECT IN CODE THAT REFLECT THE DOMAIN
  • 35. SUB-DOMAIN vs BOUNDED CONTEXT ○ DOMAIN CAN BE DECOMPOSED INTO SUB-DOMAINS (PRODUCTS, BILLING, MEMBERSHIP) ○ SUB-DOMAIN SPLIT THE DOMAIN INTO DIFFERENT UNIQUE SECTIONS ○ BOUNDED CONTEXT SPLIT THE CODE INTO DIFFERENT CODE BASES ○ SUB-DOMAIN CAN BE IMPLEMENTED BY MULTIPLE BOUNDED CONTEXTS (MEMBERSHIP AND MEMBERSHIP REBILL)
  • 36. “ ORGANIZATIONS WHICH DESIGN SYSTEMS ARE CONSTRAINED TO PRODUCE DESIGNS WHICH ARE COPIES OF THE COMMUNICATION STRUCTURES OF THESE ORGANIZATIONS - Melvin Conway ”
  • 37. CONWAY’S LAW SUB-DOMAIN BOUNDARIES ARE DETERMINED IN PART BY THE COMMUNICATION STRUCTURES WITHIN AN ORGANIZATION
  • 38.
  • 39. BOUNDED CONTEXTS ○ CODE BASE FOR DOMAIN MODEL CONTEXT ○ EVERY MODEL’S PROPERTIES AND OPERATIONS HAS SPECIAL MEANING WITHIN THE SPECIFIC CONTEXT
  • 41. CONTEXT MAPPING ○ PARTNERSHIP ○ ○ ○ ○ SUCCEED OR FAIL TOGETHER COORDINATED PLANNING JOINT MANAGEMENT OF INTEGRATION SCHEDULED COMPLETION ○ SHARED KERNEL ○ ○ ○ INTIMATE INTERDEPENDENCIES KEEP IT SMALL CAN’T BE CHANGED WITHOUT CONSULTATION ○ CUSTOMER-SUPPLIER ○ ○ ○ UPSTREAM / DOWNSTREAM RELATIONSHIP DOWNSTREAM PRIORITIES FACTOR INTO UPSTREAM PLANNING NEGOTIATED SCHEDULE ○ CONFORMIST ○ ○ UPSTREAM / DOWNSTREAM RELATIONSHIP UPSTREAM HAS NO MOTIVATION TO PROVIDE FOR DOWNSTREAM
  • 42. CONTEXT MAPPING ○ ANTICORRUPTION LAYER ○ ○ TRANSLATION LAYER LAYER TRANSLATES IN ONE OR BOTH DIRECTIONS BETWEEN THE TWO MODELS ○ OPEN HOST SERVICE ○ ○ SOA PROTOCOL TO GIVE ACCESS TO YOUR SUBSYSTEM ○ PUBLISHED LANGUAGE ○ WELL-DOCUMENTED SHARED LANGUAGE ○ SEPARATE WAYS ○ ○ COMPLETELY CUT LOOSE FROM EACH OTHER INTEGRATION IS EXPENSIVE WITH SMALL BENEFITS ○ BIG BALL OF MUD ○ ○ ○ ○ MIXED MODELS INCONSISTENT BOUNDARIES DRAW A BOUNDARY AROUND THE MESS DO NOT TRY TO APPLY SOPHISTICATED MODELING
  • 43. “ Any 3rd party system that I have to integrate with, was written by a drunken monkey typing with his feet - Oren Eini ”
  • 45. “ Any fool can write code that a computer can understand. Good programmers write code that humans can understand. - Martin Fowler ”
  • 46. REFERENCES DOMAIN-DRIVEN DESIGN BY ERIC EVANS IMPLEMENTING DOMAIN-DRIVEN DESIGN BY VAUGHN VERNON