+ All Categories
Home > Software > Beyond Design Patterns and Principles - PHPBenelux 2017

Beyond Design Patterns and Principles - PHPBenelux 2017

Date post: 08-Feb-2017
Category:
Upload: matthiasnoback
View: 382 times
Download: 2 times
Share this document with a friend
86
BEYOND DESIGN PATTERNS & PRINCIPLES WRITING GOOD OO CODE Before? Matthias Noback @matthiasnoback
Transcript
Page 1: Beyond Design Patterns and Principles - PHPBenelux 2017

BEYOND DESIGN PATTERNS & PRINCIPLESWRITING GOOD OO CODE

Before?

Matthias Noback @matthiasnoback

Page 2: Beyond Design Patterns and Principles - PHPBenelux 2017

My goals

To give you some vocabulary for code discussions and reviews

To bring back our focus to the basic ideas behind OOP

Page 3: Beyond Design Patterns and Principles - PHPBenelux 2017

Abstract factory

Builder

Factory method

Singleton

Adapter

Bridge

Composite

Facade

Proxy

Chain of responsibility

Command

Mediator

Strategy

Observer

Page 4: Beyond Design Patterns and Principles - PHPBenelux 2017

Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation principle Dependency inversion principle

Page 5: Beyond Design Patterns and Principles - PHPBenelux 2017

EVERYTHING IS AN OBJECT

Alan Kay

Page 6: Beyond Design Patterns and Principles - PHPBenelux 2017

Strings

Integers Booleans

Floats

Page 7: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 8: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 9: Beyond Design Patterns and Principles - PHPBenelux 2017

Domain concepts

Use cases

Infra-stuff

Page 10: Beyond Design Patterns and Principles - PHPBenelux 2017

Objects introduce meaning

Page 11: Beyond Design Patterns and Principles - PHPBenelux 2017

Strings

Email addresses

Page 12: Beyond Design Patterns and Principles - PHPBenelux 2017

OBJECTS ENCAPSULATE STATE AND BEHAVIOR

enclose

Page 13: Beyond Design Patterns and Principles - PHPBenelux 2017

a = … b = …

Page 14: Beyond Design Patterns and Principles - PHPBenelux 2017

behaviorA() behaviorB()

Page 15: Beyond Design Patterns and Principles - PHPBenelux 2017

Behavior

State

Primitive values

Services

Entities

Value objects

Anemic domain objects

Page 16: Beyond Design Patterns and Principles - PHPBenelux 2017

Find a balance

Page 17: Beyond Design Patterns and Principles - PHPBenelux 2017

SERVICES SHOULD BE MODELLED AS FUNCTIONS

Page 18: Beyond Design Patterns and Principles - PHPBenelux 2017

behaviorA() behaviorB() somewhatUnrelated()

!!!

Page 19: Beyond Design Patterns and Principles - PHPBenelux 2017

somewhatUnrelated()

behaviorA() behaviorB()Because: SRP

Page 20: Beyond Design Patterns and Principles - PHPBenelux 2017

behaviorA()

behaviorB()

Page 21: Beyond Design Patterns and Principles - PHPBenelux 2017

behaviorB()

Because: ISP

behaviorA()

Page 22: Beyond Design Patterns and Principles - PHPBenelux 2017

Single-method classes ~=

Functions

Page 24: Beyond Design Patterns and Principles - PHPBenelux 2017

Functions

Naturally stateless

Page 25: Beyond Design Patterns and Principles - PHPBenelux 2017

class TheClass{ public doSomething(...) { check pre-conditions happy path handle failure check post-conditions }}

Page 26: Beyond Design Patterns and Principles - PHPBenelux 2017

Simpler design, easier to test

The unit is smaller

Small number of possible execution paths

No unexpected changes in behavior

Page 27: Beyond Design Patterns and Principles - PHPBenelux 2017

OBJECTS SHOULD BE EXPLICIT ABOUT SIDE-EFFECTS

Page 28: Beyond Design Patterns and Principles - PHPBenelux 2017

class RegisterUser{ private repository private logger

public void register(name) { repository.add(new User(name)); logger.log(“New user added”); }}

Side effects!

Page 29: Beyond Design Patterns and Principles - PHPBenelux 2017

function registerUser(name, repository, logger){ repository.add(new User(name)); logger.log(“New user added”);}

Page 30: Beyond Design Patterns and Principles - PHPBenelux 2017

logger

log()

repository

add()

Page 31: Beyond Design Patterns and Principles - PHPBenelux 2017

add()

log()

RegisterUser

Page 32: Beyond Design Patterns and Principles - PHPBenelux 2017

INJECTED SERVICES SHOULD BE SINGLE-METHOD OBJECTS TOO

Page 33: Beyond Design Patterns and Principles - PHPBenelux 2017

function registerUserFactory(repository, logger) { return function(name) { repository.add(new User(name)); logger.log(“New user added”); }}

registerUser = registerUserFactory( repository, logger);

registerUser(“Matthias”);

Page 34: Beyond Design Patterns and Principles - PHPBenelux 2017

No service locators

serviceLocator.get(‘service id’).method()

Inject this object instead!

Page 35: Beyond Design Patterns and Principles - PHPBenelux 2017

No train wrecks

someService.getOtherService.doSomething()

Inject this

object instead!

Page 36: Beyond Design Patterns and Principles - PHPBenelux 2017

Inject only single-method services

Side-effects will be explicit

Responsibilities will be more explicit

Dependencies will be easier to mock

Page 37: Beyond Design Patterns and Principles - PHPBenelux 2017

OBJECTS SHOULD ONLY EXIST IN A VALID STATE

condition

Page 38: Beyond Design Patterns and Principles - PHPBenelux 2017

?

Page 39: Beyond Design Patterns and Principles - PHPBenelux 2017

construct()

Something is not right!!!?

Page 40: Beyond Design Patterns and Principles - PHPBenelux 2017

behaviorB() First call behaviorA()!!!?

Page 41: Beyond Design Patterns and Principles - PHPBenelux 2017

canCallBehaviorB()

behaviorB()

Yes

Tell, don’t askAnemic domain

model

?

Page 42: Beyond Design Patterns and Principles - PHPBenelux 2017

YesValidatorisValid( )

Page 43: Beyond Design Patterns and Principles - PHPBenelux 2017

How to prevent this?

?

Page 44: Beyond Design Patterns and Principles - PHPBenelux 2017

What about…

changeState( , , )?

Page 45: Beyond Design Patterns and Principles - PHPBenelux 2017

ONLY VALID VALUES SHOULD CROSS OBJECT BOUNDARIES

Page 46: Beyond Design Patterns and Principles - PHPBenelux 2017

Crossing boundaries

Arguments Return values, Exceptions

Page 47: Beyond Design Patterns and Principles - PHPBenelux 2017

changeState(...) { check pre-conditions ... check post-conditions}

Page 48: Beyond Design Patterns and Principles - PHPBenelux 2017

changeState()doSomething()

getSomething()

construct()

Page 49: Beyond Design Patterns and Principles - PHPBenelux 2017

Advantages of always-valid objects

Easy to debug

Easy to refactor

Easy to reason about

Page 50: Beyond Design Patterns and Principles - PHPBenelux 2017

ALMOST ALL OBJECTS SHOULD BE IMMUTABLE

unable to be changed

Page 51: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 52: Beyond Design Patterns and Principles - PHPBenelux 2017

changeState( )

Page 53: Beyond Design Patterns and Principles - PHPBenelux 2017

??????

!!!!!!!

Page 54: Beyond Design Patterns and Principles - PHPBenelux 2017

changeState( )

Page 55: Beyond Design Patterns and Principles - PHPBenelux 2017

Advantages of immutability

Clear distinction between using state and changing state

Pass on objects without worrying

Use objects without worrying

Page 56: Beyond Design Patterns and Principles - PHPBenelux 2017

Easier to reason about

Page 57: Beyond Design Patterns and Principles - PHPBenelux 2017

OBJECTS SHOULD COMMUNICATE USING WELL-DEFINED MESSAGES

“Alan Kay”

Page 58: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 59: Beyond Design Patterns and Principles - PHPBenelux 2017

call( )

Page 60: Beyond Design Patterns and Principles - PHPBenelux 2017

Calling methods ==

Sending messages

Receiving return values ==

Receiving messages

Catching exceptions ==

Receiving messages

Page 61: Beyond Design Patterns and Principles - PHPBenelux 2017

Command

Query Document

Page 62: Beyond Design Patterns and Principles - PHPBenelux 2017

Command

Query Document

Page 63: Beyond Design Patterns and Principles - PHPBenelux 2017

public void doSomething(...) { ...}

public [return-type] getSomething(...) { return ...}

Page 64: Beyond Design Patterns and Principles - PHPBenelux 2017

CQS: command-query separation

Asking for information doesn’t change observable state

Page 65: Beyond Design Patterns and Principles - PHPBenelux 2017

EVERYTHING IS AN OBJECT

Page 66: Beyond Design Patterns and Principles - PHPBenelux 2017

YOUR APPLICATION TOO!Sort of…

Page 67: Beyond Design Patterns and Principles - PHPBenelux 2017

“I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages […]”

Alan Kay

Page 68: Beyond Design Patterns and Principles - PHPBenelux 2017

a = … b = …

behaviorA() behaviorB()

Page 69: Beyond Design Patterns and Principles - PHPBenelux 2017

a = … b = …

behaviorA() behaviorB()

Page 70: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 71: Beyond Design Patterns and Principles - PHPBenelux 2017

State should always be valid

Command

Command

Command

Page 72: Beyond Design Patterns and Principles - PHPBenelux 2017

Apply CQS

Command

Query

Page 73: Beyond Design Patterns and Principles - PHPBenelux 2017

Prefer immutability

Query

Document

Page 74: Beyond Design Patterns and Principles - PHPBenelux 2017

This design emerges

Page 75: Beyond Design Patterns and Principles - PHPBenelux 2017

Your application has side-effects

Filesystem

Keyboard

Screen

Network

Page 76: Beyond Design Patterns and Principles - PHPBenelux 2017

Apply hexagonal architecture

Page 77: Beyond Design Patterns and Principles - PHPBenelux 2017

IN WHICH WAYS IS YOUR APPLICATION NOT AN OBJECT?

Page 78: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 79: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 80: Beyond Design Patterns and Principles - PHPBenelux 2017
Page 81: Beyond Design Patterns and Principles - PHPBenelux 2017

???

Page 82: Beyond Design Patterns and Principles - PHPBenelux 2017

Some suggestions

Write the serialization code yourself

The object’s design always comes first

Don’t let tools mess with object encapsulation

Page 83: Beyond Design Patterns and Principles - PHPBenelux 2017

Also…

Try Event Sourcing

Page 84: Beyond Design Patterns and Principles - PHPBenelux 2017

CONCLUSION

Page 85: Beyond Design Patterns and Principles - PHPBenelux 2017

EVERYTHING IS AN OBJECTOBJECTS ENCAPSULATE STATE AND BEHAVIOR

SERVICES SHOULD BE MODELLED AS FUNCTIONSOBJECTS SHOULD BE EXPLICIT ABOUT SIDE-EFFECTS

ALMOST ALL OBJECTS SHOULD BE IMMUTABLE

TREAT YOUR APPLICATION AS AN OBJECT(AND VICE VERSA)

ONLY VALID VALUES SHOULD CROSS OBJECT BOUNDARIESOBJECTS SHOULD ONLY EXIST IN A VALID STATE

OBJECTS SHOULD COMMUNICATE USING WELL-DEFINED MESSAGES

Page 86: Beyond Design Patterns and Principles - PHPBenelux 2017

CQRS & event sourcing in the wild Michiel Rook

Extremely defensive PHP Marco Pivetta

The true value of objects Stijn Vannieuwenhuyse

Kafka will get the message across, guaranteed

David Zuelke


Recommended