13-SOLID

Pragmatic Programmer Principles

  • Core Concept: Eliminate effects between unrelated components by designing them to be:

    • Self-contained

    • Independent

    • Having a single, well-defined purpose

Key Design Principles: SOLID

  • Purpose: SOLID is a set of principles aimed at improving software design and maintainability.

  • Key Principles:

    1. Single Responsibility Principle (SRP)

    2. Open/Closed Principle (OCP)

    3. Liskov Substitution Principle (LSP)

    4. Interface Segregation Principle (ISP)

    5. Dependency Inversion Principle (DIP)

Understanding Abstraction

  • Definition: Abstraction is the high-level concept aimed at managing complexity.

  • Key Points:

    • Focuses on essential aspects for a given task and stakeholder.

    • Both excessive and insufficient abstraction can hinder understanding.

    • Facilitates discussion by aligning with individual stakeholder perspectives.

Decomposition

  • Definition: A mechanism for conceptualizing abstractions.

  • Objective: Break down complex descriptions into manageable parts.

  • Methodologies:

    • Can be approached both top down and bottom up.

    • Aim to simplify common tasks without limiting exceptional tasks.

Information Hiding

  • Definition: Refers to how programs utilize abstraction.

  • Functionality: Hides implementation details from higher-level interfaces.

  • Principles:

    • Separate variable elements from stable elements.

    • Differentiate between names and implementations (API vs. implementation).

Encapsulation

  • Definition: A language mechanism for implementing information hiding.

  • Characteristics:

    • Typically implemented through language interfaces.

    • Encompasses both data and behavior, separating them from their implementation details.

Abstraction vs. Encapsulation

  • Comparison:

    • Abstraction: Focuses on hiding unimportant details.

    • Encapsulation: Combines data and behavior to veil irrelevant details.

    • Integration: Encapsulation adds abstraction (e.g., creating a Cat class to encapsulate all cat behaviors).

Learning Outcomes

  • By the end of this lecture, you should be able to:

    • Evaluate SOLID principles in practice and identify adherence.

    • Identify principle violations and suggest refactorings to correct them.

    • Recognize interconnections among principles and their potential cascading violations.

Detailed Examination of SOLID Principles

Single Responsibility Principle (SRP)

  • Definition: A class should have only one responsibility.

  • Implication: Only one type of change in the system specification should affect the implementation of the class.

  • Violations: Divergent changes signal SRP violations, indicating a class is managing multiple responsibilities.

Example of SRP Violation
public class Employee {
  // Determines how much an employee is paid
  public calculatePay(): number;
  // Stores Employee data in database
  public save(): void;
  // Reports hours worked and pay for auditing
  public reportHours(): string;
}
Fixing SRP Violation
  • Each class should represent a single function with a single reason to change:

public class PayCalculator {
  public calculatePay(emp: Employee): number;
}
public class EmployeeRepository {
  public save(emp: Employee): void;
}
public class ReportGenerator {
  public reportHours(emp: Employee): string;
}

Open/Closed Principle (OCP)

  • Definition: A class must be closed for modification but open for extension.

  • Design Implication: Base functionalities should remain unchanged while allowing extensions.

  • Strategy: Leverage inheritance or modular additions to implement new functionalities.

OCP Violation Example
  • If core class methods require overriding when specializing, it violates the OCP.

  • Improvement Example:

public init(): void {
   // Implementation that loads configurations
}

Liskov Substitution Principle (LSP)

  • Definition: For any derived class to be substitutable for its base class, it must adhere to the properties of the base class.

  • Formula ( Type T and S hierarchy:**

    • Let ext{ϕ(x)} be a property for object x of type T.

    • Then ext{ϕ(y)} should hold for objects y of type S where S is a subtype of T.

Related Principle Aspects
  • Substitutability: Subclass should uphold the expectations set by its superclass.

  • Precondition Rule: Should not strengthen preconditions.

  • Postcondition Rule: Should not weaken postconditions.

Testing and LSP

  • Tests Requirement: Supertype black box tests must pass even when a subtype is substituted.

  • Form of Testing: For a class to be effectively substitutable for its superclass,

  • All the supertype tests should succeed on an instance of the subtype.

Summary of Liskov Substitution Principle

  • It emphasizes that objects of a superclass should be replaceable with objects of a subclass without altering the program's desirable properties. The integrity of behavior and outcome should remain consistent across derived classes, thereby facilitating maintainability, extensibility, and correct functionality throughout the codebase.