# SOLID Principle

The SOLID principles are an object-oriented approach applied to software structure design. It was introduced by Robert C. Martin.&#x20;

The design principles encourage us to create more maintainable, understandable, and flexible software. Consequently, as our applications grow in size, we can reduce their complexity.

The word SOLID is an acronym for:

* [**S**ingle Responsibility Principle (SRP](/clean-code/bonus/solid-principle/srp-single-responsibility-principle.md))
* [**O**pen-Closed Principle (OCP)](/clean-code/bonus/solid-principle/ocp-open-closed-principle.md)
* [**L**iskov Substitution Principle (LSP)](/clean-code/bonus/solid-principle/lsp-liskov-substitution-principle.md)
* [**I**nterface Segregation Principle (ISP)](/clean-code/bonus/solid-principle/isp-interface-segregation-principle.md)
* [**D**ependency Inversion Principle (DIP)](/clean-code/bonus/solid-principle/dip-dependency-inversion-principle.md)

**SOLID principles complement each other and work together to achieve the common purpose of well-designed software.**

## Example

To understand this principle, let's see an example with a class that violates this principle as follows:

<figure><img src="/files/8NrdFbArm6TEy0hwXna3" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}

```java
class OrderService {

    private final PartnerWebClientImpl partnerWebClientImpl;

    public void sendOrderToPartner(Order order) {
        PartnerType partnerType = order.getPartnerType();
        if (partnerType == Partner1) {
            partnerWebClientImpl.sendToPartner1(order);
        } else if (partnerType == Partner2) {
            partnerWebClientImpl.sendToPartner2(order);
        } else {
            partnerWebClientImpl.sendToDefaultPartner(order);
        }
    }
}

interface PartnerWebClient {
    void sendToPartner1(Order order);
    void sendToPartner2(Order order);
    void sendToDefaultPartner(Order order);
}

class PartnerWebClientImpl {
    
    public void sendToPartner1(Order order) {
        // do something
    }

    public void sendToPartner2(Order order) {
        // do something
    }

    public void sendToDefaultPartner(Order order) {
        throw new UnsupportedPartnerException("Default partner not supported yet");
    }
}

enum PartnerType {
    Partner1,
    Partner2,
    DefaultPartner
}
```

{% endhint %}

* Violate SRP: The PartnerWebClientImpl class does many things: send to partner 1, partner 2, and a default partner.
* Violate OCP: If you have one more Partner, you have to change all classes.&#x20;
* Violate ICP: The implementation of sendToDefaultPartner() method alters the correctness of the partner. It should do something or remove completely.
* Violate ISP: One general-purpose interface PartnerWebClient.
* Violate DIP: The OrderService depends on the implementation PartnerWebClientImpl. It should depend on the interface PartnerWebClient.

Let's see how to apply SOLID:

<figure><img src="/files/5F9XcmEdVE6AhDa528ow" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}

<pre class="language-java"><code class="lang-java"><strong>class OrderService {
</strong>
    private final PartnerFactory partnerFactory;
    
    public void sendOrderToPartner(Order order) {
        PartnerService partnerService = partnerFactory.getPartnerService(order.getPartnerType());
        partnerService.handle(order);
    }
}

class PartnerFactory {

    private final List&#x3C;PartnerService> partnerServices;
    
    public void PartnerService getPartnerService(PartnerType partnerType) {
        return partnerServices.stream()
                .filter(service -> service.canHandle(partnerType))
                .findFirst()
                .orElseGet(() -> defaultPartnerService);
    }
}

interface PartnerService {

    boolean canHandle(PartnerType partnerType);

    void handle(Order order);
}

class Partner1Service implements PartnerService {

    private final PartnerWebClient partner1WebClient;

    @Override
    public boolean canHandle(PartnerType partnerType) {
        return partnerType == Partner1;
    }

    @Override
    public void handle(Order order) {
        partner1WebClient.send(order);
    }
}

class Partner2Service implements PartnerService {

    private final PartnerWebClient partner2WebClient;

    @Override
    public boolean canHandle(PartnerType partnerType) {
        return partnerType == Partner2;
    }

    @Override
    public void handle(Order order) {
        partner2WebClient.send(order);
    }
}

class DefaultPartnerService implements PartnerService {

    private final PartnerWebClient defaultPartnerWebClient;

    @Override
    public boolean canHandle(PartnerType partnerType) {
        return partnerType == null || partnerType == DefaultPartner;
    }

    @Override
    public void handle(Order order) {
        defaultPartnerWebClient.send(order);
    }
}

interface PartnerWebClient {
    void send(Order order);
}

class Partner1WebClient implements PartnerWebClient {
    public void send(Order order) {
        // do something
    }
}

class Partner2WebClient implements PartnerWebClient {
    public void send(Order order) {
        // do something
    }
}

class DefaultPartnerWebClient implements PartnerWebClient {
    public void send(Order order) {
        // do something
    }
}
</code></pre>

{% endhint %}

* Follow SRP: each class does one thing.&#x20;
* Follow OCP: easy to add new partners without modifying any existing class.&#x20;
* Follow ICP: default partner doesn't change the correctness of a partner.&#x20;
* Follow ISP: no general purpose or large interfaces.&#x20;
* Follow DIP: class depends on interfaces, not depends on implementation.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gpcoder.gitbook.io/clean-code/bonus/solid-principle.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
