Slide 1

Slide 1 text

AVOIDING THE MUD by Richard Miller http://www.flickr.com/photos/burge5000/22568539/

Slide 2

Slide 2 text

@mr_r_miller http://www.richardmiller.co.uk

Slide 3

Slide 3 text

http://www.flickr.com/photos/brostad/8583990904

Slide 4

Slide 4 text

http://www.flickr.com/photos/dominik99/384027019

Slide 5

Slide 5 text

http://www.flickr.com/photos/jasmeet/2158002974

Slide 6

Slide 6 text

Bundles For Everything? http://www.flickr.com/photos/jarkel/2288176

Slide 7

Slide 7 text

Separate Domain Model From Bundles http://www.flickr.com/photos/30666161@N05/3705814710

Slide 8

Slide 8 text

HumanResourcesBundle

Slide 9

Slide 9 text

HumanResourcesBundle HumanResources

Slide 10

Slide 10 text

HumanResourcesBundle HumanResources

Slide 11

Slide 11 text

http://www.flickr.com/photos/26582481@N08/3040936355 Enough?

Slide 12

Slide 12 text

Still Tightly Coupled

Slide 13

Slide 13 text

AbsenceEntity Request Absence Form Cancel Absence Form Approve Absence Form Change Absence Type Form

Slide 14

Slide 14 text

Sensio\HumanResources\Absence\AbsenceEntity: properties: reason: - NotBlank: { groups: [cancellation] } - Length: { max: 300, groups: [cancellation] }

Slide 15

Slide 15 text

AbsenceEntity Request Absence Form Cancel Absence Form Approve Absence Form Change Absence Type Form Request Absence Command Cancel Absence Command Approve Absence Command Change Absence Type Command

Slide 16

Slide 16 text

What About Templates?

Slide 17

Slide 17 text

AbsenceEntity upcoming .html .twig details .html .twig calendar .html .twig unapproved .html .twig

Slide 18

Slide 18 text

{% if absence.endDate < date() %} past {% else %} absence.status {% endif %} getDisplayStatus() AbsenceEntity getEndDate() getStatus()

Slide 19

Slide 19 text

{% if absence.endDate < date() %} past {% else %} absence.status {% endif %} getDisplayStatus() AbsenceEntity getEndDate() getStatus()

Slide 20

Slide 20 text

{{ absence.displayStatus }} getDisplayStatus() AbsenceEntity getEndDate() getStatus() getDisplayStatus()

Slide 21

Slide 21 text

{{ absence.displayStatus }} getDisplayStatus() AbsenceEntity getEndDate() getStatus() getDisplayStatus()

Slide 22

Slide 22 text

AbsenceEntity Request Absence Form Cancel Absence Form Approve Absence Form Change Absence Type Form Absence View upcoming .html .twig details .html .twig calendar .html .twig unapproved .html .twig

Slide 23

Slide 23 text

AbsenceEntity Request Absence Form Cancel Absence Form Approve Absence Form Change Absence Type Form Absence View upcoming .html .twig details .html .twig calendar .html .twig unapproved .html .twig getStatus()

Slide 24

Slide 24 text

Unapproved Absence View Calendar View AbsenceEntity Request Absence Form Cancel Absence Form Approve Absence Form Change Absence Type Form Upcoming Absences View Absence Details View upcoming .html .twig details .html .twig calendar .html .twig unapproved .html .twig

Slide 25

Slide 25 text

SRP

Slide 26

Slide 26 text

Behaviour Not State

Slide 27

Slide 27 text

Request Absence Controller Absence Entity setReason($reason) setStatus(AbsenceEntity::CANCELLED) setCancellationDate(new DateTime()) Cancel Absence Command getReason()

Slide 28

Slide 28 text

Request Absence Controller Absence Entity cancel($reason) Cancel Absence Command getReason()

Slide 29

Slide 29 text

Cancel Absence Command Absence Entity Validate internal consistency Validate user input

Slide 30

Slide 30 text

CancelAbsenceComm andHandler Cancel Absence Command Handler AbsenceEntity cancel($reason) handle($command) Request Absence Controller Absence Entity cancel($reason) Cancel Absence Command

Slide 31

Slide 31 text

Infrastructure?

Slide 32

Slide 32 text

Absence Repository (Interface) findById($id) findUpcomingByMember($member) findAllByMember($member) Doctrine ORM Absence Repository Doctrine ODM Absence Repository Guzzle Client Absence Repository Infrastructure Domain

Slide 33

Slide 33 text

AbsenceEntity Absence Repository Domain Bundle Service Config Infrastructure Doctrine ORM Absence Repository Mapping Config

Slide 34

Slide 34 text

Absence Repository (Interface) findById($id) findUpcomingByMember($member) findAllByMember($member) add(AbsenceEntity $absence)

Slide 35

Slide 35 text

Events

Slide 36

Slide 36 text

OnUpdate Event AbsenceEntity Dispatches

Slide 37

Slide 37 text

OnUpdate Event AbsenceEntity Dispatches

Slide 38

Slide 38 text

Absence Cancelled Event Cancel Absence Command Handler Dispatches

Slide 39

Slide 39 text

Absence Cancelled Event In Memory Listener Immediate Action Place In Messaging Queue Listens

Slide 40

Slide 40 text

Absence Cancelled Event Flush Listener Listens Absence Approved Event Domain Infrastructure Listens

Slide 41

Slide 41 text

Separating Commands From Queries

Slide 42

Slide 42 text

Command Command Handler Entity Datastore

Slide 43

Slide 43 text

Datastore View Datastore View Datastore Command Command Handler Entity Event

Slide 44

Slide 44 text

Datastore View Datastore View Datastore Command Command Handler Entity View Template Event

Slide 45

Slide 45 text

Separating Bundles Horizontally

Slide 46

Slide 46 text

Non-application Specific Code

Slide 47

Slide 47 text

HumanResources CustomLoggingBundle HumanResourcesBundle

Slide 48

Slide 48 text

HumanResourcesBundle HumanResources CustomLoggingBundle CustomLogging CustomLoggingBundle CustomLoggingBundle CustomLogging HumanResourcesBundle

Slide 49

Slide 49 text

HumanResources CustomLoggingBundle CustomLogging CustomLoggingBundle CustomLoggingBundle CustomLogging If it must! HumanResourcesBundle

Slide 50

Slide 50 text

HumanResources CustomLoggingBundle CustomLogging CustomLoggingBundle CustomLoggingBundle CustomLogging HumanResourcesBundle

Slide 51

Slide 51 text

Separating By Context

Slide 52

Slide 52 text

AbsencePlannerBundle AbsencePlanner CustomLoggingBundle CustomLogging CustomLoggingBundle RecruitmentBundle Recruitment

Slide 53

Slide 53 text

Message Queue/REST AbsencePlannerBundle AbsencePlanner CustomLoggingBundle CustomLogging CustomLoggingBundle RecruitmentBundle Recruitment

Slide 54

Slide 54 text

CustomLoggingBundle CustomLogging CustomLoggingBundle RecruitmentBundle Recruitment Off the shelf Package Message Queue/REST Message Queue/REST AbsencePlannerBundle AbsencePlanner

Slide 55

Slide 55 text

Separate Commonality

Slide 56

Slide 56 text

AbsencePlannerBundle AbsencePlanner RecruitmentBundle Recruitment AbsencePlannerBundle AbsencePlanner CustomLoggingBundle CustomLogging CustomLoggingBundle RecruitmentBundle Recruitment User Management

Slide 57

Slide 57 text

!= Staff Member Entity User Entity

Slide 58

Slide 58 text

AbsencePlannerBundle AbsencePlanner AbsencePlannerBundle AbsencePlanner CustomLoggingBundle CustomLogging CustomLoggingBundle RecruitmentBundle Recruitment UserManagementBundle

Slide 59

Slide 59 text

Now?

Slide 60

Slide 60 text

http://www.flickr.com/photos/mtsofan/8313606885

Slide 61

Slide 61 text

https://github.com/beberlei/litecqrs-php http://behat.org/

Slide 62

Slide 62 text

http://williamdurand.fr/ http://verraes.net/#blog http://www.whitewashing.de/

Slide 63

Slide 63 text

QUESTIONS?