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.
- 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. - 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 existingShape
class by creating new classes that inherit from it. - Liskov Substitution Principle (LSP) – Subtypes must be substitutable for their base types. Example in .NET: Consider a class
Rectangle
that inherits from the base classShape
. The classRectangle
should not have any behavior that violates the contracts established by the base classShape
. - 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
andIEmailReceiver
. - 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 classShippingCalculator
to calculate shipping costs. To adhere to the DIP, the classOrderProcessor
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,
- 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
}
}
- 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);
}
}
- 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; }
}
}
- 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
}
}
- 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);
}
}