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

Présentation spring data Matthieu Briend
Présentation spring data  Matthieu BriendPrésentation spring data  Matthieu Briend
Présentation spring data Matthieu BriendSOAT
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.jsRob O'Doherty
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js ExpressEyal Vardi
 
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
 
Technologies sur angular.pptx
Technologies sur angular.pptxTechnologies sur angular.pptx
Technologies sur angular.pptxIdrissaDembl
 
[JWPA-1]의존성 주입(Dependency injection)
[JWPA-1]의존성 주입(Dependency injection)[JWPA-1]의존성 주입(Dependency injection)
[JWPA-1]의존성 주입(Dependency injection)Young-Ho Cho
 
WebLogic Scripting Tool Overview
WebLogic Scripting Tool OverviewWebLogic Scripting Tool Overview
WebLogic Scripting Tool OverviewJames Bayer
 
Maven 3 Overview
Maven 3  OverviewMaven 3  Overview
Maven 3 OverviewMike Ensor
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with SpringJoshua Long
 
A Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on AndroidA Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on AndroidOutware Mobile
 
ADF Bindings & Data Controls
ADF Bindings & Data ControlsADF Bindings & Data Controls
ADF Bindings & Data ControlsRohan Walia
 
Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsAlexander van Trijffel
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOPDzmitry Naskou
 
[JWAP-2] DI & Spring
[JWAP-2] DI & Spring[JWAP-2] DI & Spring
[JWAP-2] DI & SpringYoung-Ho Cho
 

What's hot (20)

Présentation spring data Matthieu Briend
Présentation spring data  Matthieu BriendPrésentation spring data  Matthieu Briend
Présentation spring data Matthieu Briend
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js Express
 
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
 
Its time to React.js
Its time to React.jsIts time to React.js
Its time to React.js
 
Technologies sur angular.pptx
Technologies sur angular.pptxTechnologies sur angular.pptx
Technologies sur angular.pptx
 
[JWPA-1]의존성 주입(Dependency injection)
[JWPA-1]의존성 주입(Dependency injection)[JWPA-1]의존성 주입(Dependency injection)
[JWPA-1]의존성 주입(Dependency injection)
 
Node js introduction
Node js introductionNode js introduction
Node js introduction
 
React
React React
React
 
WebLogic Scripting Tool Overview
WebLogic Scripting Tool OverviewWebLogic Scripting Tool Overview
WebLogic Scripting Tool Overview
 
React js
React jsReact js
React js
 
Maven 3 Overview
Maven 3  OverviewMaven 3  Overview
Maven 3 Overview
 
REST APIs with Spring
REST APIs with SpringREST APIs with Spring
REST APIs with Spring
 
Domain Driven Design
Domain Driven Design Domain Driven Design
Domain Driven Design
 
A Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on AndroidA Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on Android
 
ADF Bindings & Data Controls
ADF Bindings & Data ControlsADF Bindings & Data Controls
ADF Bindings & Data Controls
 
Applying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain ModelsApplying Domain-Driven Design to craft Rich Domain Models
Applying Domain-Driven Design to craft Rich Domain Models
 
Spring Framework - AOP
Spring Framework - AOPSpring Framework - AOP
Spring Framework - AOP
 
[JWAP-2] DI & Spring
[JWAP-2] DI & Spring[JWAP-2] DI & Spring
[JWAP-2] DI & Spring
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 

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

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
 

Similar to Domain Driven Design (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
 
Domain Driven Design 101
Domain Driven Design 101Domain Driven Design 101
Domain Driven Design 101
 
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
 

Recently uploaded

Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 

Recently uploaded (20)

Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 

Domain Driven Design

  • 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