Clean Code and Refactoring
Continuously improving the current code base
Refactoring
Process of changing the code to make it
easier to understand and cheaper to
modify but preserving its observable
behavior.
Programs must be written for
people to read,
and only incidentally for
machines to execute.
Abelson & Sussman
Keeping the code base
habitable
Habitable Code
Habitability enables programmers, coders, bug-fixers,
and people coming to the code later in its life to
understand its construction and intentions and to
change it comfortably and confidently.
Richard Gabriel
Clean Code
● Easy to understand (by all the team).
● Understandability makes changeability,
extensibility and maintainability possible.
Sustainability
Code Smells
Code structures that reflects problems on the code base.
Usually indicating design flaws.
A code smell can be an easy target to start improving the
code.
Code Smells
Duplicated code Switch statements
Long method Shotgun surgery
Large class Divergent Change
Long parameter list Comments (deodorant)
Primitive obsession Boolean parameter
Data clumps Message chains
Code Smells & Refactorings
There are refactorings techniques that might be used to remove a given
code smell.
Some examples:
● Switch Statements => Extract method, move method…
● Long parameter list => Introduce Parameter Object...
● Long Method => Extract method, Replace Temp with Query...
● Primitive obsession => Replace Data Value with Object...
Boy Scout Rule
“Leave this world a little better than you found it.”
Robert Baden-Powell
Code Smells & Design
It's not enough to detect that your code has code
smells (design problems).
You also need to know what good design is, to
know how to improve your code.
Rules of Simple Design
-
Beck Design Rules, Martin Fowler
Naming
● A good name is a good abstraction that helps the reader to
associate domain concepts.
● Choose names that express intention and make sense in the
domain.
● Beware of introducing alien concepts.
Naming Tips
● Pronounceable
● Explain what it does, not how
● Problem domain names
● Follow conventions
● Do not include numbers
● Do not include information for the compiler
SOLID
● Single Responsibility Principle (SRP)
● Open Closed Principle (OCP)
● Liskov Substitution Principle (LSP)
● Interface Segregation Principle (ISP)
● Dependency Inversion Principle (DIP)
SOLID
● Guidelines, not rules.
● Remember: flexibility is not free, it increases complexity.
● Much better if you get to them by refactoring when the
need is clear.
Single Responsibility Principle
Single Responsibility Principle
A module/function/object
should have
only one reason to change.
Single Responsibility Principle
● In this context a responsibility is a reason for change.
● Important to separate responsibilities because each
responsibility is an axis of change.
● If a module has more than one responsibility the
responsibilities become coupled
Single Responsibility Principle
● Depending on how the application is changing,
responsibilities should be separated or not.
● Wait for the need to appear.
● At a minimum identify responsibilities as private functions
that do only one thing.
Open/Closed Principle
Open/Closed Principle
Software entities should be
open for extension
but
closed for modification.
Open/Closed Principle
● A module using such abstractions can be closed for
modification, since it depends on an abstraction that is fixed.
Yet its behavior can be extended by creating new derivatives
of the abstraction.
● Separation of generic functionality from its implementation.
Open/Closed Principle
● Wait until the changes happen! Avoid needless complexity.
● Get to OCP by refactoring.
● Resist premature abstraction.
Liskov Substitution Principle
Liskov Substitution Principle
Subtypes must be
substitutable
for their base types.
Liskov Substitution Principle
● Software is really about behavior (responsibilities).
● Any implementation must respect the contract of the
abstraction.
● LSP allows a module, expressed in terms of an abstraction, to
comply with OCP.
Interface Segregation Principle
Interface Segregation Principle
Clients should not
be forced to depend
on methods
they do not use.
Interface Segregation Principle
● A non-cohesive interface contains different groups of
methods each serving different clients.
● Changes forced by one client on methods it uses will affect
other clients that do not use those methods.
● To avoid this separate clients should mean separate
interfaces.
● Non-cohesive interface increase the chances of violating LSP
Dependency Inversion Principle
Dependency Inversion Principle
a. High level modules should not depend upon low level modules. Both
should depend upon abstractions.
b. Abstractions should not depend upon details. Details should depend
upon abstractions.
Dependency Inversion Principle
● It makes the high level module independent of the details it
controls.
● Critically important for constructing code that is resilient to
change.
● The code will still be vulnerable to changes in interfaces.
Summary
Habitable Code
Code Smells
Refactorings
Test harness
Reduce fear
Translate knowledge to code