Design Principles:
SOLID
21-11-24   CMPT 373         Slides 15      © Dr. B. Fraser   1
     Topics
     Name your favourite design principle which:
      1) Limits for whom we change a file.
      2) Adds new code for changes.
      3) Makes substitutable objects.
      4) Prevents depending on things you don’t need.
      5) Prevents high-level policies from depending on
         low-level details.
21-11-24                                                  2
     Design Principles
      ●
           Design principles help us design software which is:
             –   more understandable
             –   ..
             –   more maintainable
      ●
           We have seen
             –   Separate aspects that change
                 from those that stay the same
             –   Classes should be
                 open for extension, but closed for modification
             –   Program to an interface, not an implementation
             –   Favour composition over inheritance
21-11-24                                                           3
     SOLID
      ●
           SRP: Single Responsibility Principle
             –   Each part of the system must have only one reason to change.
      ●
           OCP: Open-Closed Principle
             –   For a software system to be easy to change, those changes must
                 be done through adding new code, not changing existing code.
      ●
           LSP: Liskov Substitution Principle
             –   To build a software system from interchangeable parts,
                 the parts must adhere to a contract which allows the parts
                 to be interchangeable.
      ●
           ISP: Interface Segregation Principle
             –   Don't depend on things you don't use.
      ●
           DIP: Dependency Inversion Principle
             –   Code that implements high-level policy
                 should not depend on code that implements low-level details.
21-11-24                                                 (Clean Architecture, Robert C. Martin, 2018; p59)   4
           SRP
21-11-24         5
     Single Responsibility Principle (SRP)
      ●
           ..
                –   Actor: A group of stakeholders
      ●
           Idea
                –   The contents of a module are there to
                    satisfy the needs of one group.
21-11-24                                             (Clean Architecture, Robert C. Martin, 2018)   6
     SRP Violation: Multiple Actors
      ●
           Actors’ Needs
             – calculatePay(): specified by accounting
             –   reportHours(): specified by human resources
             –   save(): specified by IT administrators
      ●
           Design couples Employee to three different actors
             – Imagine a regularHours() function used by calculatePay() and
               reportHours()
             –   If accountants ask for a change to regularHours(), the change
                 unexpectedly impacts reportHours() and HR
      ●
           SRP: Separate the code so that changes needed by one actor
                 ..
21-11-24                                                                         7
     SRP Solution
      ●
           Move each actor’s needs to own
           class
             –   Store data in its own
                 EmployeeData class
             –   Create three independent classes
                 to process the data
      ●
           No part of the processing code is
           beholden to multiple stakeholders.
21-11-24                                            8
           OCP
21-11-24         9
     Open Closed Principle (OCP)
      ●
           "A software artifact should be open for extension but
           closed for modification."
21-11-24                    (Bertrand Meyer. Object Oriented Software Construction, Prentice Hall, 1988, p23)   10
     OCP and Checked Exceptions
           High-Level
               void printResult() {
                   int value = sumValues();
                   display(value);
               }
           Logic Layer
               int sumValues() {
                   return dbGetValue("Sales")
                          + dbGetValue("Service");
               }
           DB Layer                                   What happens when
               int dbGetValue(String record) {       the DB Layer throws a
                   return ...;                        checked exception?
               }
21-11-24                                                                     11
     OCP and Checked Exceptions
           void printResult() {
               int value = 0;
               try {
                   value = sumValues();
               } catch (DbException e) {
                   display("ERROR");
               }
               display(value);
           }
           int sumValues()                       throws DbException
           {
               return dbGetValue("Sales")
                      + dbGetValue("Service");
           }
           int dbGetValue(String record)         throws DbException
           {
               return ...;
           }
21-11-24                                                              12
     OCP and Checked Exceptions
      ●
           Using Checked Exceptions Violates OCP
             –   A low-level change to one module
                 ..
      ●
           Solutions
             –   Throw unchecked exceptions
             –   Wrap exceptions inside custom (checked)
                 MyDatabaseException:
                 Changes to exceptions thrown are wrapped inside
                 custom exception.
21-11-24                                                           13
     OCP & Architecture
      ●
           Design is a spectacular failure if
           ..
      ●
           Ex: Generating a business report
             – already implemented for the web
                 (scrollable, negative numbers in red)
             –   now adding B&W print
                 (pagination, negative numbers in brackets)
      ●
           To add the print report, what needs to:
             – be changed?
             – be added?
21-11-24                                                 (Clean Architecture, Robert C. Martin, 2018) 14
     OCP & Architecture
      ●
           To add the print report, what needs to
               be changed?                 be added?
           One class         Multiple classes
21-11-24                                          (Clean Architecture, Robert C. Martin, 2018) 15
     OCP & Architecture (cont)
      ●
           OCP is about protection from change
             –   If component A should be protected from changes in
                 component B, then..
      ●
           Ex: ReportGenerator is protected
           from ScreenPresenter
             –   What does ReportGenerator
                 depend on?
             –   It's the business rules;
                 it's least likely to change;
                 it’s most likely to be reused.
      ●
           We'll see later how to use the
           dependency inversion principle.
21-11-24                                                              16
           LSP
21-11-24         17
     Inheritance
      ●
           Idea: Represents a..
      ●
           Example:
                      –   Square is-a Rectangle, and gives reuse.
                      –   But..
                                                     ..
                                                          What is an example
                                                          method in Rectangle
                                                           inconsistent with
                                                               Square?
                      –   How can we describe this problem?
21-11-24                                                                        18
     Inheritance: LSP
      ●
           Liskov Substitution Principle (LSP)
           B can inherit from A only if..
                 1)..
                        that A's method accepts (or more) and
                 2)..
                        that A's method does (or more).
      ●
           What methods in Rectangle fail LSP for Square?
             –
             –   Square does not do the same things
                 with all values as Rectangle: fails LSP.
21-11-24                                                        19
     Is-A: LSP & Immutable
      ●
           LSP & Immutable
             –   Would making Rectangle and Square immutable
                 help?
             –
      ●
           Inheritance must satisfy the SLP
           so all derived objects are interchangable.
21-11-24                                                       20
     Is-A LSP: Example
      ●
           Photographer can photograph any Animal.
           DuckPhotographer only wants to photograph Ducks.
      ●
           DuckPhotographer.photograph()
           wants to reject non-ducks
             –   Could throw an
                 IllegalArgumentException?
      ●
           DuckPhotographer
           ..
             –   ..
21-11-24                                                      21
     Is-A LSP
 ●
     Rephrase LSP:
           –   Client code using a reference to the base class must be
               able to..
           –   i.e., behaviour
               is unchanged.
21-11-24                                                                 22
           ISP
21-11-24         23
     Interface Segregation Principle (ISP)
      ●
           Clients should not be forced to..
                                Decompose into interface for each client
21-11-24                                   (Agile Principles, Patterns, and Practices in C# Martin, Micah, 2006) 24
     ISP Door Example
                        ●
                            Add a timed alarm to door using a
                            timer & listener
                        ●
                            We need VaultDoor
                            to be a TimerListener.
21-11-24                                                        25
     ISP Door Example
     ●
           What is wrong with making Door a TimerListener
           so that VaultDoor can register with the Timer?
           ●
               ..
           ●
               Derived classes need to
               implement TimerListener
           ●
               Change to TimerListener
               interface requires
               changes to all derived
               classes.
21-11-24                                                    26
     Possible ISP solution
      ●
           Don’t force classes to
           implement interfaces they don’t need.
21-11-24                                           27
           DIP
21-11-24         28
     Dependency Inversion Principle (DIP)
      ●
           Flexible code..
           not on concrete implementations.
             –   Exception for stable classes like String
             –   Apply DIP to volatile classes we are actively developing.
                 Use interfaces; they are much less volatile
21-11-24                                                                     29
     Common Case
      ●
           High-level code
           often depends on low-level implementations
      ●
           Scope of Change
             – Changes in the lowest levels (changing a class name /
               method signature)..
      ●
           Can we "invert" this so highest level is isolated from change?
           "Dependency Inversion"
21-11-24                                                                    30
     Dependency Inversion
21-11-24                    31
     Dependency Inversion
      ●
           Idea:
              – ..
      ●
           This is dependency inversion:
           Lower level depends on the
           interface in higher level
      ●
           This is Ownership Inversion:
           higher level owns the interface.
              – It dictates services it needs,
                lower levels can implement
                that to service its needs.
      ●
           ..
21-11-24                                         32
     OCP & DIP Revisited
      ●
           Before DIP, Report        ●
                                         After DIP: DB depends on
           Generator depends on DB       Report Generator
21-11-24                                                            33
     SOLID Summary
      ●
           SRP: Single Responsibility Principle
             –   Each part of the system must have only one reason to change.
      ●
           OCP: Open-Closed Principle
             –   For a software system to be easy to change, those changes must
                 be done through adding new code, not changing existing code.
      ●
           LSP: Liskov Substitution Principle
             –   To build a software system from interchangeable parts, the parts
                 must adhere to a contract which allows the parts to be
                 interchangeable.
      ●
           ISP: Interface Segregation Principle
             –   Don't depend on things you don't use.
      ●
           DIP: Dependency Inversion Principle
             –   Code that implements high-level policy
                 should not depend on code that implements low-level details.
21-11-24                                                 (Clean Architecture, Robert C. Martin, 2018; p59) 34