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 Interface Segregation Principle (ISP) states that clients should not be forced to depend on interfaces they do not use. It suggests that large interfaces should be split into smaller and more specific ones so that clients only need to be concerned with the interfaces relevant to their needs.

In pseudocode, the ISP can be illustrated as follows:

```
// A large interface that violates ISP
Interface IAnimal {
void walk();
void swim();
void fly();
}

// Smaller interfaces that adhere to ISP
Interface IWalker {
void walk();
}

Interface ISwimmer {
void swim();
}

Interface IFlyer {
void fly();
}

// A class implementing the smaller interfaces
Class Dog implements IWalker {
void walk() {
// implementation for walking
}
}

Class Fish implements ISwimmer {
void swim() {
// implementation for swimming
}
}

Class Bird implements IWalker, IFlyer {
void walk() {
// implementation for walking
}

void fly() {
// implementation for flying
}
}
```

By splitting the original large interface into smaller interfaces, the ISP is maintained as clients can now choose to depend only on the interfaces they need. This promotes better code organization and avoids unnecessary dependencies.

Code Example

Without Interface Segregation Principle Principle


// Here, we have a fat interface that requires implementing all methods for any class that uses it.

Interface WorkTasks {
    function workOnTask()
    function eatLunch()
    function workOnExtraTask()
}

// This class has to implement all functions, even if it doesn't use them all.
Class HumanWorker implements WorkTasks {
    function workOnTask() {
        // work on regular tasks
    }

    function eatLunch() {
        // human eating lunch
    }

    function workOnExtraTask() {
        // work on an extra task
    }
}

Class RobotWorker implements WorkTasks {
    function workOnTask() {
        // work on regular tasks
    }

    function eatLunch() {
        // Robots don't eat, so this method shouldn't be here.
        // However, due to the fat interface, it has to be.
    }

    function workOnExtraTask() {
        // work on an extra task
    }
}

// As we see, RobotWorker has a useless function eatLunch() that it's forced to implement. This is a violation of ISP.

With Interface Segregation Principle Principle


// We break down the fat interface into smaller, more specific ones.

Interface WorkTask {
    function workOnTask()
}

Interface Lunch {
    function eatLunch()
}

Interface ExtraWork {
    function workOnExtraTask()
}

// Now, classes can implement only the interfaces they need.

Class HumanWorker implements WorkTask, Lunch, ExtraWork {
    function workOnTask() {
        // work on regular tasks
    }

    function eatLunch() {
        // human eating lunch
    }

    function workOnExtraTask() {
        // work on an extra task
    }
}

Class RobotWorker implements WorkTask, ExtraWork {
    function workOnTask() {
        // work on regular tasks
    }

    // No eatLunch() method here because the robot doesn't eat. The class is not forced to implement it anymore.

    function workOnExtraTask() {
        // work on an extra task
    }
}

// This way, the RobotWorker doesn't need to worry about the eatLunch() method anymore, adhering to the Interface Segregation Principle.

Interface Segregation Principle (ISP) states that clients should not be forced to depend on interfaces they do not use. Instead of having a single large interface, it is better to have multiple smaller interfaces based on specific behaviors.

Here are the key points for implementing ISP in pseudocode:

1. Identify the different behaviors or functionalities required by the clients.
2. Define a separate interface for each behavior or functionality.
3. Each interface should contain only the methods specific to that behavior.
4. Create classes that will implement these interfaces.
5. Implement the required methods in each class according to the corresponding interface.
6. Clients can now depend on the specific interfaces they need and use only the required methods.
7. Avoid having a single interface with all methods if some clients do not need them.
8. Any changes to a specific behavior will not affect other clients as they don't depend on the unused methods.
9. This allows for better modularity and decoupling of code.
10. Repeat steps 2-9 for additional behaviors or functionalities.

By following the ISP, you can create more flexible and maintainable code by separating responsibilities into smaller, cohesive interfaces.
Common mistakes while implementing the Interface Segregation Principle (ISP) in pseudocode:

1. Including unnecessary methods in an interface: One common mistake is including methods that are not required by all implementing classes. This violates the ISP as it forces classes to implement methods that are irrelevant to them.

2. Creating large interfaces: Another mistake is creating interfaces that contain too many methods. This violates the ISP as it forces classes to implement methods that they do not need, leading to unnecessary dependencies and increased complexity.

3. Not considering future extensibility: Failing to consider future changes and additions to the system can also lead to violations of the ISP. If new requirements arise and additional methods need to be included in an interface, all implementing classes will be forced to implement these new methods even if they do not need them.

Best practices for implementing the Interface Segregation Principle in pseudocode:

1. Identify the common behavior: Start by identifying the common behavior that all implementing classes should have. This will help you determine the methods that should be included in the interface.

2. Separate interfaces by behavior: Split the interfaces based on specific behaviors or functionalities. Each interface should represent a single responsibility or behavior. This ensures that classes only implement the interfaces relevant to them.

3. Keep interfaces small and focused: Ensure that each interface contains a minimal number of methods that are cohesive and related to the specific behavior represented by the interface. This makes the intent of the interface clear and allows classes to implement only the methods they require.

4. Consider future extensibility: Think about potential future changes or additions to the system. Design interfaces in such a way that they can be easily extended without impacting existing implementing classes. This promotes flexibility and scalability.

5. Encourage composition over inheritance: Instead of relying solely on inheritance to implement interfaces, consider using composition. This allows greater flexibility and modularity, as classes can implement multiple small interfaces and reuse code more effectively.

By following these best practices, you can effectively apply the Interface Segregation Principle in your pseudocode, leading to more modular, maintainable, and flexible code.

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