Post on 10-May-2015
description
SOLID Software Design@jankeesvanandel
@jwalgemoed
@JPoint
SOLID Software Design 1
About us
Jarno Walgemoed–Architect @JPoint–Fa-Med–Blinker–DJI
SOLID Software Design 2
Jan-Kees van Andel–Architect @JPoint–Rabobank–SNS Bank
–Apache MyFaces–Devoxx Steering
Develo
per
Develo
per
Developer
Developer
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 3
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 4
Goals
NOT our goal
SOLID Software Design 5
Goals
Mastery takes lots of practice– You can’t learn to surf by reading a book– Neither programming
SOLID Software Design 6
Goals
SOLID Software Design 7
“The 10.000 hour rule” – Malcolm Gladwell
Goals
SOLID Software Design 8
• ShuHaRi– Shu: Traditional wisdom– Ha: Breaking with tradition– Ri: Transcendence
Goals
After this session– you will NOT suddenly write better code
But…– you hopefully have some hooks to get better
SOLID Software Design 9
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 10
Code quality
Is this code quality?
SOLID Software Design 11
private static final String OID = "oId";private static final String TIME_INCIDENT = "timeOfIncident";private static final String EX_MSG = "exMsg";private static final String TECH_EX_MSG = "techExMsg";
...
mav.addObject(OID, oId == null ? "":oId);mav.addObject(TIME_INCIDENT, (new Date()).toString());mav.addObject(EX_MSG, e.getMessage() == null ? "":e.getMessage());mav.addObject(TECH_EX_MSG, e.toString());
Code quality
Is this code quality?
SOLID Software Design 12
@Controllerpublic class StartController {
@Autowired public StartController(SessionData sessionData, TransactionService txService, InitializerFactory initFactory, AuthorizationHandler authHandler, UIBinder uiBinder, StartValidator startValidator, WebApplicationContext ctx, RegistrationService regService) { //...
Code quality
Is this code quality?
SOLID Software Design 13
Code quality
Is this code quality?
SOLID Software Design 14
Code quality
Is this code quality?
SOLID Software Design 15
/** * This controller contains default Action and Render mappings, * used as fallback for handling invalid URL's. This prevents DOS * attacks, because a "no-handler-found“ Exception results in a * corrupt application state in WAS and can only be restored by * restarting the application. These handlers solve this problem. */@Controller@RequestMapping("VIEW")public class DefaultController {
Code quality
Is this code quality?
SOLID Software Design 16
/** * This controller contains default Action and Render mappings, * used as fallback for handling invalid URL's. This prevents DOS * attacks, because a "no-handler-found“ Exception results in a * corrupt application state in WAS and can only be restored by * restarting the application. These handlers solve this problem. */@Controller@RequestMapping("VIEW")public class WebSphereASDefaultHandlerController {
Code quality
Tonight, code quality means OO Design
– OOD is not free or easy, not even with Java/C#
– A lot of structured programming out there!
SOLID Software Design 17
Code quality
Tonight, code quality means SOLID principles
– Not about Object Oriented Modeling• (Person, User, Plane is-a Vehicle, etc)• Highlighting Nouns
– But about Dependency Management
SOLID Software Design 18
Code quality
Tonight, code quality means Dependency Mgt– Because• We DON’T want rigid code• We DON’T want changes to cause ripple effects• We DON’T want fragile code• We DO want easily unit testable code• We DO want reusable code• We DO want readable code
SOLID Software Design 19
Code quality
Why dependency Management?– Because we don’t want code rot
SOLID Software Design 20
Code quality
Why dependency Management?– Refactor sprint
SOLID Software Design 21
Code quality
Why dependency Management?– Continuous refactoring
SOLID Software Design 22
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 23
SOLID
SOLID– First stated by Robert C. Martin in 1995– “The Ten Commandments of OO Programming”
SOLID Software Design 24
SOLID
SOLID:– Later documented in “Agile Software
Development: Principles, Patterns and Practices”
SOLID Software Design 25
SOLID
Short for:– SRP: Single Responsibility Principle
–OCP: Open-Closed Principle
– LSP: Liskov Substitution Principle
– ISP: Interface Segregation Principle
–DIP: Dependency Inversion Principle
SOLID Software Design 26
Single Responsibility Principle
“A class should have only one reason to change”– Theory– Simple example– Real world example– Considerations– Conclusion
SOLID Software Design 27
Single Responsibility Principle
Theory– A Class Should Only Have One Reason To Change– Also referred to with the term Cohesion
(DeMarco, Page-Jones)– Separation of Concerns– Classes should have ONE well-defined
responsibility
SOLID Software Design 28
Single Responsibility Principle
SOLID Software Design 29
Single Responsibility Principle
Simple example– Database application interface specification
SOLID Software Design 30
public interface Database { public void connect(String url);
public void disconnect();
public ResultSet executeQuery(String query);}
Single Responsibility Principle
Simple example– What if the protocol changes?– What if the connection management changes?– What if we want to implement pooling or caching?
– We’ll need to change the database implementation in both cases
SOLID Software Design 31
Single Responsibility Principle
Simple example– How about this?
SOLID Software Design 32
public interface DatabaseConnection {
public ResultSet executeQuery(String query);}
public interface DatabaseConnectionManager {
public DatabaseConnection connect(String url);
public void disconnect(DatabaseConnection conn);}
Single Responsibility Principle
Simple example– DatabaseConnection implementations handle
querying– DatabaseConnectionManager implementations
handle connections– We’ve managed to split two responsibilities
SOLID Software Design 33
Single Responsibility Principle
Considerations– Should we split every class we create? No.– Will we end up with one-method classes? No.
SOLID Software Design 34
Single Responsibility Principle
Considerations– If the application doesn’t require changing either
of the coupled responsibilities at different times DON’T USE SRP
– Don’t apply SRP if there are no symptoms– Treat it as a guideline– Be consistent in what you call a “Responsibility”• Split on functionality, domain, architecture, layers and
do this in a consistent way
SOLID Software Design 35
Single Responsibility Principle
Conclusion– Simplest SOLID principle, hardest to get right– Be critical deciding whether or not an SRP
violation needs to be fixed– Stay pragmatic!– State management simplified by separating object
lifecycles
SOLID Software Design 36
Single Responsibility Principle
Question: Real world usages of SRP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers
SOLID Software Design 37
Open-Closed Principle
“Software entities should be open for extension, but closed for modification”– Theory– Simple example– Real world example– Considerations– Conclusion
SOLID Software Design 38
Open-Closed Principle
Theory– Helps preventing rigidity and cascading changes– Open for extension• Behaviour of a module can be extended
– Closed for modification• Extending does not result in a source change for a
module
SOLID Software Design 39
Open-Closed Principle
SOLID Software Design 40
Open-Closed Principle
Simple Example– We are using this Rectangle object
SOLID Software Design 41
public class Rectangle {
private int width; private int height;
public int getWidth() { return width; }
public int getHeight() { return height; }}
Open-Closed Principle
Simple Example– With this function we calculate area totals
SOLID Software Design 42
public class AreaCalculator {
public int calculateTotalArea(Rectangle [] rectangles) { int totalArea = 0; for(Rectangle rectangle : rectangles){ totalArea += rectangle.getWidth() * rectangle.getHeight(); } return totalArea; }}
Open-Closed Principle
Simple Example– Now we want to add a circle to the equation
SOLID Software Design 43
public class Circle { private int radius;
public int getRadius() { return radius; }}
Open-Closed Principle
Simple Example– What happens to the calculation?
SOLID Software Design 44
public double calculateTotalArea(Object [] objects) { double totalArea = 0; for(Object object : objects){ if(object instanceof Rectangle){ Rectangle rectangle = (Rectangle)object; totalArea += rectangle.getWidth() * rectangle.getHeight(); } if(object instanceof Circle){ Circle circle = (Circle)object; totalArea += circle.getRadius() * circle.getRadius() * Math.PI; } } return totalArea;}
Open-Closed Principle
Simple Example– This is poor design (of course)– The calculate method is not closed for
modification and not open for extension– Adding a Circle requires the developer to change
the calculation code!
SOLID Software Design 45
Open-Closed Principle
Simple Example– Introducing Shape and extending it
SOLID Software Design 46
public abstract class Shape { public abstract double getArea();}
public class Circle extends Shape { public double getArea() { return radius * radius * Math.pi; } …}
Open-Closed Principle
Simple Example– Simplifies AreaCalculator substantially– Allows future extension
SOLID Software Design 47
public class AreaCalculator {
public double calculateTotalArea(Shape[] shapes) { double totalArea = 0; for (Shape shape : shapes) { totalArea += shape.getArea(); } return totalArea; }}
Open-Closed Principle
Simple Example– The calculation is now Open for extension and
closed for modification– Adding another shape to the equation no longer
requires a change to the calculate implementation
SOLID Software Design 48
Open-Closed Principle
Considerations
SOLID Software Design 49
Open-Closed Principle
Considerations– Abstraction is key– So… should we just abstract everything? No.
– Abstract elements that require frequent change– Overuse of abstractions can create clutter– Avoid premature abstraction
SOLID Software Design 50
Open-Closed Principle
Conclusion– At the heart of Object Oriented design– Design using logical, useful abstractions– Add abstractions only when required– Expect having no changes in your code– Stimulate change (test, iterate)– Properly refactor code that’s affected by these changes
SOLID Software Design 51
Open-Closed Principle
Question: Real world usages of OCP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers
SOLID Software Design 52
Liskov Substitution Principle
“If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T”– Come again?
SOLID Software Design 53
Liskov Substitution Principle
“Subtypes must be substitutable for their base types”– Theory– Simple example– Real world example– Considerations– Conclusion
SOLID Software Design 54
Liskov Substitution Principle
Theory– Polymorphism problem
– A extends B• This means A IS-A B• …but is this always true for A and B?
SOLID Software Design 55
Liskov Substitution Principle
SOLID Software Design 56
Liskov Substitution Principle
Simple Example– Square extends Rectangle• Square IS-A Rectangle, right?
– Difference between Square and Rectangle• Rectangle can have different height and width settings• Square has equal values for both
SOLID Software Design 57
Liskov Substitution Principle
Simple Example– So, this is correct then?
SOLID Software Design 58
class Rectangle { private int width; private int height;
public Rectangle(int width, int height) { this.width = width; this.height = height; } // Setters left out for brevity}
class Square extends Rectangle { // Initialize as a square public Square(int size) { super(size, size); }}
Liskov Substitution Principle
Simple Example– Suppose we test the Square like this
– Our square suddenly is a 42 by 50 Rectangle!
SOLID Software Design 59
Square square = new Square(42);assertEquals(42, square.getWidth()); // Oksquare.setHeight(50);// Width should be the same as height, and we changed it!assertEquals(50, square.getWidth()); // Whoops!
Liskov Substitution Principle
Simple Example– Fixing is easy, but is this really the way to go?
SOLID Software Design 60
class Square extends Rectangle {
public void setWidth(int width) { super.setWidth(width); super.setHeight(width); }
public void setHeight(int height) { super.setHeight(height); super.setWidth(height); }}
Liskov Substitution Principle
Simple Example– Maybe better to do this
SOLID Software Design 61
class Square extends Shape { // Immutable private final int size;
public Square(int size) { this.size = size; }
@Override public int getHeight() { return size; }
@Override public int getWidth() { return size; }}
Liskov Substitution Principle
Considerations– The IS-A relationship not always applies in code• A square is a rectangle in the real world• A square is not a rectangle in code – contract breaks
when square doesn’t override rectangle behaviour
– Immutability can make a difference• public Rectangle(int width, int height);• public Square(int size);• If both are immutable, Rectangle really IS-A Square!
SOLID Software Design 62
Liskov Substitution Principle
Conclusion– Rule of thumb
• Instead of: A IS-A B, use: A is substitutable by B
– Inherit from a more abstract supertype if needed• Rectangle and Square could both inherit from Shape• Shape should enforce no rules for width and height
– Should you prevent LSP violations at all cost? No.• What if you only have a method that draws Rectangles• Will the LSP violation be a problem then?
SOLID Software Design 63
Liskov Substitution Principle
Question: Real world usages of LSP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers
SOLID Software Design 64
Interface Segregation Principle
“Clients should not be forced to depend on methods that they do not use”– Theory– Simple example– Real world example– Considerations– Conclusion
SOLID Software Design 65
Interface Segregation Principle
SOLID Software Design 66
Interface Segregation Principle
Simple Example– Interface definition for a worker doing work
– Implementation for a generic employee
SOLID Software Design 67
public interface Worker { public void work(); public void eat();}
public class Employee implements Worker { public void work() { // do work stuff } public void eat() { // eat lunch, keep up strength ;) }}
Interface Segregation Principle
Simple Example– Robots are also part of the business
– But they don’t eat lunch– Still, eat() has to be implemented
SOLID Software Design 68
public class Robot implements Worker { public void work() { // Work (without union breaks } public void eat() { // Wait, what? }}
Interface Segregation Principle
Simple Example– Split up the interfaces into sensible pieces
SOLID Software Design 69
public interface NutritionConsumer { public void eat();}
public interface Worker { public void work();}
Interface Segregation Principle
Simple Example– Implement the interfaces as needed
SOLID Software Design 70
public class Employee implements Worker, NutritionConsumer { public void work() { } public void eat() { }}
public class Robot implements Worker { public void work() {}}
Interface Segregation Principle
Simple Example– Class dealing with Worker objects
– Can deal with both robots and employees– Doesn’t need to be concerned with the nutritional
needs of the Employee type workers
SOLID Software Design 71
public class WorkloadManager { public void putWorkerToWork(Worker worker) { worker.work(); }}
Interface Segregation Principle
Considerations– Avoid coupling between interfaces and clients– Clients should only depend on methods they use– Separation reduces the risk of changes cascading
to implementing classes that do not have a need for those methods
SOLID Software Design 72
Interface Segregation Principle
Conclusion– Separate interfaces when it makes sense– Don’t overdo it!• Prevent classes having to implement many interfaces• Prevent one-method interfaces
– Common sense is key (again)• Split up interfaces as soon as clients show the need to
do so
SOLID Software Design 73
Interface Segregation Principle
Question: Real world usages of ISP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers
SOLID Software Design 74
Dependency Inversion Principle
“High-level modules should not depend on low-level modules directly, but through abstraction”“Abstractions should not depend on details, details should depend on abstractions”– Theory– Simple example– Real world example– Considerations– Conclusion
SOLID Software Design 75
Dependency Inversion Principle
SOLID Software Design 76
Dependency Inversion Principle
Simple Example– Application that monitors system status
SOLID Software Design 77
public class SystemStatus {
private HeatGauge gauge;
public void checkTemperature() throws OverheatingException { if(gauge.actualTemperature() > 55) { throw new OverheatingException(); } }}
Dependency Inversion Principle
Simple Example– HeatGauge implementation
SOLID Software Design 78
public class HeatGauge { public int actualTemperature() { // Do some measuring and return the results }}
Dependency Inversion Principle
Simple Example– Systemstatus directly depends on HeatGauge– Changes to HeatGauge can affect SystemStatus
SOLID Software Design 79
public class SystemStatus {
private HeatGauge gauge = new HeatGauge();
public void checkTemperature() throws OverheatingException { if(gauge.actualTemperature() > 55) { throw new OverheatingException(); } }}
Dependency Inversion Principle
Simple Example– Abstract away the dependency
SOLID Software Design 80
public interface HeatGauge { public int actualTemperature();}
public class HeatGaugeImpl implements HeatGauge { public int actualTemperature() { // Do some measuring }}
Dependency Inversion Principle
Simple Example– Use the new abstraction
– Better, but not perfect
SOLID Software Design 81
public class SystemStatus {
// Less dependent by using the interface private HeatGauge gauge = new GaugeImpl();
public void checkTemperature() throws OverheatingException { if(gauge.actualTemperature() > 55) { throw new OverheatingException(); } }}
Dependency Inversion Principle
Simple Example– Improving the example
– Abstracts away the implementation used to gauge the temperature
SOLID Software Design 82
public class SystemStatus { private HeatGauge heatGauge; public SystemStatus(HeatGauge heatGauge){ this.heatGauge = heatGauge; }
public void checkTemperature() throws OverheatingException { if(heatGauge.actualTemperature() > 55) { throw new OverheatingException(); } }}
Dependency Inversion Principle
Considerations– Clients should ‘own’ the interfaces used to access
low-level modules– Not the same as Dependency Injection (DI)• Dependency Inversion
– Using abstractions to achieve loose coupling– Ownership should be at client level
• Dependency Injection – Design pattern to implement loose coupling
SOLID Software Design 83
Dependency Inversion Principle
Conclusion– Maybe the most relevant of all SOLID principles– Allows robust code to be written using
abstractions– Dependency Inversion• Relevant when designing functionality
– Dependency Injection• Relevant when implementing functionality
– Do all classes need an interface? No.
SOLID Software Design 84
Dependency Inversion Principle
Question: Real world usages of DIP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers
SOLID Software Design 85
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 86
Other principles
Not SOLID, but just as important!– REP: Release reuse Equivalency Principle– CCD: Common Closure Principle– CRP: Common Reuse Principle– ADP: Acyclic Dependencies Principle– SDP: Stable Dependencies Principle– SAP: Stable Abstractions Principle– From the same book as SOLID
SOLID Software Design 87
Other principles
Not SOLID, but just as important!– REP: Release reuse Equivalency Principle– CCD: Common Closure Principle– CRP: Common Reuse Principle
– About package cohesion
SOLID Software Design 88
Other principles
Not SOLID, but just as important!– ADP: Acyclic Dependencies Principle– SDP: Stable Dependencies Principle– SAP: Stable Abstractions Principle
– About package coupling
SOLID Software Design 89
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 90
Conclusion
Demo– Small web application to demo the ideas
SOLID Software Design 91
Agenda
– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A
SOLID Software Design 92
Conclusion
Master the SOLID principles– Use it in your communications– Use it to challenge your design/yourself– Applicable to modules, libraries, components...
– But don’t be dogmatic about it– Don’t write SOLID, just because you can– Try to see the disadvantages too!– Don’t just believe the hype!
SOLID Software Design 93
Conclusion
SOLID principles are no hard rules– Definitely no hard rules!– Also no goals, just a means to an end
– There are more principles– Principle of least Knowledge– Premature optimization is the root of all evil– Composition over Inheritance– K.I.S.S. / Y.A.G.N.I.
SOLID Software Design 94
Conclusion
Don’t be dogmatic– Even Uncle Bob said this– http://blog.objectmentor.com/articles/2009/02/0
6/on-open-letter-to-joel-spolsky-and-jeff-atwood
– In response to– http://www.joelonsoftware.com/items/2009/01/3
1.html
SOLID Software Design 95
Q&A
Any questions left?
SOLID Software Design 96