Download - Clean code & design patterns
![Page 1: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/1.jpg)
![Page 2: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/2.jpg)
Pascal Larocque
● TrustCharge Team● Behat guy● Testing guy● SOLID guy● Pattern guy● Father of 3● Star Wars Geek
@pascallarocque
![Page 3: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/3.jpg)
Bad Code● Singletons● Tight Coupling● Untestable● Premature Optimization● Indescriptive name● Duplication
![Page 4: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/4.jpg)
Cost of Bad Code
● Very hard / Impossible to estimate ● Slows down team velocity● High Learning curve● Brings down team moral● Increases cost of development
![Page 5: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/5.jpg)
The Primal Conundrum
Programmers face a conundrum of basic values. All developers with more than a few years experience know that previous messes slow them down. And yet all developers feel the pressure to make messes in order to meet deadlines. In short, they don’t take the time to go fast!
![Page 6: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/6.jpg)
True professionals know that the second part of the conundrum is wrong. You will not make the deadline by making the mess. Indeed, the mess will slow you down instantly, and will force you to miss the deadline. The only way to make the deadline—the only way to go fast—is to keep the code as clean as possible at all times.
![Page 7: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/7.jpg)
How do I write Clean Code?
![Page 8: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/8.jpg)
What is Clean Code?“Clean code can be read, and enhanced by a developer other than its original author. It has unit and acceptance tests. It has meaningful names. It provides one way rather than many ways for doing one thing. It has minimal dependencies, which are explicitly defined, and provides a clear and minimal API. Code should be literate since depending on the language, not all necessary information can be expressed clearly in code alone.”
- Dave Thomas
“Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions and straightforward lines of control.”
- Grady Booch
“I like my code to be elegant and efficient. The logic should be straightforward to make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and performance close to optimal so as not to tempt people to make the code messy with unprincipled optimizations. Clean code does one thing well.”
- Bjarne Stroustrup
You know you are working on clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.
- Ward Cunningham
![Page 9: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/9.jpg)
What is Clean Code?
![Page 10: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/10.jpg)
The Boy Scout Rule
“Leave the campground cleaner than you found it”
Code Rots and Degrades as time passes
The Code has to be kept clean over time. We must take an active role in preventing the degradation.
![Page 11: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/11.jpg)
Naming
● Use intention revealing names○ Why it exists○ What it does○ How it’s used
● Classes should have nouns or noun phrases○ Don’t use Manager, Processor, Data or Info
● Methods should have verbs or verb phrases● Accessor, Mutators or predicates should
have get, set or is● Use solution domain name
○ Factory, Visitor, Queue
![Page 12: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/12.jpg)
Functions
● Small● Smaller than that!!!● Does ONE THING● Does ONLY ONE THING● Blocks and Indentation
○ IF, While, For● One level of abstraction per function
○ getHTML()○ $parsed = Parser::render($url)○ $xml->append($node)
![Page 13: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/13.jpg)
Functions
● Reads like a Top Down Narrative○ To render the page we get all the content○ To get all the content we extract it from the DB○ To extract it from the DB we need to connect
![Page 14: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/14.jpg)
Function Arguments
The ideal number of arguments for a function is zero (niladic).Next comes one (monadic), followed closely by two (dyadic).Three arguments (triadic) should be avoided where possible.More than three (polyadic) requires very special justification—and then shouldn’t be used anyway.
![Page 15: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/15.jpg)
Function Arguments - Flags
Flag Arguments should be avoided.It does 1 thing if true and another thing when it’s false.render(true):
renderForScreen()
renderForTest()
![Page 16: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/16.jpg)
Function Argument - Objects
It’s easier to pass Objects instead of a long argument list or array
Rectangle makeRectangle(Double x1, Double y1, Double x2, Double y2)
Rectangle makeRectangle(Point point1, Point point2)
![Page 17: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/17.jpg)
checkPassword(username, password) { user = $this->dataAccessor->findByUsername(username) valid= md5($user->getPassword()) === password if(valid) { Session.init(user) } else { Session.clear() } return valid }
Have no side effect
Sides effects are lies.
BAD
![Page 18: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/18.jpg)
Enforce Temporal Couplingclass ACL { function login(username, password) { this->user = this->findUser(username, password) this->getPermissions() this->startACLSession() }}
BAD
class ACL { function login(username, password) { this->user = this->findUser(username, password) this->permissions = this->getPermissions($this->user) this->startACLSession(this->permissions) }}
BETTER
![Page 19: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/19.jpg)
if ($this->_sortBySet() === true) { ... } else if ($this->_sortByActor() === true) { ... } else if ($this->_sortByClip() === true) { ... } else { … }
Make Conditions clear if (true === $bySetId && (true === empty($photoCollection) || true === empty($photoSet))) { ... } else if (true === $byActorId && (true === empty($photoCollection) || true === empty($actor))) { ... } else if (true === $byClipId && (true === empty($photoCollection) || true === empty($scene))) { ... } else { … }
BAD
BETTER
![Page 20: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/20.jpg)
sortingAlgorithmInterface = phosetSortingFactory->findSorter(sortBy) sorted list = sortingAlgorithmInterface ->sort(photosetList)
Replace Conditions with Factory if ($this->_sortBySet() === true) { ... } else if ($this->_sortByActor() === true { ... } else if ($this->_sortByClip() === true) { ... } else { … }
POLYMORPHISM
GOODNESS
![Page 21: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/21.jpg)
Abstract Factory Pattern
![Page 22: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/22.jpg)
Encapsulate Change
Class UserRepository { function findById(id) { return Doctrine::getTable('Users')->createQuery(‘u’)
->where(‘u.id = ?’, id) ->fetchOne();
}}
ORM MY GOD
Class UserRepository { function findById(id) { userData = this->dataAccessor->findById(id) user = userFactory->create(userData) return user }}
The only constant is Change.
![Page 23: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/23.jpg)
Strategy Pattern
![Page 24: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/24.jpg)
The Law of Demeter
method f of a class C should only call the methods of these: ● C● An object created by f ● An object passed as an argument to f ● An object held in an instance variable of C
![Page 25: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/25.jpg)
Class ACL { protected user function hasAccessToAdmin() { return this->user ->isAdmin() }}
The Law of Demeter Class ACL { function hasAccessToAdmin() { return getUserManager() ->getUser(123) ->getProfile() ->isAdmin() }}
BAD
Class ACL { protected user protected aclVisitor function setVisitor(visitor) { … } function hasAccessToAdmin() { return this->aclVisitor ->isAdmin(this->user-getProfile()) }}
Class AclVisitor { function isAdmin(profile) { return profile->isadmin() }}
MEH
PATTERNS!!!
![Page 26: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/26.jpg)
Visitor Pattern
![Page 27: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/27.jpg)
Don’t pass NULL, Don’t return NULL
Throw an exception
Return a NullObjectfindUser(ID) { user = this->dataAccessor->findById(ID) if(user == null) { user = new NullUser(); } return user}
Class NullUser { function getName { return ‘’ //DO NOTHING }}
![Page 28: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/28.jpg)
NullObject Pattern
![Page 29: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/29.jpg)
Observer Pattern
![Page 30: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/30.jpg)
Singleton Pattern
![Page 31: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/31.jpg)
Singleton Pattern
"Singletons are the path of the dark side. Singletons lead to implicit dependencies. Implicit dependencies lead to global state. Global state leads to suffering."
![Page 32: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/32.jpg)
As events arrive from the outside world at a port, a technology-specific adapter converts it into a usable procedure call or message and passes it to the application.
CreditCardService
Hexagonal Architecture
CreditCardService
HTTP
REST
PHPUnit
SOCKETAD
APTE
R
![Page 33: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/33.jpg)
When the application has something to send out, it sends it out through a port to an adapter, which creates the appropriate signals needed by the receiving technology (human or automated).
CreditCardService
Hexagonal Architecture
CreditCardService
HTML
XML
PHPUnit
JSONPADAPTER
![Page 34: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/34.jpg)
Class CreditCardService __construct(InputInterface, OutputInterface) {
this->input = InputInterfacethis->output = OutputInterface
}function process() { input = this->input->getInput()
output = this->doProcessing(input)return this->ouput
->sendOutput(output)}
}CreditCardService
Hexagonal Architecture
CreditCardService
class CreditCardHTTPInputAdapter implements InputInterface{
function getInput() {..}}class CreditCardJSONPOutputAdapter implements OutputInterface{
function sendOutput(output) {..}}
![Page 35: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/35.jpg)
More stuff
Command Query SeparationFunctions should either do something or answer something, but not both.
DRYDon’t repeat yourself. Duplication may be the root of all evil in software.
SOLIDSingle Responsibility, Open/Closed Principle, Liskov substitution principle, Interface segregation, Dependency Inversion
Structured ProgrammingEvery function and every block has one Entry and one Exit
Use Exceptions and Error HandlingFunctions should do one thing. Error handling is one thing. Thus, a function that handles errors should do nothing else.
![Page 36: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/36.jpg)
SHARE KNOWLEDGEKNOWLEDGE DECAYS FAST
SLOW DOWN TO GO FAST
NEVER ASK PERMISSION TO DO YOUR JOB CORRECTLY
![Page 37: Clean code & design patterns](https://reader033.vdocuments.site/reader033/viewer/2022052523/556549b8d8b42a9b4c8b4c91/html5/thumbnails/37.jpg)
QUESTIONS?