DEV Community

Cover image for SOLID in Software Development - 5
ajay-8192
ajay-8192

Posted on

SOLID in Software Development - 5

Dependency Inversion Principle (DIP)

The Dependency Inversion Principle (DIP) states that "High-level modules should not depend on low-level modules; both should depend on abstractions." In other words, we should depend on high-level abstractions (interfaces, abstract classes) rather than on low-level concretions (concrete classes, implementations). This makes our code more flexible and easier to test.

Here is an example of how the DIP can be violated:

public class EmailService {
    private SendEmailUseCase sendEmailUseCase;

    public EmailService(SendEmailUseCase sendEmailUseCase) {
        this.sendEmailUseCase = sendEmailUseCase;
    }

    public void sendEmail(String to, String subject, String body) {
        sendEmailUseCase.sendEmail(to, subject, body);
    }
}

public class SendEmailUseCase {
    private SMTPClient smtpClient;

    public SendEmailUseCase(SMTPClient smtpClient) {
        this.smtpClient = smtpClient;
    }

    public void sendEmail(String to, String subject, String body) {
        smtpClient.connect();
        smtpClient.send(to, subject, body);
        smtpClient.disconnect();
    }
}
Enter fullscreen mode Exit fullscreen mode

The EmailService class depends on the SendEmailUseCase class, which in turn depends on the SMTPClient class. This violates the DIP because the EmailService class depends on a low-level concretion (SMTPClient). This makes the EmailService classless flexible and more difficult to test.

A better way to design this code would be to use an interface to abstract the SMTPClient class:

public interface SMPTClient {
    void connect();
    void send(String to, String subject, String body);
    void disconnect();
}

public class EmailService {
    private SMPTClient smtpClient;

    public EmailService(SMPTClient smtpClient) {
        this.smtpClient = smtpClient;
    }

    public void sendEmail(String to, String subject, String body) {
        smtpClient.connect();
        smtpClient.send(to, subject, body);
        smtpClient.disconnect();
    }
}

public class MockSMPTClient implements SMPTClient {
    @Override
    public void connect() {
        // Implement mock connection logic
    }

    @Override
    public void send(String to, String subject, String body) {
        // Implement mock send logic
    }

    @Override
    public void disconnect() {
        // Implement mock disconnect logic
    }
}

public class SendEmailUseCase {
    private SMPTClient smtpClient;

    public SendEmailUseCase(SMPTClient smtpClient) {
        this.smtpClient = smtpClient;
    }

    public void sendEmail(String to, String subject, String body) {
        smtpClient.connect();
        smtpClient.send(to, subject, body);
        smtpClient.disconnect();
    }
}
Enter fullscreen mode Exit fullscreen mode

This code follows the DIP because the EmailService class depends on an interface (SMPTClient) rather than on a low-level concretion (SMTPClient). This makes the EmailService class more flexible and easier to test.

**** 💻ALL THE BEST💻 ****

Top comments (0)