(println "Hello World! :)")
DDD as an implementation detail
Eloi Poch
Sergi González
Who$are$we?$
$
!
es.linkedin.com/in/eloipoch/$
$
$
@eloipoch$
$
Eloi.poch@akamon.com$
Eloi!Poch!
!
Technical!Lead!at!@Akamon!
•  So8ware$Developer$
•  Clojure$developer$wannabe$
•  Want$to$code$in$Castefa$beach$while$drinking$wine$
(conj '(1 2 3) 4)
Who$are$we?$
$
!
es.linkedin.com/in/sergigp/$
$
$
“SergiGP$
$
Sergi.gonzalez@akamon.com$
Sergi!
!
Technical!Lead!at!@Akamon!
•  So<ware$Developer$
•  Chief$Trolling$Officer$
•  Two$animals$remaining$to$have$an$urban$zoo$
Akamon
A little bit on Akamon before
we deal with the technical stuff
We#develop#Social#Casino#Games#
Por$olio'of'Facebook'games'
Por$olio'of'Mobile'apps'
Recently(launched(a(new(Casino(Suite(
Technically …
Flash Client Game Server Backend
AS3
Nova
Java
JReactive & Vertx
PHP
Horus
@eloipoch @jordillonch @SergiGP
@jorgeavila_ss @jdiezc
@jvalduvieco
@amassa5
Who we are? The backend team
Development
Problems
Our expectations…
Performance
Big Data
Difficult Algorithms
Concurrency
Real time analytics
Scalability
The ugly truth…
Technical Problems
Code Complexity
Big ball of mud
Shared State
Coupling
& Non-Technical
problems
Different Cultures
Tackling Complex Code
The Philosophy
Simple made Easy
Complex((
One(role(
One(task(
not(a(single(opera2on(
(
OBJECTIVE
Hard(
Familiar,(near(your(
knowledge(
(
(
Simple(vs(Easy(
(
SUBJECTIVEOBJECTIVE
Simple vs Easy
$mysqli = new mysqli("localhost", "horus", "olakease", “suite");
$mysqli->query("INSERT INTO users …”))
SIMPLE
EASY
/**
* @ORMEntity
* @ORMTable(name="product")
*/
class Product
$sum = function ($carry, $item) { return $carry + $item; }
array_reduce([1, 2, 3], $sum);
$acc = 0;
foreach ([1, 2, 3] as $value) {
$acc += $value;
}
SIMPLE
EASY
Simple vs EasySimple vs Easy
$acc = 0;
foreach ([1, 2, 3] as $value) {
$acc += $value;
}
SIMPLE
EASY
(reduce + [1 2 3])
Simple vs EasySimple vs Easy
Simplicity vs Easiness
• Easy to understand
• Easy to debug
• Easy to change,
flexibility,
maintenable
• Easy to use
• Hard to debug
• Hard to change
Complected
• Something does more than one thing and you can’t
split it easily
• Source of accidental complexity
• DON’T DO IT
Essential Complexity
VS
Accidental Complexity
Do not complect, compose
Tackling Complex Code
The Theory
Organisational level
Pair Programming
Pull Requests
Code Reviews
Continuous Integration
Self Empowerment
Never ask for permission unless it
would be reckless not to
Trust
Great teams are unafraid to air their dirty laundry, admit
their mistakes, their weaknesses and their concerns
without fear.
Patrick Lencioni
Technical Level
Lean Approach
Any model/solution
is provisional
YAGNI
You Aren’t Gonna Need It
DDD Concepts
• DDD Tactical:
• Application
Services
• Domain Services
• Domain Events
• Repositories
• AR & VO
• DDD Strategical:
• Modules
• Bounded
Contexts
• SubDomains
• Context Maps
CQRS Concepts
Hexagonal
Architecture
TDD & BDD
Tackling Complex Code
The Practice
Divide, Test &
Conquer
Product Entity
Example
Product
Id
Name
Description
Price
Currency
Image Url
Coins
StoreId
Product
Product
Descriptions
Product
Prices
Stores
Product
Benefits
Product
Images
ProductId
Product
Description
Product
Price
Stores
Product
Benefit
Product
Image
Description
Name Currency
Amount
Coins
StoreId
Image Url
ProductId
Product
Description
Product
Price
Stores
Product
Benefit
Product
Image
Description
Name Currency
Amount
Coins
StoreId
Image Url
Product BC
ProductId
Product
Description
Product
Price
Stores
Product
Benefit
Product
Image
Description
Name Currency
Amount
Coins
StoreId
Image Url
Pricing/Sales BC
Product BC
Product
Id
BenefitId
Product Price
ProductId
Amount
Currency
Product
Description
ProductId
Name
Description
Product Benefit
Id
Amount
VirtualMoneyId
Product Store
ProductId
StoreId
HORUS
Big Picture
• Directories: 773
• Files: 1501
• Lines of code: 113885
• Non-Comment Lines of Code: 88806 (80%)
• Average Class Length: 14 lines
• Average Method Length: 2 lines
• Cyclomatic Complexity / LLOC: 0.06
• Cyclomatic Complexity / Number of Methods: 1.21
HORUS
Big Picture of our Code in Horus
• Directories: 773 / 558
• Files: 1501 / 1001
• Lines of code: 113885 / 41205
• Non-Comment Lines of Code: 88806 (80%) / 38045 (92%)
• Average Class Length: 14 lines / 5 lines
• Average Method Length: 2 lines / 2 lines
• Cyclomatic Complexity / LLOC: 0.06 / 0.03
• Cyclomatic Complexity / Number of Methods: 1.21 / 1.14
UserPostController Command Bus
UserRegistratorCommandHandler
UserRegistrator
Domain
Event
Publisher
UserRegisteredDomainEv
entSubscriber
UserAccountOpener
User UserRepository Event
Subscribers
.
.
.
POST /users
[
userId: 0db90987-5ce1-4683-bb05-7d1b5539cb0b
]
Command
Handlers
.
.
.
UserRegisteredDomainEvent
User
HORUS
BASIC REQUEST
UserRegistrationCommand
UserRegistrationCommand
userId
analyticsContextId
userId
analyticsContextId
UserRegisteredDomainEvent
userId
analyticsContextId
id 

(Economy Account)
UserPostController Command Bus
UserRegistratorCommandHandler
UserRegistrator
Domain
Event
Publisher
UserRegisteredDomainEv
entSubscriber
UserAccountOpener
User UserRepository Event
Subscribers
.
.
.
POST /users
[
userId: 0db90987-5ce1-4683-bb05-7d1b5539cb0b
]
Command
Handlers
.
.
.
UserRegisteredDomainEvent
User
HORUS
BASIC REQUEST
UserRegistrationCommand
UserRegistrationCommand
userId
analyticsContextId
userId
analyticsContextId
UserRegisteredDomainEvent
userId
analyticsContextId
id 

(Economy Account)
UserModule
EconomyModule
Operational
Analytics
Support
Marketing
DE
C
Q
Q
We are still
COUPLED !!
Operational
Analytics
Support
Marketing
HTTP
…
Tackling Complex Code
The Conclusions
Mistakes
• Do not store domain events
• Own libraries for CQRS & DDD
• Do not use Domain Services
• Domain events with wrong identifiers
• Couple App Services to Commands & Queries
• Not start earlier some Modules/Bounded Contexts
Mistakes
• Let the DB guide us
• Let the framework guide us
Problems
• Domain Events: Lost of order (async)
• Doctrine
• Unit Of Work + Integration Test = Fail
• Embedded: Identifier or not
• Behat: The Container
Tips & Tricks
• Repositories:
• Just add, save and find
• Use of DQL implies the schema is too complex
• Controllers: 50 lines of code
• Application Services: Avoid business logic
• One step at time: Hex. Arch. -> DDD -> CQRS -> ES?
• Start it as a Module and promote it later to BC
TROLLTIME
QUESTIONS?
Akamon Developers

PHP Barcelona Monthly Talk Feb 2015