www.luxoft.com
SOLID Design Principles
Ionuț Bilică
What is Software Design?
javac
Why Is Design Important?
$$$$$66666
$6
javac$
6
$$$$$66666
Martin Fowler’s Design Stamina Hypothesis
Attention to Design
Tim
e n
ee
de
d to
im
ple
me
nt u
se
r sto
ry
User Stories
good design
no design
The primary value of software is that it is soft.
That it is resilient in the face of inevitable change.
That it not only meets the users' requirements and solves their problems in the
present tense, but that it can be readily adapted to meet needs that will arrive
tomorrow, or the next day.
The Value of Code
The Code should do its job, solving a problem that the user has today.The secondary value of software:
SOLID
Single Responsibility Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Design Patterns vs Design Principles
cleancoders.com
Single Responsibility Principle
A class should have one, and only one, reason to change.
Open Closed Principle
You should be able to extend a classes behavior, without modifying it.
Common Closure Principle
Classes that change together are packaged together.
Single Responsibility Principle
A class should have one, and only one, reason to change.
Open Closed Principle
You should be able to extend a classes behavior, without modifying it.
Common Closure Principle
Classes that change together are packaged together.
Why does software changes?
A change is requested by the product owner through a user story.
A user story relates to a business capability of the software.
A user story is written in business language.
A change comes as a user story, for a business capability, and is written in
business language.
Single Responsibility Principle
A class should have one, and only one, reason to change.
Open Closed Principle
You should be able to extend a classes behavior, without modifying it.
Common Closure Principle
Classes that change together are packaged together.
Packaging
by type by function
Packaging
by type by function
non cohesive cohesive
Package cohesion
Single Responsibility Principle
private String assemblyDirections() {
String directions = "You can go";
for (Direction to : Direction.values()) {
if (canMoveTo(to)) {
directions += " " + to;
}
}
directions += " from here.";
return directions;
}
private List<Direction> getAvailableDirections() {
List<Direction> directions = new ArrayList<>();
for (Direction to : Direction.values()) {
if (canMoveTo(to)) {
directions.add(to);
}
}
return directions;
}
private String describe(Direction[] directions) {
String str = "You can go";
for (int i=0; i<directions.length; i++) {
str += " " + directions[i];
}
str += " from here.";
return directionsStr;
}
Single Responsibility Principlepublic class ResponseBuilder {
public Document buildReponseForAccept(int dealId) {
//Create service response for Accept request.
//...
}
public Document buildReponseForReject(int dealId, String reason) {
//Create service response for Reject request.
//...
}
public Document buildReponseForUpdate(int dealId, DealDiff diff) {
//Create service response for Update request.
//...
}
public Document buildResponseForWithdraw(int dealId) {
//Create service response for Update request.
//...
}
}
Single Responsibility Principlepublic class Configuration {
//...
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public boolean startInMaximizedWindow() {
return port;
}
public Color getMainThemeColor() {
return mainThrmeColor;
}
}
public static class ConnectionFactory {
private final String host;
private final int port;
@Injectpublic ConnectionFactory(@Config String host,
@Config int port) {this.host = host;this.port = port;
}
//...
}
Breaking the Single Responsibility Principle
Break unrelated code
Unrelated tests fail Unrelated functionality breaks
Blame is thrown around Clients panic and build mistrust
Open Closed Principlepublic void checkout(Receipt receipt) {
Money total = receipt.getTotal();
Payment p = acceptCash(total);
receipt.addPayment(p);
}
public void checkout(Receipt receipt,
PaymentMethodType paymentMethodType) {
Money total = receipt.getTotal();
Payment p = null;
if (paymentMethodType == CASH) {
p = acceptCash(total);
} else if (paymentMethodType == CREDIT) {
p = acceptCredit(total);
} else {
// There's no way to reached this. I hope.
}
receipt.addPayment(p);
}
public void checkout(Receipt receipt,
PaymentMethod paymentMethod) {
Money total = receipt.getTotal();
Payment p = paymentMethod.acceptPayment(total);
receipt.addPayment(p);
}
Open Closed Principle
public void handleRequest(Request request) {
switch (request.getType()) {
case ACCEPT:
handleAccept(request);
break;
case REJECT:
handleReject(request);
break;
case WITHDRAW:
handleWithdraw(request);
break;
default:
// Hope to never get here.
break;
}
}
public void handleRequest(Request request) {
for (RequestHandler handler : requestHandlers) {
if (handler.accept(request)) {
handler.handle(request);
}
}
}
Liskov Substitution Principle
Interface Segregation Principle
John API: writeCode, playFootball, drinkBeerInterface
Clients
John
Unsupported methodsMatthew
Unsupported methods Adrian Mutu
Services
Luxoft Team Leader Unneeded methods
Football team capitanUnneeded methods Unneeded methods
BuddyUnneeded methods
John API: writeCode, playFootball, drinkBeer
Interface Segregation Principle
John
Matthew
Adrian Mutu
Football team capitan
Luxoft Team Leader
Buddy
Interface
Clients
Services
FootballPlayerProgrammer BeerDrinker
Unsupported methods
Unsupported methods
Unneeded methods
Unneeded methods Unneeded methods
Unneeded methods
Dependency Inversion
Luxoft
Work Procedures
John MatthewAlex
Dependency Inversion
Luxoft
Work Procedures
John MatthewAlex
Programmer QA
Designing with principles - New Project
Never anticipate
Programmers are not the best at anticipating business needs.
Code written in anticipation of a business need is code unused, not tested in real life, getting in the way.
Anticipatory code create needless abstraction, needless complexity.
YAGN.
Act!
Change the design as soon as needed to respect the principles.
Getting to a design - Legacy Code
Do nothing because
Feeling not authorized or scared to change badly designed code.
The job is overwhelming: too much to understand, change and test.
Fix it all, now!
Take 3 months to make everything perfect.
1 extra month to test everything.
Make it 6 months.
Can’t be done.
The Boy Scouts Rule
When you need to touch existing code, leave it better than you found it.
Add 4 – 8 hours to the task estimate to clean the code and apply the design principles.
Coping with depression
Accept that most code is rotten.
Do not write code that rots easily.
When asking for refactoring time, use non-personal, well educated arguments.
Expect people to agree with you when discussing code quality.
Ignoring design principles affects the company but, most important, it also affects you.
Be the best programmer you can be, regardless of the circumstances.
Top Related