SOLID Principles in .NET

Posted by

SOLID is an acronym that represents 5 principles of object-oriented software design. These principles were introduced by Robert Martin and are considered best practices for designing maintainable and scalable software systems.

  1. Single Responsibility Principle (SRP) – A class should have only one reason to change. Example in .NET: Consider a class PrintService that is responsible for printing documents. The class should only have responsibilities related to printing and should not include any other responsibilities like saving to disk or sending an email.
  2. Open/Closed Principle (OCP) – Software entities should be open for extension but closed for modification. Example in .NET: Consider a class Shape that defines the basic behavior for geometric shapes. New shapes can be added to the system without modifying the existing Shape class by creating new classes that inherit from it.
  3. Liskov Substitution Principle (LSP) – Subtypes must be substitutable for their base types. Example in .NET: Consider a class Rectangle that inherits from the base class Shape. The class Rectangle should not have any behavior that violates the contracts established by the base class Shape.
  4. Interface Segregation Principle (ISP) – Clients should not be forced to depend on interfaces they do not use. Example in .NET: Consider an interface IEmailService that defines methods for sending and receiving emails. The method for receiving emails is not used by all clients. To adhere to the ISP, the interface can be split into two separate interfaces: IEmailSender and IEmailReceiver.
  5. Dependency Inversion Principle (DIP) – High-level modules should not depend on low-level modules. Both should depend on abstractions. Example in .NET: Consider a class OrderProcessor that depends on a concrete class ShippingCalculator to calculate shipping costs. To adhere to the DIP, the class OrderProcessor should depend on an abstraction (interface) IShippingCalculator instead of a concrete implementation.

Adhering to these principles can lead to more maintainable and scalable software systems.

Following are some examples w.r.t. C# coding for SOLID depiction,

  1. Single Responsibility Principle (SRP): A class should have only one reason to change.
public class UserService
{
    public void CreateUser(User user)
    {
        // Implementation for creating user
    }

    public void UpdateUser(User user)
    {
        // Implementation for updating user
    }
}
  1. Open/Closed Principle (OCP): Classes should be open for extension but closed for modification.
public interface IPrinter
{
    void Print(Document document);
}

public class ConsolePrinter : IPrinter
{
    public void Print(Document document)
    {
        Console.WriteLine(document.Content);
    }
}

public class FilePrinter : IPrinter
{
    public void Print(Document document)
    {
        File.WriteAllText(document.FileName, document.Content);
    }
}
  1. Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types.
public class Rectangle
{
    public int Width { get; set; }
    public int Height { get; set; }

    public virtual int Area()
    {
        return Width * Height;
    }
}

public class Square : Rectangle
{
    public new int Width
    {
        get { return base.Width; }
        set { base.Width = base.Height = value; }
    }

    public new int Height
    {
        get { return base.Height; }
        set { base.Width = base.Height = value; }
    }
}
  1. Interface Segregation Principle (ISP): Clients should not be forced to depend on interfaces they do not use.
public interface IWorker
{
    void Work();
    void Eat();
}

public interface IWorkable
{
    void Work();
}

public interface IFeedable
{
    void Eat();
}

public class Robot : IWorkable
{
    public void Work()
    {
        // Implementation for work
    }
}

public class Human : IWorkable, IFeedable
{
    public void Work()
    {
        // Implementation for work
    }

    public void Eat()
    {
        // Implementation for eat
    }
}
  1. Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions.
public interface IDatabase
{
    void SaveData(string data);
}

public class SQLDatabase : IDatabase
{
    public void SaveData(string data)
    {
        // Implementation for saving data to SQL database
    }
}

public class Logger
{
    private readonly IDatabase _database;

    public Logger(IDatabase database)
    {
        _database = database;
    }

    public void Log(string message)
    {
        _database.SaveData(message);
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.