AVOIDING THE MUDby Richard Millerhttp://www.flickr.com/photos/burge5000/22568539/
View Slide
@mr_r_millerhttp://www.richardmiller.co.uk
http://www.flickr.com/photos/brostad/8583990904
http://www.flickr.com/photos/dominik99/384027019
http://www.flickr.com/photos/jasmeet/2158002974
Bundles For Everything?http://www.flickr.com/photos/jarkel/2288176
Separate Domain Model FromBundleshttp://www.flickr.com/photos/[email protected]/3705814710
HumanResourcesBundle
HumanResourcesBundle HumanResources
http://www.flickr.com/photos/[email protected]/3040936355Enough?
Still Tightly Coupled
AbsenceEntityRequestAbsenceFormCancelAbsenceFormApproveAbsenceFormChangeAbsenceTypeForm
Sensio\HumanResources\Absence\AbsenceEntity:properties:reason:- NotBlank: { groups: [cancellation] }- Length: { max: 300, groups: [cancellation] }
AbsenceEntityRequestAbsenceFormCancelAbsenceFormApproveAbsenceFormChangeAbsenceTypeFormRequestAbsenceCommandCancelAbsenceCommandApproveAbsenceCommandChangeAbsenceTypeCommand
What About Templates?
AbsenceEntityupcoming.html.twigdetails.html.twigcalendar.html.twigunapproved.html.twig
{% if absence.endDate < date() %}past{% else %}absence.status{% endif %}getDisplayStatus()AbsenceEntitygetEndDate()getStatus()
{{ absence.displayStatus }}getDisplayStatus()AbsenceEntitygetEndDate()getStatus()getDisplayStatus()
AbsenceEntityRequestAbsenceFormCancelAbsenceFormApproveAbsenceFormChangeAbsenceTypeFormAbsenceViewupcoming.html.twigdetails.html.twigcalendar.html.twigunapproved.html.twig
AbsenceEntityRequestAbsenceFormCancelAbsenceFormApproveAbsenceFormChangeAbsenceTypeFormAbsenceViewupcoming.html.twigdetails.html.twigcalendar.html.twigunapproved.html.twiggetStatus()
UnapprovedAbsenceViewCalendarViewAbsenceEntityRequestAbsenceFormCancelAbsenceFormApproveAbsenceFormChangeAbsenceTypeFormUpcomingAbsencesViewAbsenceDetailsViewupcoming.html.twigdetails.html.twigcalendar.html.twigunapproved.html.twig
SRP
Behaviour Not State
RequestAbsenceControllerAbsenceEntitysetReason($reason)setStatus(AbsenceEntity::CANCELLED)setCancellationDate(new DateTime())CancelAbsenceCommandgetReason()
RequestAbsenceControllerAbsenceEntitycancel($reason)CancelAbsenceCommandgetReason()
CancelAbsenceCommandAbsenceEntityValidate internal consistencyValidate user input
CancelAbsenceCommandHandlerCancelAbsenceCommandHandlerAbsenceEntitycancel($reason)handle($command)RequestAbsenceControllerAbsenceEntitycancel($reason)CancelAbsenceCommand
Infrastructure?
AbsenceRepository(Interface)findById($id)findUpcomingByMember($member)findAllByMember($member)DoctrineORMAbsenceRepositoryDoctrineODMAbsenceRepositoryGuzzleClientAbsenceRepositoryInfrastructureDomain
AbsenceEntityAbsenceRepositoryDomain BundleServiceConfigInfrastructureDoctrineORMAbsenceRepositoryMappingConfig
AbsenceRepository(Interface)findById($id)findUpcomingByMember($member)findAllByMember($member)add(AbsenceEntity $absence)
Events
OnUpdateEventAbsenceEntity Dispatches
AbsenceCancelledEventCancelAbsenceCommandHandlerDispatches
AbsenceCancelledEventIn MemoryListenerImmediate Action Place In Messaging QueueListens
AbsenceCancelledEventFlushListenerListensAbsenceApprovedEventDomain InfrastructureListens
Separating Commands FromQueries
CommandCommandHandlerEntity Datastore
DatastoreViewDatastoreViewDatastoreCommandCommandHandlerEntityEvent
DatastoreViewDatastoreViewDatastoreCommandCommandHandlerEntityViewTemplateEvent
Separating Bundles Horizontally
Non-application Specific Code
HumanResourcesCustomLoggingBundleHumanResourcesBundle
HumanResourcesBundle HumanResourcesCustomLoggingBundle CustomLoggingCustomLoggingBundleCustomLoggingBundle CustomLoggingHumanResourcesBundle
HumanResourcesCustomLoggingBundle CustomLoggingCustomLoggingBundleCustomLoggingBundle CustomLoggingIf it must!HumanResourcesBundle
HumanResourcesCustomLoggingBundle CustomLoggingCustomLoggingBundleCustomLoggingBundle CustomLoggingHumanResourcesBundle
Separating By Context
AbsencePlannerBundle AbsencePlannerCustomLoggingBundle CustomLoggingCustomLoggingBundleRecruitmentBundle Recruitment
Message Queue/RESTAbsencePlannerBundle AbsencePlannerCustomLoggingBundle CustomLoggingCustomLoggingBundleRecruitmentBundle Recruitment
CustomLoggingBundle CustomLoggingCustomLoggingBundleRecruitmentBundle RecruitmentOff the shelf PackageMessage Queue/RESTMessage Queue/RESTAbsencePlannerBundle AbsencePlanner
Separate Commonality
AbsencePlannerBundle AbsencePlannerRecruitmentBundle RecruitmentAbsencePlannerBundle AbsencePlannerCustomLoggingBundle CustomLoggingCustomLoggingBundleRecruitmentBundle RecruitmentUser Management
!=StaffMemberEntityUserEntity
AbsencePlannerBundle AbsencePlannerAbsencePlannerBundle AbsencePlannerCustomLoggingBundle CustomLoggingCustomLoggingBundleRecruitmentBundle RecruitmentUserManagementBundle
Now?
http://www.flickr.com/photos/mtsofan/8313606885
https://github.com/beberlei/litecqrs-phphttp://behat.org/
http://williamdurand.fr/http://verraes.net/#bloghttp://www.whitewashing.de/
QUESTIONS?