bgenius kennissessie_20120510

96
SOLID Software Design @jankeesvanandel @jwalgemoed @JPoint SOLID Software Design 1

Upload: bgenius

Post on 10-May-2015

356 views

Category:

Technology


0 download

DESCRIPTION

SOLID Software Design by jPoint.

TRANSCRIPT

Page 1: bGenius kennissessie_20120510

SOLID Software Design@jankeesvanandel

@jwalgemoed

@JPoint

SOLID Software Design 1

Page 2: bGenius kennissessie_20120510

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

Page 3: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 3

Page 4: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 4

Page 5: bGenius kennissessie_20120510

Goals

NOT our goal

SOLID Software Design 5

Page 6: bGenius kennissessie_20120510

Goals

Mastery takes lots of practice– You can’t learn to surf by reading a book– Neither programming

SOLID Software Design 6

Page 7: bGenius kennissessie_20120510

Goals

SOLID Software Design 7

“The 10.000 hour rule” – Malcolm Gladwell

Page 8: bGenius kennissessie_20120510

Goals

SOLID Software Design 8

• ShuHaRi– Shu: Traditional wisdom– Ha: Breaking with tradition– Ri: Transcendence

Page 9: bGenius kennissessie_20120510

Goals

After this session– you will NOT suddenly write better code

But…– you hopefully have some hooks to get better

SOLID Software Design 9

Page 10: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 10

Page 11: bGenius kennissessie_20120510

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());

Page 12: bGenius kennissessie_20120510

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) { //...

Page 13: bGenius kennissessie_20120510

Code quality

Is this code quality?

SOLID Software Design 13

Page 14: bGenius kennissessie_20120510

Code quality

Is this code quality?

SOLID Software Design 14

Page 15: bGenius kennissessie_20120510

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 {

Page 16: bGenius kennissessie_20120510

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 {

Page 17: bGenius kennissessie_20120510

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

Page 18: bGenius kennissessie_20120510

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

Page 19: bGenius kennissessie_20120510

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

Page 20: bGenius kennissessie_20120510

Code quality

Why dependency Management?– Because we don’t want code rot

SOLID Software Design 20

Page 21: bGenius kennissessie_20120510

Code quality

Why dependency Management?– Refactor sprint

SOLID Software Design 21

Page 22: bGenius kennissessie_20120510

Code quality

Why dependency Management?– Continuous refactoring

SOLID Software Design 22

Page 23: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 23

Page 24: bGenius kennissessie_20120510

SOLID

SOLID– First stated by Robert C. Martin in 1995– “The Ten Commandments of OO Programming”

SOLID Software Design 24

Page 25: bGenius kennissessie_20120510

SOLID

SOLID:– Later documented in “Agile Software

Development: Principles, Patterns and Practices”

SOLID Software Design 25

Page 26: bGenius kennissessie_20120510

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

Page 27: bGenius kennissessie_20120510

Single Responsibility Principle

“A class should have only one reason to change”– Theory– Simple example– Real world example– Considerations– Conclusion

SOLID Software Design 27

Page 28: bGenius kennissessie_20120510

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

Page 29: bGenius kennissessie_20120510

Single Responsibility Principle

SOLID Software Design 29

Page 30: bGenius kennissessie_20120510

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);}

Page 31: bGenius kennissessie_20120510

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

Page 32: bGenius kennissessie_20120510

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);}

Page 33: bGenius kennissessie_20120510

Single Responsibility Principle

Simple example– DatabaseConnection implementations handle

querying– DatabaseConnectionManager implementations

handle connections– We’ve managed to split two responsibilities

SOLID Software Design 33

Page 34: bGenius kennissessie_20120510

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

Page 35: bGenius kennissessie_20120510

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

Page 36: bGenius kennissessie_20120510

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

Page 37: bGenius kennissessie_20120510

Single Responsibility Principle

Question: Real world usages of SRP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers

SOLID Software Design 37

Page 38: bGenius kennissessie_20120510

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

Page 39: bGenius kennissessie_20120510

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

Page 40: bGenius kennissessie_20120510

Open-Closed Principle

SOLID Software Design 40

Page 41: bGenius kennissessie_20120510

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; }}

Page 42: bGenius kennissessie_20120510

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; }}

Page 43: bGenius kennissessie_20120510

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; }}

Page 44: bGenius kennissessie_20120510

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;}

Page 45: bGenius kennissessie_20120510

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

Page 46: bGenius kennissessie_20120510

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; } …}

Page 47: bGenius kennissessie_20120510

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; }}

Page 48: bGenius kennissessie_20120510

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

Page 49: bGenius kennissessie_20120510

Open-Closed Principle

Considerations

SOLID Software Design 49

Page 50: bGenius kennissessie_20120510

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

Page 51: bGenius kennissessie_20120510

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

Page 52: bGenius kennissessie_20120510

Open-Closed Principle

Question: Real world usages of OCP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers

SOLID Software Design 52

Page 53: bGenius kennissessie_20120510

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

Page 54: bGenius kennissessie_20120510

Liskov Substitution Principle

“Subtypes must be substitutable for their base types”– Theory– Simple example– Real world example– Considerations– Conclusion

SOLID Software Design 54

Page 55: bGenius kennissessie_20120510

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

Page 56: bGenius kennissessie_20120510

Liskov Substitution Principle

SOLID Software Design 56

Page 57: bGenius kennissessie_20120510

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

Page 58: bGenius kennissessie_20120510

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); }}

Page 59: bGenius kennissessie_20120510

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!

Page 60: bGenius kennissessie_20120510

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); }}

Page 61: bGenius kennissessie_20120510

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; }}

Page 62: bGenius kennissessie_20120510

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

Page 63: bGenius kennissessie_20120510

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

Page 64: bGenius kennissessie_20120510

Liskov Substitution Principle

Question: Real world usages of LSP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers

SOLID Software Design 64

Page 65: bGenius kennissessie_20120510

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

Page 66: bGenius kennissessie_20120510

Interface Segregation Principle

SOLID Software Design 66

Page 67: bGenius kennissessie_20120510

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 ;) }}

Page 68: bGenius kennissessie_20120510

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? }}

Page 69: bGenius kennissessie_20120510

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();}

Page 70: bGenius kennissessie_20120510

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() {}}

Page 71: bGenius kennissessie_20120510

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(); }}

Page 72: bGenius kennissessie_20120510

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

Page 73: bGenius kennissessie_20120510

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

Page 74: bGenius kennissessie_20120510

Interface Segregation Principle

Question: Real world usages of ISP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers

SOLID Software Design 74

Page 75: bGenius kennissessie_20120510

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

Page 76: bGenius kennissessie_20120510

Dependency Inversion Principle

SOLID Software Design 76

Page 77: bGenius kennissessie_20120510

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(); } }}

Page 78: bGenius kennissessie_20120510

Dependency Inversion Principle

Simple Example– HeatGauge implementation

SOLID Software Design 78

public class HeatGauge { public int actualTemperature() { // Do some measuring and return the results }}

Page 79: bGenius kennissessie_20120510

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(); } }}

Page 80: bGenius kennissessie_20120510

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 }}

Page 81: bGenius kennissessie_20120510

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(); } }}

Page 82: bGenius kennissessie_20120510

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(); } }}

Page 83: bGenius kennissessie_20120510

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

Page 84: bGenius kennissessie_20120510

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

Page 85: bGenius kennissessie_20120510

Dependency Inversion Principle

Question: Real world usages of DIP?– Examples in Java API– Examples in GoF Design Patterns– Big abusers

SOLID Software Design 85

Page 86: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 86

Page 87: bGenius kennissessie_20120510

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

Page 88: bGenius kennissessie_20120510

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

Page 89: bGenius kennissessie_20120510

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

Page 90: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 90

Page 91: bGenius kennissessie_20120510

Conclusion

Demo– Small web application to demo the ideas

SOLID Software Design 91

Page 92: bGenius kennissessie_20120510

Agenda

– Goals– Code quality– SOLID– Other principles– Demo– Conclusion– Q&A

SOLID Software Design 92

Page 93: bGenius kennissessie_20120510

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

Page 94: bGenius kennissessie_20120510

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

Page 95: bGenius kennissessie_20120510

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

Page 96: bGenius kennissessie_20120510

Q&A

Any questions left?

SOLID Software Design 96