Upload
guiwoda
View
184
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Introduction to Domain driven design, given by @GuiWoda at #LaravelBA on sept 17, 2014
Citation preview
Domain Driven Design
Ubiquitous Language
UbiquitousLanguage@Fowler's blog
Ubiquitous LanguageThat’s all there is to it
Ubiquitous LanguageThat’s all there is to it
Questions?
Client (Domain expert)
Project Manager Developer
We need to add a new security policy to our
accounts. Our customers can’t have more than two
active offers per billing term.
We need to restrict promotions. A user cannot
have more than two promotions per month.
public function validate(User $user){ // … other crazy validations
if (count ($user->getPromotions()) > 2) throw new ValidationException( “User can’t have more than 2 promotions per month” );
// … continue with crazy validations}
Favor model language over translations
Client (Domain expert)
Project Manager Developer
We need to add a new security policy to our
accounts. Our customers can’t have more than two
active offers per billing term.
public function validate(Account $account){ // … other crazy validations
if (! $account->satisfies( new ActiveOffersPerBillingTermSecurityPolicy )) throw new ValidationException( “Account did not satisfy the active offers security policy” );
// … continue with crazy validations}
ActiveOffersPerBillingTermSecurityPolicy
… really?TOO MUCH CODE!
I WON’T TYPE THAT!!!11
Semantics
SemanticsActiveOffersPerBillingTermSecurityPolicy means something
in the MODEL LANGUAGE
count($user->getPromotions()) > 2 does not convey this knowledge
SemanticsActiveOffersPerBillingTermSecurityPolicy means something
in the MODEL LANGUAGE
count($user->getPromotions()) > 2 does not convey this knowledge
=> MAKE IMPLICIT BUSINESS RULES EXPLICIT
Favor model language over translations
When a domain expert (client) feels something’s wrong with the model language, you’ll know something’s wrong with the domain model.
Client (Domain expert)
Project Manager Developer
When we talk about a billing term, we need to consider if the customer is billed on a
monthly or yearly basis.
| class ActiveOffersPerBillingTermSecurityPolicy | { | protected $maxOffers = 2; | | public function isSatisfiedBy(Account $account) | { | return count(- | $account->getMonthlyOffers()+ | $account->getOffersForBillingTerm() | ) < $this->maxOffers; | }
Domain Knowledge
Domain KnowledgeFocus your efforts in building a clear domain,
specific to your client’s needs
Knowledge crunching
Client (Domain expert)
Project Manager Developer
class LongOverdueCustomerContactCommand{ public function execute() { $customers = Customer::where( ‘account.balance’, ‘<’, 0 )->get();
foreach ($customers as $customer) $this->sendRefinanceEmail($customer); }}
We need to contact long overdue customers to refinance their debt.
Client (Domain expert)
Project Manager Developer
class LongOverdueCustomerContactCommand{ public function execute() { $customers = Customer::where( ‘account.balance’, ‘<’, 0 )->get();
foreach ($customers as $customer) $this->sendRefinanceEmail($customer); }}
We need to contact long overdue customers to refinance their debt.
Client (Domain expert)
Project Manager Developer
We need to contact long overdue customers to refinance their debt.
What is the difference between a regular customer, an overdue customer and a
long overdue customer?
Client (Domain expert)
Project Manager Developer
class CustomerRepository{ public function findOverdue() { return Customer::where(‘account.balance’, ‘<’, 0) ->get(); }
public function findLongOverdue() { // Write more complex query logic for this one... }}
Overdue is straightforward, customers in debt right now.
Long overdue customers are the ones that have been overdue over the last 3
billing terms, at the end of each billing term.
Knowledge crunchingKnowledge crunching deepens the domain
model, and brings better understanding
But… How?
Domain-orientedDesign Patterns
class AccountsController{ public function index() { $accounts = Account::all();
return View::make(‘accounts.index’, [ ‘accounts’ => $accounts ]); }}
class AccountsController{ public function index() { $accounts = Account::all();
return View::make(‘accounts.index’, [ ‘accounts’ => $accounts ]); }}
EvansClassification@Fowler's blog
Entities
EntitiesObjects with an identity
LifespanUnique criteria
ValueObjects
ValueObjectsDefined by their attributes
Aggregates
AggregatesCluster of domain objectsTransactional coherence
Services
ServicesDomain coordinators
Define actions
Repositories
RepositoriesData access abstraction
Factories
FactoriesObject creation
Domain Events
Domain EventsObjects that represent significant domain
events
Domain-orientedArchitecture
Layered Architecture
Layered Architecture
?
Hexagonal Architecture
Hexagonal Architecture
?
Domain-orientedArchitecture
Isolate your domain model from specific application needs:
UI - Persistence - External Services - Application workflow - etc...
So… What’s the point?
It’s not about writing code
It’s not about writing codeThat’s the easy part… right?
It’s not about writing codeIt’s about understanding what needs to be
solved before starting to code
Creating a language which makes conversations
between domain experts and developers possible without
misinterpretations
Creating a language which makes conversations
between domain experts and developers possible without
(so many) misinterpretations
● Eric Evans, “Domain-Driven Design: Tackling Complexity in the Heart of Software”
● Vaughn Vernon, “Implementing Domain-Driven Design”
● Martin Fowler, “Patterns of Enterprise Application Architecture”
● dddcommunity.org | Domain Driven Design Community
● -http://domainlanguage.com/ddd/reference/DDD_Reference_2011-01-31.pdf
● -http://www.lmgtfy.com/?q=Domain+Driven+Design