SOLID Software Design
    @jankeesvanandel
     @jwalgemoed

        @JPoint


       SOLID Software Design   1
About us

Jarno Walgemoed                 Jan-Kees van Andel
–Architect @JPoint              –Architect @JPoint
–Fa-Med
               r                –Rabobank




                                               r
            pe




                                              pe
–Blinker                        –SNS Bank
          lo
       ve
–DJI




                                             elo
   D e                          –Apache MyFaces



                                    v
                                –Devoxx Steering
                                 De
                     SOLID Software Design           2
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




  “The 10.000 hour rule” – Malcolm Gladwell

                  SOLID Software Design       7
Goals




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

                     SOLID Software Design   8
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?
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());




                                SOLID Software Design                   11
Code quality

Is this code quality?
@Controller
public class StartController {

   @Autowired
   public StartController(SessionData sessionData,
                          TransactionService txService,
                          InitializerFactory initFactory,
                          AuthorizationHandler authHandler,
                          UIBinder uiBinder,
                          StartValidator startValidator,
                          WebApplicationContext ctx,
                          RegistrationService regService) {
       //...




                          SOLID Software Design               12
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?
/**
 * 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 {




                          SOLID Software Design                15
Code quality

Is this code quality?
/**
 * 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 {




                          SOLID Software Design                16
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
public interface Database {

    public void connect(String url);

    public void disconnect();

    public ResultSet executeQuery(String query);
}




                              SOLID Software Design   30
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?
public interface DatabaseConnection {

    public ResultSet executeQuery(String query);
}

public interface DatabaseConnectionManager {

    public DatabaseConnection connect(String url);

    public void disconnect(DatabaseConnection conn);
}




                           SOLID Software Design       32
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
public class Rectangle {

    private int width; private int height;

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
}



                              SOLID Software Design   41
Open-Closed Principle

Simple Example
    – With this function we calculate area totals
public class AreaCalculator {

    public int calculateTotalArea(Rectangle [] rectangles) {
        int totalArea = 0;
        for(Rectangle rectangle : rectangles){
            totalArea +=
                 rectangle.getWidth() * rectangle.getHeight();
        }
        return totalArea;
    }
}




                           SOLID Software Design                 42
Open-Closed Principle

Simple Example
    – Now we want to add a circle to the equation
public class Circle {
    private int radius;

    public int getRadius() {
        return radius;
    }
}




                           SOLID Software Design    43
Open-Closed Principle

Simple Example
    – What happens to the calculation?
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;
}




                               SOLID Software Design                     44
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
public abstract class Shape {
    public abstract double getArea();
}

public class Circle extends Shape {
    public double getArea() {
        return radius * radius * Math.pi;
    }
    …
}




                           SOLID Software Design   46
Open-Closed Principle

Simple Example
    – Simplifies AreaCalculator substantially
    – Allows future extension
public class AreaCalculator {

    public double calculateTotalArea(Shape[] shapes) {
        double totalArea = 0;
        for (Shape shape : shapes) {
            totalArea += shape.getArea();
        }
        return totalArea;
    }
}




                           SOLID Software Design         47
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?
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);
    }
}



                              SOLID Software Design   58
Liskov Substitution Principle

Simple Example
   – Suppose we test the Square like this
Square square = new Square(42);
assertEquals(42, square.getWidth()); // Ok
square.setHeight(50);
// Width should be the same as height, and we changed it!
assertEquals(50, square.getWidth()); // Whoops!


   – Our square suddenly is a 42 by 50 Rectangle!




                           SOLID Software Design            59
Liskov Substitution Principle

Simple Example
    – Fixing is easy, but is this really the way to go?
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);
    }
}




                          SOLID Software Design           60
Liskov Substitution Principle

Simple Example
    – Maybe better to do this
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;
    }
}


                                SOLID Software Design   61
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
public interface Worker {
    public void work();
    public void eat();
}


   – Implementation for a generic employee
public class Employee implements Worker {
    public void work() { // do work stuff }
    public void eat() { // eat lunch, keep up strength ;) }
}




                                SOLID Software Design         67
Interface Segregation Principle

Simple Example
   – Robots are also part of the business
public class Robot implements Worker {
    public void work() { // Work (without union breaks }
    public void eat() { // Wait, what? }
}


   – But they don’t eat lunch
   – Still, eat() has to be implemented




                                SOLID Software Design      68
Interface Segregation Principle

Simple Example
   – Split up the interfaces into sensible pieces
public interface NutritionConsumer {
    public void eat();
}

public interface Worker {
    public void work();
}




                                SOLID Software Design   69
Interface Segregation Principle

Simple Example
   – Implement the interfaces as needed
public class Employee implements Worker, NutritionConsumer {
    public void work() { }
    public void eat() { }
}

public class Robot implements Worker {
    public void work() {}
}




                                SOLID Software Design          70
Interface Segregation Principle

Simple Example
   – Class dealing with Worker objects
public class WorkloadManager {
    public void putWorkerToWork(Worker worker) {
        worker.work();
    }
}



   – 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
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
public class SystemStatus {

    private HeatGauge gauge;

    public void checkTemperature() throws OverheatingException {
        if(gauge.actualTemperature() > 55) {
            throw new OverheatingException();
        }
    }
}




                                SOLID Software Design              77
Dependency Inversion Principle

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




                                SOLID Software Design   78
Dependency Inversion Principle

Simple Example
    – Systemstatus directly depends on HeatGauge
    – Changes to HeatGauge can affect SystemStatus
public class SystemStatus {

    private HeatGauge gauge = new HeatGauge();

    public void checkTemperature() throws OverheatingException {
        if(gauge.actualTemperature() > 55) {
            throw new OverheatingException();
        }
    }
}




                                SOLID Software Design              79
Dependency Inversion Principle

Simple Example
   – Abstract away the dependency
public interface HeatGauge {
    public int actualTemperature();
}

public class HeatGaugeImpl implements HeatGauge {
    public int actualTemperature() {
        // Do some measuring
    }
}




                                SOLID Software Design   80
Dependency Inversion Principle

Simple Example
    – Use the new abstraction
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();
        }
    }
}



    – Better, but not perfect


                                SOLID Software Design              81
Dependency Inversion Principle

Simple Example
    – Improving the example
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();
        }
    }
}

    – Abstracts away the implementation used to gauge
      the temperature
                                   SOLID Software Design           82
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/06/on

  – In response to
  – http://www.joelonsoftware.com/items/2009/01/31.ht




                    SOLID Software Design         95
Q&A

Any questions left?




                      SOLID Software Design   96

bGenius kennissessie_20120510

  • 1.
    SOLID Software Design @jankeesvanandel @jwalgemoed @JPoint SOLID Software Design 1
  • 2.
    About us Jarno Walgemoed Jan-Kees van Andel –Architect @JPoint –Architect @JPoint –Fa-Med r –Rabobank r pe pe –Blinker –SNS Bank lo ve –DJI elo D e –Apache MyFaces v –Devoxx Steering De SOLID Software Design 2
  • 3.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 3
  • 4.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 4
  • 5.
    Goals NOT our goal SOLID Software Design 5
  • 6.
    Goals Mastery takes lotsof practice – You can’t learn to surf by reading a book – Neither programming SOLID Software Design 6
  • 7.
    Goals “The10.000 hour rule” – Malcolm Gladwell SOLID Software Design 7
  • 8.
    Goals • ShuHaRi – Shu: Traditional wisdom – Ha: Breaking with tradition – Ri: Transcendence SOLID Software Design 8
  • 9.
    Goals After this session – you will NOT suddenly write better code But… – you hopefully have some hooks to get better SOLID Software Design 9
  • 10.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 10
  • 11.
    Code quality Is thiscode quality? 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()); SOLID Software Design 11
  • 12.
    Code quality Is thiscode quality? @Controller public class StartController { @Autowired public StartController(SessionData sessionData, TransactionService txService, InitializerFactory initFactory, AuthorizationHandler authHandler, UIBinder uiBinder, StartValidator startValidator, WebApplicationContext ctx, RegistrationService regService) { //... SOLID Software Design 12
  • 13.
    Code quality Is thiscode quality? SOLID Software Design 13
  • 14.
    Code quality Is thiscode quality? SOLID Software Design 14
  • 15.
    Code quality Is thiscode quality? /** * 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 { SOLID Software Design 15
  • 16.
    Code quality Is thiscode quality? /** * 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 { SOLID Software Design 16
  • 17.
    Code quality Tonight, codequality 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
  • 18.
    Code quality Tonight, codequality 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
  • 19.
    Code quality Tonight, codequality 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
  • 20.
    Code quality Why dependencyManagement? – Because we don’t want code rot SOLID Software Design 20
  • 21.
    Code quality Why dependencyManagement? – Refactor sprint SOLID Software Design 21
  • 22.
    Code quality Why dependencyManagement? – Continuous refactoring SOLID Software Design 22
  • 23.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 23
  • 24.
    SOLID SOLID –First stated by Robert C. Martin in 1995 – “The Ten Commandments of OO Programming” SOLID Software Design 24
  • 25.
    SOLID SOLID: –Later documented in “Agile Software Development: Principles, Patterns and Practices” SOLID Software Design 25
  • 26.
    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
  • 27.
    Single Responsibility Principle “Aclass should have only one reason to change” – Theory – Simple example – Real world example – Considerations – Conclusion SOLID Software Design 27
  • 28.
    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
  • 29.
    Single Responsibility Principle SOLID Software Design 29
  • 30.
    Single Responsibility Principle Simpleexample – Database application interface specification public interface Database { public void connect(String url); public void disconnect(); public ResultSet executeQuery(String query); } SOLID Software Design 30
  • 31.
    Single Responsibility Principle Simpleexample – 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
  • 32.
    Single Responsibility Principle Simpleexample – How about this? public interface DatabaseConnection { public ResultSet executeQuery(String query); } public interface DatabaseConnectionManager { public DatabaseConnection connect(String url); public void disconnect(DatabaseConnection conn); } SOLID Software Design 32
  • 33.
    Single Responsibility Principle Simpleexample – DatabaseConnection implementations handle querying – DatabaseConnectionManager implementations handle connections – We’ve managed to split two responsibilities SOLID Software Design 33
  • 34.
    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
  • 35.
    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
  • 36.
    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
  • 37.
    Single Responsibility Principle Question:Real world usages of SRP? – Examples in Java API – Examples in GoF Design Patterns – Big abusers SOLID Software Design 37
  • 38.
    Open-Closed Principle “Software entitiesshould be open for extension, but closed for modification” – Theory – Simple example – Real world example – Considerations – Conclusion SOLID Software Design 38
  • 39.
    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
  • 40.
    Open-Closed Principle SOLID Software Design 40
  • 41.
    Open-Closed Principle Simple Example – We are using this Rectangle object public class Rectangle { private int width; private int height; public int getWidth() { return width; } public int getHeight() { return height; } } SOLID Software Design 41
  • 42.
    Open-Closed Principle Simple Example – With this function we calculate area totals public class AreaCalculator { public int calculateTotalArea(Rectangle [] rectangles) { int totalArea = 0; for(Rectangle rectangle : rectangles){ totalArea += rectangle.getWidth() * rectangle.getHeight(); } return totalArea; } } SOLID Software Design 42
  • 43.
    Open-Closed Principle Simple Example – Now we want to add a circle to the equation public class Circle { private int radius; public int getRadius() { return radius; } } SOLID Software Design 43
  • 44.
    Open-Closed Principle Simple Example – What happens to the calculation? 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; } SOLID Software Design 44
  • 45.
    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
  • 46.
    Open-Closed Principle Simple Example – Introducing Shape and extending it public abstract class Shape { public abstract double getArea(); } public class Circle extends Shape { public double getArea() { return radius * radius * Math.pi; } … } SOLID Software Design 46
  • 47.
    Open-Closed Principle Simple Example – Simplifies AreaCalculator substantially – Allows future extension public class AreaCalculator { public double calculateTotalArea(Shape[] shapes) { double totalArea = 0; for (Shape shape : shapes) { totalArea += shape.getArea(); } return totalArea; } } SOLID Software Design 47
  • 48.
    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
  • 49.
    Open-Closed Principle Considerations SOLID Software Design 49
  • 50.
    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
  • 51.
    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
  • 52.
    Open-Closed Principle Question: Realworld usages of OCP? – Examples in Java API – Examples in GoF Design Patterns – Big abusers SOLID Software Design 52
  • 53.
    Liskov Substitution Principle “Iffor 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
  • 54.
    Liskov Substitution Principle “Subtypesmust be substitutable for their base types” – Theory – Simple example – Real world example – Considerations – Conclusion SOLID Software Design 54
  • 55.
    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
  • 56.
    Liskov Substitution Principle SOLID Software Design 56
  • 57.
    Liskov Substitution Principle SimpleExample – 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
  • 58.
    Liskov Substitution Principle SimpleExample – So, this is correct then? 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); } } SOLID Software Design 58
  • 59.
    Liskov Substitution Principle SimpleExample – Suppose we test the Square like this Square square = new Square(42); assertEquals(42, square.getWidth()); // Ok square.setHeight(50); // Width should be the same as height, and we changed it! assertEquals(50, square.getWidth()); // Whoops! – Our square suddenly is a 42 by 50 Rectangle! SOLID Software Design 59
  • 60.
    Liskov Substitution Principle SimpleExample – Fixing is easy, but is this really the way to go? 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); } } SOLID Software Design 60
  • 61.
    Liskov Substitution Principle SimpleExample – Maybe better to do this 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; } } SOLID Software Design 61
  • 62.
    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
  • 63.
    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
  • 64.
    Liskov Substitution Principle Question:Real world usages of LSP? – Examples in Java API – Examples in GoF Design Patterns – Big abusers SOLID Software Design 64
  • 65.
    Interface Segregation Principle “Clientsshould not be forced to depend on methods that they do not use” – Theory – Simple example – Real world example – Considerations – Conclusion SOLID Software Design 65
  • 66.
    Interface Segregation Principle SOLID Software Design 66
  • 67.
    Interface Segregation Principle SimpleExample – Interface definition for a worker doing work public interface Worker { public void work(); public void eat(); } – Implementation for a generic employee public class Employee implements Worker { public void work() { // do work stuff } public void eat() { // eat lunch, keep up strength ;) } } SOLID Software Design 67
  • 68.
    Interface Segregation Principle SimpleExample – Robots are also part of the business public class Robot implements Worker { public void work() { // Work (without union breaks } public void eat() { // Wait, what? } } – But they don’t eat lunch – Still, eat() has to be implemented SOLID Software Design 68
  • 69.
    Interface Segregation Principle SimpleExample – Split up the interfaces into sensible pieces public interface NutritionConsumer { public void eat(); } public interface Worker { public void work(); } SOLID Software Design 69
  • 70.
    Interface Segregation Principle SimpleExample – Implement the interfaces as needed public class Employee implements Worker, NutritionConsumer { public void work() { } public void eat() { } } public class Robot implements Worker { public void work() {} } SOLID Software Design 70
  • 71.
    Interface Segregation Principle SimpleExample – Class dealing with Worker objects public class WorkloadManager { public void putWorkerToWork(Worker worker) { worker.work(); } } – 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
  • 72.
    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
  • 73.
    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
  • 74.
    Interface Segregation Principle Question:Real world usages of ISP? – Examples in Java API – Examples in GoF Design Patterns – Big abusers SOLID Software Design 74
  • 75.
    Dependency Inversion Principle “High-levelmodules 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
  • 76.
    Dependency Inversion Principle SOLID Software Design 76
  • 77.
    Dependency Inversion Principle SimpleExample – Application that monitors system status public class SystemStatus { private HeatGauge gauge; public void checkTemperature() throws OverheatingException { if(gauge.actualTemperature() > 55) { throw new OverheatingException(); } } } SOLID Software Design 77
  • 78.
    Dependency Inversion Principle SimpleExample – HeatGauge implementation public class HeatGauge { public int actualTemperature() { // Do some measuring and return the results } } SOLID Software Design 78
  • 79.
    Dependency Inversion Principle SimpleExample – Systemstatus directly depends on HeatGauge – Changes to HeatGauge can affect SystemStatus public class SystemStatus { private HeatGauge gauge = new HeatGauge(); public void checkTemperature() throws OverheatingException { if(gauge.actualTemperature() > 55) { throw new OverheatingException(); } } } SOLID Software Design 79
  • 80.
    Dependency Inversion Principle SimpleExample – Abstract away the dependency public interface HeatGauge { public int actualTemperature(); } public class HeatGaugeImpl implements HeatGauge { public int actualTemperature() { // Do some measuring } } SOLID Software Design 80
  • 81.
    Dependency Inversion Principle SimpleExample – Use the new abstraction 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(); } } } – Better, but not perfect SOLID Software Design 81
  • 82.
    Dependency Inversion Principle SimpleExample – Improving the example 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(); } } } – Abstracts away the implementation used to gauge the temperature SOLID Software Design 82
  • 83.
    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
  • 84.
    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
  • 85.
    Dependency Inversion Principle Question:Real world usages of DIP? – Examples in Java API – Examples in GoF Design Patterns – Big abusers SOLID Software Design 85
  • 86.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 86
  • 87.
    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
  • 88.
    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
  • 89.
    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
  • 90.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 90
  • 91.
    Conclusion Demo –Small web application to demo the ideas SOLID Software Design 91
  • 92.
    Agenda – Goals – Code quality – SOLID – Other principles – Demo – Conclusion – Q&A SOLID Software Design 92
  • 93.
    Conclusion Master the SOLIDprinciples – 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
  • 94.
    Conclusion SOLID principles areno 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
  • 95.
    Conclusion Don’t be dogmatic – Even Uncle Bob said this – http://blog.objectmentor.com/articles/2009/02/06/on – In response to – http://www.joelonsoftware.com/items/2009/01/31.ht SOLID Software Design 95
  • 96.
    Q&A Any questions left? SOLID Software Design 96

Editor's Notes

  • #38 Java API: -Examples: -Abusers: Almost every class with Context or Manager in it (javax.faces.FacesContext, javax.persistence.EntityManager, javax.servlet, HttpServletRequest, java.lang.Math, java.util.Collections) GoF Examples: Template Method, Chain of Responsibility, Decorator Abusers:
  • #53 Java API: -Examples: javax.servlet.Filter, -Abusers: java.lang.String GoF -Examples: Template Method, Chain of Responsibility, Decorator, Abstract Factory, Command -Abusers: Singleton What about Aspect Oriented Programming? Open-Closed Principle on module level
  • #65 Java API: -Examples: java.util.Collection, java.util.Set, java.util.List, java.util.Map, -Abusers: GoF -Examples: State, Strategy, Command, -Abusers: Template Method, Decorator
  • #75 Java API: -Examples: Serializable, Cloneable, Collection (specifics are in List, Set, Map) -Abusers: Iterable (why .remove()?) GoF -Examples: Adapter, Mediator -Abusers:
  • #86 Java API: -Examples: javax.servlet.HttpServlet (interfaces of HttpServletRequest/Response passed in, details are hidden) -Abusers: All static functions GoF -Examples: Strategy, State, Iterator, -Abusers: Spring Framework (Dependency Injection vs. Dependency Inversion)