CS3342 Lecture 6
Software Design Principles - OCP, LSP, DIP
Software design principles: Characteristics of Good Software Design.
- Single Responsibility Principle (SRP)
- Open-Closed Principle (OCP)
- Liskov Substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
- Law of Demeter Principle (LoD)
Open-Closed Principle (OCP)
Software entities (class, modules, functions, etc)
- should be Open for Extension,
- but Closed for Modification
OCP provides a better design structure
Target of our programming style: Modules should be written so they can be extended without requiring them to be modified
Example:
Solution: Get rid of IF… THEN… ELSE
Best Solution: OCP Abstraction
=>
Example:
OCP Heuristics – Private Data (-)
Make all object-data, variables within an object private. (No public Variables (publically accessible data)!)
Summary:
- Open for extension – easily to add new functions
- Closed for modification and access – minimize impacts to existing code when making a change or an addition.
- Use class abstraction (interface/abstract in Java or virtual class in C++) for what is common in the variation
-
Java “Interface” : implicit abstract and cannot have implementations
-
Java “Abstract” : can implement default behaviors.
-
- Use subclassing (or polymorphism) to provide different behaviors in subclasses.
Liskov Substitution Principle (LSP)
LSP Keywords:
- Substitutability / Replaceable?
- The Definition/Measure of a subtyping relation
- Strong behavioural subtyping
- Ensure that new derived subclasses ONLY extending the base-class
- Without changing their behaviour
Derived subclasses (sub-types) must be completely substitutable for their parent class (base type).
- i.e. Substituted / Replaced by another set of implementations.
- Can an iPad be abstracted and reasoned as a computer? If Yes, then class iPad can inherit from class Computer.
LSP is about Meaning and Substitution
- Make sure subclasses can be used to “replace” their parent class.
- Subclass could have additional features.
- Subclass should not inherit features don’t exist in the actual context!
LSP problem
Analysis:
- For a Square, the attributes Height and Width must be equal.
- We can override setHeight and setWidth to perform the same task (i.e., we duplicate the code in two functions),
- BUT we cannot control any caller object of a Square object to use the sequence of these methods semantically meaningful
Dependency Inversion Principle (DIP)
- A specific form of decoupling software modules.
- Direction of dependency matters
I. High-level modules should not depend on Low-level modules.
Both should depend on abstractions.
II. Abstractions should not depend on details.
Details should depend on abstractions.
DIP Violation
- All classes in the diagram on the above are concrete classes.
- ABussinessClass in the business (top) layer depends on AServiceClass in the service (middle) layer. Similarly, AServiceClass depends on a AUtilityClass in the utility (bottom) layer, e.g., the code of ABussinessClass calls a method of AServiceClass.
- Thus, the above business class depends transitively on the classes at the bottom layer.
- This is poor in design because changes in low level modules may lead to changes in high-level modules.
- Also, high-level modules will be more difficult to reuse in other contexts
Design towards an Interface, NOT an implementation.
When in Doubt(if not sure…), add a new Level of indirectness
DIP Example:
- Button directly depends on Lamp.
- Button cannot be reused for other appliances (e.g., SpotLight). becauce: Private Lamp lamp; explicitly declared
- Create a generalized interface Appliance, for the operations of “turningOn()” and “turningOff()”.
- Revise the Button class so that Button class depends on the newly created generalized interface Appliance.
- Different appliances can now be implemented using this generalized interface, and be controlled by pushButton().
Summary:
- Both low-level class and high-level class depend on their abstractions (i.e. abstract or interface classes)
- High-level modules owns the interface (e.g., create a demand of the operations in the interface and hence determine the content of the interface)
- Common interface is an important for Software Engineering Dev. Teams, for software enhancement, maintenance, upgrades..etc.
- Low-level classes should implement toward their interface.
Summary of OCP,LSP,DIP
- Open for Extension
- Closed for modification
- The design of a subclass can be a substitute of its parent class
- Subclass must comply with their superclass
- Avoid incorrect dependency
- Use interface/abstract for better extension