Solid Principles

Solid Principles

Solid Principles are the time tested principles for writing clean and high quality code in object oriented programming.

Why should you study SOLID Principles?

Studying the SOLID principles is essential for software developers because they provide a clear framework for designing software that's easy to maintain, scalable, and resilient against bugs. You will find a major difference in your code quality once you learn these principles as they are time tested.

The Liskov Substitution Principle (LSP) is a fundamental principle in object-oriented programming. It states that objects of a superclass should be replaceable with objects of its subclass without affecting the correctness of the program.

Here is an example of pseudocode that demonstrates LSP:

```
class Shape {
method draw() {
// Perform the generic drawing logic
}
}

class Circle extends Shape {
method draw() {
// Implement the specific drawing logic for a circle
}
}

class Rectangle extends Shape {
method draw() {
// Implement the specific drawing logic for a rectangle
}
}

function drawShape(Shape shape) {
shape.draw();
}

// Usage
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();

drawShape(shape1); // This will draw a circle
drawShape(shape2); // This will draw a rectangle
```

In this pseudocode, the `Shape` class defines a generic `draw` method that is common for all shapes. The `Circle` and `Rectangle` classes extend the `Shape` class and provide their own specific implementations of the `draw` method.

The `drawShape` function takes an object of type `Shape` as a parameter and calls its `draw` method. This function doesn't need to know the specific shape it is drawing; it only relies on the fact that any object of type `Shape` can be replaced with its subclass objects (`Circle` or `Rectangle`) without affecting the correctness of the program.

By adhering to LSP, we ensure that our code is flexible and extensible while maintaining the behavior expected from objects of the superclass.

Code Example

Without Liskov Substitution Principle Principle


Class Bird {
    Method fly() {
        // Code for flying
    }
}

Class Penguin Inherits Bird {
    Method fly() {
        // Penguin cannot fly, but since it's a bird, this method might be implemented inappropriately.
        // This scenario breaks the Liskov Substitution Principle because a penguin is not substitutable for a bird that can fly.
    }
}

Function makeBirdFly(Bird bird) {
    bird.fly();  // This seems correct because generally, birds fly, but it's not true for all birds (e.g., penguin).
}

// Usage
Bird penguin = new Penguin();
makeBirdFly(penguin);  // This will cause issues since penguins can't fly, violating LSP.

With Liskov Substitution Principle Principle


Class Bird {
}

Class FlyingBird Inherits Bird {
    Method fly() {
        // Code for flying, applicable to birds that can fly.
    }
}

Class Penguin Inherits Bird {
    // Penguin class doesn't have fly method, adhering to LSP.
}

Function makeBirdFly(FlyingBird bird) {
    bird.fly();  // This is correct as we are sure that the bird passed to this function can fly.
}

// Usage
FlyingBird sparrow = new FlyingBird();
makeBirdFly(sparrow);  // Correct usage, LSP is not violated.

Bird penguin = new Penguin();
// makeBirdFly(penguin); would be an error if uncommented because the penguin is not a FlyingBird, preserving LSP.

The Liskov Substitution Principle (LSP) is a concept in object-oriented programming that states that objects of a superclass should be replaceable with objects of its subclasses without altering the correctness of the program. Here are the key points to keep in mind when implementing LSP in pseudocode:

1. Use Inheritance: Create a superclass that defines a common interface and behavior for multiple subclasses. The subclasses should inherit from the superclass.

2. Limit Preconditions: The preconditions (input requirements) of the superclass methods should not be strengthened in the subclass methods. If the superclass expects certain inputs, the subclass should not require more specific or restricted inputs.

3. Relax Postconditions: The postconditions (output guarantees) of the superclass methods should not be weakened in the subclass methods. If the superclass guarantees certain outputs, the subclass should ensure the same or stronger guarantees.

4. Avoid Exceptions: The subclass methods should not throw any additional or broader exceptions than the superclass methods. If the superclass method throws a specific exception, the subclass method should either throw the same exception or a subclass of it.

5. Preserve Behavioral Consistency: The behavior of the subclass methods should match or extend the behavior of the superclass methods. The subclass should not introduce new behaviors that are not present in the superclass.

Here's a pseudocode example demonstrating the implementation of LSP:


class Shape:
method draw():
// Common implementation for all shapes
...

class Circle inherits Shape:
method draw():
// Implements drawing a circle
...

class Rectangle inherits Shape:
method draw():
// Implements drawing a rectangle
...

function main():
shape1 = Circle()
shape2 = Rectangle()

drawShapes(shape1, shape2)

function drawShapes(shape1, shape2):
shape1.draw()
shape2.draw()
```

In this example, the superclass `Shape` defines a common interface for the subclasses `Circle` and `Rectangle` using the `draw` method. The `drawShapes` function can accept any object of type `Shape` or its subclasses and invoke the `draw` method without any issues, as per the LSP.
Common mistakes while implementing the Liskov Substitution Principle in pseudocode include:

1. Changing preconditions: One mistake is changing the preconditions in a derived class. The Liskov Substitution Principle states that the preconditions of a base class method should not be strengthened in a derived class. If the derived class has stricter requirements than the base class, it violates the principle.

2. Violating postconditions: Another mistake is violating the postconditions of a base class method in a derived class. The Liskov Substitution Principle requires that the derived class method should fulfill the same postconditions as the base class method. If the derived class method weakens or changes the postconditions, it violates the principle.

3. Adding new exceptions: Introducing new exceptions in a derived class method that are not present in the base class violates the Liskov Substitution Principle. The principle states that a client should be able to rely on the exceptions thrown by the base class method and handle them appropriately.

Best practices for implementing the Liskov Substitution Principle in pseudocode:

1. Follow the contract of the base class: Ensure that all derived classes adhere to the contract defined by the base class. This includes maintaining the same behavior and semantics of the base class methods.

2. Avoid code duplication: Refrain from duplicating code from the base class in derived classes. Instead, use inheritance properly to inherit and extend the behavior of the base class.

3. Use polymorphism: Leverage polymorphism to implement different behaviors for derived classes while still conforming to the base class contract. By using inheritance and virtual methods, you can achieve this effectively.

4. Test for substitutability: Test your derived classes to ensure that they can be substituted for instances of the base class without causing any issues or violating the Liskov Substitution Principle.

5. Document the design: Clearly document the relationship between the base class and derived classes, along with any additional constraints or requirements that the derived classes need to follow. This documentation will help other developers understand and adhere to the Liskov Substitution Principle.

SolidPrinciples is a website dedicated to SOLID Principles. We want to ensure developers really the understand SOLID Principles and understand how to apply them in their code. It is both beginner and intermediate level friendly.

SolidPrinciples

SolidPrinciples © 2024 All rights reserved.

email
email
email