beyond design patterns and principles - writing good oo code
TRANSCRIPT
![Page 1: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/1.jpg)
BEYOND DESIGN PATTERNS & PRINCIPLESWRITING GOOD OO CODE
Before?
Matthias Noback @matthiasnoback
![Page 2: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/2.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/3.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/4.jpg)
Single responsibility principle Open/closed principle Liskov substitution principle Interface segregation principle Dependency inversion principle
![Page 5: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/5.jpg)
EVERYTHING IS AN OBJECT
Alan Kay
![Page 6: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/6.jpg)
Strings
Integers Booleans
Floats
![Page 7: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/7.jpg)
![Page 8: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/8.jpg)
![Page 9: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/9.jpg)
Domain concepts
Use cases
Infra-stuff
![Page 10: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/10.jpg)
Objects introduce meaning
![Page 11: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/11.jpg)
Strings
Email addresses
![Page 12: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/12.jpg)
OBJECTS ENCAPSULATE STATE AND BEHAVIOR
enclose
![Page 13: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/13.jpg)
a = … b = …
![Page 14: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/14.jpg)
behaviorA() behaviorB()
![Page 15: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/15.jpg)
Behavior
State
Primitive values
Services
Entities
Value objects
Anemic domain objects
![Page 16: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/16.jpg)
Find a balance
![Page 17: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/17.jpg)
SERVICES SHOULD BE MODELLED AS FUNCTIONS
![Page 18: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/18.jpg)
behaviorA() behaviorB() somewhatUnrelated()
!!!
![Page 19: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/19.jpg)
somewhatUnrelated()
behaviorA() behaviorB()Because: SRP
![Page 20: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/20.jpg)
behaviorA()
behaviorB()
![Page 21: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/21.jpg)
behaviorB()
Because: ISP
behaviorA()
![Page 22: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/22.jpg)
Single-method classes ~=
Functions
![Page 24: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/24.jpg)
Functions
Naturally stateless
![Page 25: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/25.jpg)
class TheClass{ public doSomething(...) { check pre-conditions happy path handle failure check post-conditions }}
![Page 26: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/26.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/27.jpg)
OBJECTS SHOULD BE EXPLICIT ABOUT SIDE-EFFECTS
![Page 28: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/28.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/29.jpg)
function registerUser(name, repository, logger){ repository.add(new User(name)); logger.log(“New user added”);}
![Page 30: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/30.jpg)
logger
log()
repository
add()
![Page 31: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/31.jpg)
add()
log()
RegisterUser
![Page 32: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/32.jpg)
INJECTED SERVICES SHOULD BE SINGLE-METHOD OBJECTS TOO
![Page 33: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/33.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/34.jpg)
No service locators
serviceLocator.get(‘service id’).method()
Inject this object instead!
![Page 35: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/35.jpg)
No train wrecks
someService.getOtherService.doSomething()
Inject this
object instead!
![Page 36: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/36.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/37.jpg)
OBJECTS SHOULD ONLY EXIST IN A VALID STATE
condition
![Page 38: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/38.jpg)
?
![Page 39: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/39.jpg)
construct()
Something is not right!!!?
![Page 40: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/40.jpg)
behaviorB() First call behaviorA()!!!?
![Page 41: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/41.jpg)
canCallBehaviorB()
behaviorB()
Yes
Tell, don’t askAnemic domain
model
?
![Page 42: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/42.jpg)
YesValidatorisValid( )
![Page 43: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/43.jpg)
How to prevent this?
?
![Page 44: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/44.jpg)
What about…
changeState( , , )?
![Page 45: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/45.jpg)
ONLY VALID VALUES SHOULD CROSS OBJECT BOUNDARIES
![Page 46: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/46.jpg)
Crossing boundaries
Arguments Return values, Exceptions
![Page 47: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/47.jpg)
changeState(...) { check pre-conditions ... check post-conditions}
![Page 48: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/48.jpg)
changeState()doSomething()
getSomething()
construct()
![Page 49: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/49.jpg)
Advantages of always-valid objects
Easy to debug
Easy to refactor
Easy to reason about
![Page 50: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/50.jpg)
ALMOST ALL OBJECTS SHOULD BE IMMUTABLE
unable to be changed
![Page 51: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/51.jpg)
![Page 52: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/52.jpg)
changeState( )
![Page 53: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/53.jpg)
??????
!!!!!!!
![Page 54: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/54.jpg)
changeState( )
![Page 55: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/55.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/56.jpg)
Easier to reason about
![Page 57: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/57.jpg)
OBJECTS SHOULD COMMUNICATE USING WELL-DEFINED MESSAGES
“Alan Kay”
![Page 58: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/58.jpg)
![Page 59: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/59.jpg)
call( )
![Page 60: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/60.jpg)
Calling methods ==
Sending messages
Receiving return values ==
Receiving messages
Catching exceptions ==
Receiving messages
![Page 61: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/61.jpg)
Command
Query Document
![Page 62: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/62.jpg)
Command
Query Document
![Page 63: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/63.jpg)
public void doSomething(...) { ...}
public [return-type] getSomething(...) { return ...}
![Page 64: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/64.jpg)
CQS: command-query separation
Asking for information doesn’t change observable state
![Page 65: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/65.jpg)
EVERYTHING IS AN OBJECT
![Page 66: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/66.jpg)
YOUR APPLICATION TOO!Sort of…
![Page 67: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/67.jpg)
“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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/68.jpg)
a = … b = …
behaviorA() behaviorB()
![Page 69: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/69.jpg)
a = … b = …
behaviorA() behaviorB()
![Page 70: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/70.jpg)
![Page 71: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/71.jpg)
State should always be valid
Command
Command
Command
![Page 72: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/72.jpg)
Apply CQS
Command
Query
![Page 73: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/73.jpg)
Prefer immutability
Query
Document
![Page 74: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/74.jpg)
This design emerges
![Page 75: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/75.jpg)
Your application has side-effects
Filesystem
Keyboard
Screen
Network
![Page 76: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/76.jpg)
Apply hexagonal architecture
![Page 77: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/77.jpg)
IN WHICH WAYS IS YOUR APPLICATION NOT AN OBJECT?
![Page 78: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/78.jpg)
![Page 79: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/79.jpg)
![Page 80: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/80.jpg)
![Page 81: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/81.jpg)
???
![Page 82: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/82.jpg)
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 - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/83.jpg)
Also…
Try Event Sourcing
![Page 84: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/84.jpg)
CONCLUSION
![Page 85: Beyond design patterns and principles - writing good OO code](https://reader030.vdocuments.mx/reader030/viewer/2022012917/589a162e1a28ab2a678b4a69/html5/thumbnails/85.jpg)
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