Dependency Inversion Principle (DIP)

Dependency Inversion Principle (DIP)

The Dependency Inversion Principle states: High-level modules should not depend on low-level modules. Both should depend on abstractions. Also, abstractions should not depend on details; details should depend on abstractions.

 

Real-Time Example: Notification System

Imagine an application that needs to send notifications (email, SMS, etc.).

Violates DIP (Tightly Coupled Design):

public class NotificationService

{

    private readonly EmailSender emailSender = new EmailSender();

 

    public void Notify(string message)

    {

        emailSender.SendEmail(message);

    }

}

 

public class EmailSender

{

    public void SendEmail(string message)

    {

        Console.WriteLine($"Email sent: {message}");

    }

}

Here, NotificationService directly depends on the concrete class EmailSender. This tight coupling makes it hard to testextend, or replace (e.g., with SmsSender).

 

Follows DIP (Loosely Coupled Design):

Introduce an abstraction:

public interface INotifier

{

    void Send(string message);

}

Implement different types of notifiers:

public class EmailSender : INotifier

{

    public void Send(string message)

    {

        Console.WriteLine($"Email: {message}");

    }

}

 

public class SmsSender : INotifier

{

    public void Send(string message)

    {

        Console.WriteLine($"SMS: {message}");

    }

}

Inject the dependency:

public class NotificationService

{

    private readonly INotifier notifier;

 

    public NotificationService(INotifier notifier)

    {

        this.notifier = notifier;

    }

 

    public void Notify(string message)

    {

        notifier.Send(message);

    }

}

Now, NotificationService depends on an abstraction (INotifier), not a specific class. This allows easy substitution, testing, and extension.

 

Benefits of Applying DIP

  • Promotes loose coupling
  • Improves testability using mocks/fakes
  • Enables flexibility and scalability
  • Encourages interface-driven design

This principle is the backbone of dependency injection in frameworks like ASP.NET Core, where services are registered and resolved by abstractions — not directly constructed.

DIP helps build software systems that are modular, reusable, and easy to refactor as requirements evolve.

Comments

Popular posts from this blog

Multiline to singleline IN C# - CODING

EF Core interview questions for beginners

EF Core interview questions for experienced