an introduction to domain driven design in php

56
An Introduction to Domain Driven Design in PHP Chris Renner Nashville PHP Meetup August 9, 2016

Upload: chris-renner

Post on 16-Apr-2017

419 views

Category:

Software


3 download

TRANSCRIPT

Page 1: An Introduction to Domain Driven Design in PHP

An Introduction to Domain Driven Design

in PHPChris Renner

Nashville PHP MeetupAugust 9, 2016

Page 2: An Introduction to Domain Driven Design in PHP

Agenda• A bit about me & what I do

• Describe our principle application and its purpose

• High-level DDD concepts

• Implementation strategies and patterns

• Lessons learned

• Conclusion

Page 3: An Introduction to Domain Driven Design in PHP

About Me - Personal

• Married 17 years with two little ones (10 and 3)

• In Nashville 18 years, originally from Kentucky

• Interests: Too many!

Page 4: An Introduction to Domain Driven Design in PHP

The Renners

Page 5: An Introduction to Domain Driven Design in PHP

About Me - Professional

• Sr. Application Developer at VUMC, 12 years at Vanderbilt,~10 years as PHP dev

• Self-taught developer*

• internal-facing enterprise scale apps

• Prior: proposal writer, contract negotiator

Page 6: An Introduction to Domain Driven Design in PHP

What I do• Application Development

• User interaction & support

• Business Analysis

• Reporting and analytics

• Support one enterprise app, a few small apps and a couple of websites

Page 7: An Introduction to Domain Driven Design in PHP

Our Main App• PEER

• Went online July 2007

• Primary business application of a department of 30 users, with hundreds of other “customers”.

• Domain is “Contract Management”

Page 8: An Introduction to Domain Driven Design in PHP

What is DDD?

• A set of solutions to documenting, solving and managing the complexity of business problems in your code.

• A methodology for thinking and talking about solving business problems with code

Page 9: An Introduction to Domain Driven Design in PHP

DDD is not…• a TV show on Food Network

• anything to do with domain names or DNS

• code, but rather principles and practices.

• MVC or an MVC replacement.

• a design pattern.

• an all-or-nothing proposition.

Page 10: An Introduction to Domain Driven Design in PHP

DDD is…• a process

• modeling business logic in code

• a common language among devs and stakeholders

• agile*

Page 11: An Introduction to Domain Driven Design in PHP

When to use?• Complicated business logic

• Large code base

• Multiple devs

• Long dev cycle, app lifecycle

• moving paper/human processes into an electronic system

Page 12: An Introduction to Domain Driven Design in PHP

When NOT to use?

• Short development cycle

• Microservices

• Simple business models

• Minimal business logic

Page 13: An Introduction to Domain Driven Design in PHP

Requirements• General intelligence - must understand

client’s business process

• Communication skills - must be able to translate biz speak to tech speak and vice versa

• Humility

Page 14: An Introduction to Domain Driven Design in PHP

The Big Picture

Page 15: An Introduction to Domain Driven Design in PHP

Domain• A sphere of knowledge, influence or activity.

The subject area to which the user applies a program is the domain of the software

• e.g. Used Car Sales, Patient Medical Records, Contract Management*

• not Automotive, Health Care

Page 16: An Introduction to Domain Driven Design in PHP

Model

• A software abstraction representing a specific concept in the domain.

• Data & Biz Logic

• Will be continually refined as understanding of domain grows.

Page 17: An Introduction to Domain Driven Design in PHP

Ubiquitous Language

• Ubiquitous: omnipresent, everywhere

• Set of terms structured around the domain model and used by both tech and biz team members when discussing the project.

• Use in the code

Page 18: An Introduction to Domain Driven Design in PHP

Bounded Context

• Limits drawn around the scope of the business problem create a context area.

• Statements about a model can only be understood within this context.

Page 19: An Introduction to Domain Driven Design in PHP

“Tactical” DDD

Page 20: An Introduction to Domain Driven Design in PHP

Entities

• e.g. Car, Patient, Invoice, Contract

• Typically 1-class per entity

• Mimic real objects

• Data + Business Logic = Domain Models

Page 21: An Introduction to Domain Driven Design in PHP

class Widget {

public $id;

public $price;

public function __construct(){}

public function isDiscountable(){// logic here

}}

Page 22: An Introduction to Domain Driven Design in PHP

Factories

• Objects that create instances of other objects

• TIP: Pass in an ID to get back hydrated instance

Page 23: An Introduction to Domain Driven Design in PHP

class Widget{

public static function factory($id = null){// create instance$obj = new Widget();

// hydrate with data from persistenceif ($id) {WidgetMapper::hydrate($obj, $id);

}

return $obj;}

}

$foo = Widget::factory(1234);

Page 24: An Introduction to Domain Driven Design in PHP

Aggregates

• One-to-Many

• E.g. Entity “Invoice” may have multiple line items, each probably a LineItem Entity

• Roll up many like things into a parent

Page 25: An Introduction to Domain Driven Design in PHP

Domain Services• Use sparingly!

• Capture business logic that operates on more than one entity/model

• When a class isn’t a “thing”

• != application services

Page 26: An Introduction to Domain Driven Design in PHP

Domain Events

• Real actions, events or activities in the business

• Becomes your domain logic

• Place in model/entity or service layer

Page 27: An Introduction to Domain Driven Design in PHP

Modules• Separate code into meaningful subject areas

based on business logic

• One module for system/application support/architectural stuff, then modules for each business sub-area or bundle of related code

• Personal preference

Page 28: An Introduction to Domain Driven Design in PHP

Layers (Hexagonal Architecture)

• Separation of concerns

• Outer later is interface, either UI or service connections

• middle layer that translates requests into business actions

• inner layer is business logic

Page 29: An Introduction to Domain Driven Design in PHP

Patterns and Best Practices

Page 30: An Introduction to Domain Driven Design in PHP

Domain Models

• Implementation of Entity

• Use Inheritance and/or Traits & Interfaces to abstract and re-use

• Domain Model + Mapper + Table Data Gateway patterns

Page 31: An Introduction to Domain Driven Design in PHP

Domain

ModelMapper Table

• All SQL in Table class• Mapper translates between Model

properties and table column• Model has NO awareness of the Table class• Application code (controllers, services)

interact with the Model only

Page 32: An Introduction to Domain Driven Design in PHP

class Widget extends DomainModelAbstract{

public $id;public $name;public $price;protected $department;

public static function factory($id = null){

// create instance$obj = new Widget();

// hydrate with data from persistenceif ($id) {

WidgetMapper::hydrate($obj, $id);}

return $obj;}

}

Page 33: An Introduction to Domain Driven Design in PHP

class WidgetTable extends TableAbstract{

public $name = ‘WIDGET_TABLE’;public $primary = ‘ID’;

public function fetchById($id){

$sql = “SELECT * FROM $this->name WHERE $this->primary = :id”;

$result = $db->query($sql, [‘:id’ = > $id]);

return $result->fetch();}

}

Page 34: An Introduction to Domain Driven Design in PHP

class WidgetMapper extends MapperAbstract {

public static $columns =[‘id’ => ‘ID’,‘name’ => ‘NAME,‘price’ => ‘PRICE’

]

}

Page 35: An Introduction to Domain Driven Design in PHP

Interacting with a Domain Model Instance

$myWidget = Widget::factory();$myWidget->setName(‘Acme Super Thingy’);$myWidget->price = 99.95;$id = $myWidget->save();

echo $id; // 1234

Page 36: An Introduction to Domain Driven Design in PHP

Lazy Loading

class Widget{

public $deptId;

private $department;

public function getDept(){

if (!$this->department) {$this->department = Department::factory($this->deptId);

}

return $this->department;}

}

echo $widget->getDept()->name; // Human Resources

Page 37: An Introduction to Domain Driven Design in PHP

Getters and Setters

• Don’t Overuse!

• Opportunity to Add Logic

Page 38: An Introduction to Domain Driven Design in PHP

public function setName($string){$this->name = substr($string, 5, 100);

}

public function setStatus($status){if($status != $this->status) {$this->addtoStatusLog($status);}

$this->status = $status;}

Page 39: An Introduction to Domain Driven Design in PHP

Strategy Pattern

• aka “Policy Pattern”

• encapsulate business rules/logic

Page 40: An Introduction to Domain Driven Design in PHP

Strategy Pattern Example

class Contract{

public function isExpired(){

if(strtotime($this->endDate) < time()) {return true;

}

return false;}

}

$contract->setEndDate(‘2016-08-01’);echo $contract->isExpired(); // true

Page 41: An Introduction to Domain Driven Design in PHP

Specification Pattern• like Strategy, but a separate class instead of

a function

• single public function isSatisfiedBy() determines if an object meets specified criteria

• can be chained

Page 42: An Introduction to Domain Driven Design in PHP

Specification Pattern Exampleclass BillingAgreementSpecification{

public function isSatisfiedBy(Contract $contract){

if(!$contract->requirementA) {return false;

}

if(!$contract->requirementB) {return false;

}

return true;}

}

$spec = new BillingAgreementSpecification();echo $spec->isSatisfiedBy($contract); // true

Page 43: An Introduction to Domain Driven Design in PHP

Lessons Learned

Page 44: An Introduction to Domain Driven Design in PHP

Intention-Revealing Interface

• Contextually Relevant Variable, Function and Class Names

• public function sendFullyExecutedEmail()

Page 45: An Introduction to Domain Driven Design in PHP

Comment Your Code

• comment and docblock everything

Page 46: An Introduction to Domain Driven Design in PHP

IDs for Everything!

• usernames and emails are NOT unique IDs!

• give everything an internal numeric ID, even if its never seen by user

Page 47: An Introduction to Domain Driven Design in PHP

Minimize Shortcuts• Code it to work first, then go back and make

it right

• hack-y code will bite you later

• iterate + feedback, don’t assume you fully understand the problem - the Model will never be “done”

Page 48: An Introduction to Domain Driven Design in PHP

Avoid Framework Lock-In

• Preference for components

• Composer

• Consider extending a Micro-Framework v. an all-in-one package

Page 49: An Introduction to Domain Driven Design in PHP

Good OOP required

• Abstraction

• Encapsulation

• Separation of Concerns

Page 50: An Introduction to Domain Driven Design in PHP

Avoid Unnecessary Complexity

• Ask “is this necessary?”

• Don’t let DDD rules become a prison

• Simplicity = Maintainability

Page 51: An Introduction to Domain Driven Design in PHP

Become the Expert

• You will uncover flaws and inefficiencies in the business logic

• You may end up understanding the business process better than stakeholders

Page 52: An Introduction to Domain Driven Design in PHP

Summary• DDD a way of communicating and thinking

about a complex business problem

• Implementing DDD involves the best of enterprise design patterns, OOP and clean code principles.

• Use what works, every project is different

Page 53: An Introduction to Domain Driven Design in PHP

References• Domain Driven Design: Tackling Complexity in the Heart

of Software - Eric Evans, 2003

• DDD Reference - Eric Evans, https://www.domainlanguage.com/ddd/reference/

• Clean Code: A Handbook of Agile Software Craftsmanship - Robert Martin, 2008

• Patterns of Enterprise Application Architecture - Martin Fowler, 2002

• phproundtable: Domain Driven Design in PHP - https://www.phproundtable.com/episode/domain-driven-design-in-php

Page 54: An Introduction to Domain Driven Design in PHP

Find Me

• Twitter: @rennerchris

• Web: www.chrisrenner.com

• Email: [email protected]

Page 55: An Introduction to Domain Driven Design in PHP

I’m Troy McClure, and you might remember me from such tech talks as “Creating Legacy Code”

and “Maximizing Technical Debt”

Page 56: An Introduction to Domain Driven Design in PHP

Questions?