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

Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applicationsFabricio Epaminondas
 
Py.test
Py.testPy.test
Py.testsoasme
 
날로 먹는 Django admin 활용
날로 먹는 Django admin 활용날로 먹는 Django admin 활용
날로 먹는 Django admin 활용KyeongMook "Kay" Cha
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithVictor Rentea
 
Workshop Spring - Session 1 - L'offre Spring et les bases
Workshop Spring  - Session 1 - L'offre Spring et les basesWorkshop Spring  - Session 1 - L'offre Spring et les bases
Workshop Spring - Session 1 - L'offre Spring et les basesAntoine Rey
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration수홍 이
 
Introduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsIntroduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsEric Hogue
 
Django admin site 커스텀하여 적극적으로 활용하기
Django admin site 커스텀하여 적극적으로 활용하기Django admin site 커스텀하여 적극적으로 활용하기
Django admin site 커스텀하여 적극적으로 활용하기영우 박
 
Spring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrineSpring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrineSyrine Ben aziza
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureJosé Paumard
 
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
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 Yong Joon Moon
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술NAVER D2
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications JavaAntoine Rey
 

What's hot (20)

Clean code
Clean codeClean code
Clean code
 
Hexagonal architecture for java applications
Hexagonal architecture for java applicationsHexagonal architecture for java applications
Hexagonal architecture for java applications
 
Py.test
Py.testPy.test
Py.test
 
날로 먹는 Django admin 활용
날로 먹는 Django admin 활용날로 먹는 Django admin 활용
날로 먹는 Django admin 활용
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a Monolith
 
JUnit 5
JUnit 5JUnit 5
JUnit 5
 
Workshop Spring - Session 1 - L'offre Spring et les bases
Workshop Spring  - Session 1 - L'offre Spring et les basesWorkshop Spring  - Session 1 - L'offre Spring et les bases
Workshop Spring - Session 1 - L'offre Spring et les bases
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
DDD Introduction
DDD IntroductionDDD Introduction
DDD Introduction
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
 
Introduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec JenkinsIntroduction à l’intégration continue avec Jenkins
Introduction à l’intégration continue avec Jenkins
 
Django admin site 커스텀하여 적극적으로 활용하기
Django admin site 커스텀하여 적극적으로 활용하기Django admin site 커스텀하여 적극적으로 활용하기
Django admin site 커스텀하여 적극적으로 활용하기
 
Spring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrineSpring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrine
 
Asynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFutureAsynchronous API in Java8, how to use CompletableFuture
Asynchronous API in Java8, how to use CompletableFuture
 
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
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
Bbl sur les tests
Bbl sur les testsBbl sur les tests
Bbl sur les tests
 

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
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Scriptccherubino
 

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
 
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

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
 
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
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
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
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
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
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
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
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 

Recently uploaded (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
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...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
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
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
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
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
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
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
+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...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 

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