The SOLID principles are a set of five design principles that help software developers create more maintainable, flexible, and scalable software systems. These principles were introduced by Robert C. Martin and are widely used in object-oriented programming and software design.
Single Responsibility Principle (SRP): A class should have only one reason to change, meaning it should have only one responsibility. In other words, a class should have only one job.
Example in C#:
// Incorrect implementation
class Employee
{
public void CalculateSalary()
{
// ... calculate salary logic
}
public void SaveToDatabase()
{
// ... save to database logic
}
}
// Correct implementation
class Employee
{
public void CalculateSalary()
{
// ... calculate salary logic
}
}
class EmployeeRepository
{
public void SaveToDatabase(Employee employee)
{
// ... save to database logic
}
}
Open/Closed Principle (OCP): Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means you should be able to add new functionality without changing existing code.
Example in C#:
// Incorrect implementation
class Circle {
public double Radius { get; set; }
}
class AreaCalculator {
public double CalculateArea(Circle circle) {
return Math.PI * circle.Radius * circle.Radius;
}
public double CalculateArea(Rectangle rectangle) {
return rectangle.Width * rectangle.Height;
}
}
// Correct implementation using abstraction and inheritance
abstract class Shape {
public abstract double CalculateArea();
}
class Circle : Shape {
public double Radius { get; set; }
public override double CalculateArea() {
return Math.PI * Radius * Radius;
}
}
class Rectangle : Shape {
public double Width { get; set; }
public double Height { get; set; }
public override double CalculateArea() {
return Width * Height;
}
}
Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types without affecting the correctness of the program. In other words, objects of derived classes should be able to replace objects of the base class without altering the desirable properties of the program.
Example in C#:
// Incorrect implementation
class Bird {
public virtual void Fly() {
// ... flying logic
}
}
class Ostrich : Bird {
public override void Fly() {
throw new InvalidOperationException("Ostriches can't fly!");
}
}
// Correct implementation
interface IFlyable {
void Fly();
}
class Bird : IFlyable {
public void Fly() {
// ... flying logic
}
}
class Ostrich : Bird {
// Ostrich doesn't need to override Fly() since it inherits the
// implementation from Bird.
}
Interface Segregation Principle (ISP): This principle states that a class should not be forced to implement interfaces it doesn't use. In other words, a client should not be forced to depend on interfaces it doesn't need.
Example in C#:
// Incorrect implementation
interface IWorker {
void Work();
void Eat();
}
class Manager : IWorker {
public void Work() {
// ... manager-specific work logic
}
public void Eat() {
// ... manager-specific eat logic
}
}
class Developer : IWorker {
public void Work() {
// ... developer-specific work logic
}
public void Eat() {
// ... developer-specific eat logic
}
}
// Correct implementation using interface segregation
interface IWorker {
void Work();
}
interface IEater {
void Eat();
}
class Manager : IWorker, IEater {
public void Work() {
// ... manager-specific work logic
}
public void Eat() {
// ... manager-specific eat logic
}
}
class Developer : IWorker {
public void Work() {
// ... developer-specific work logic
}
}
Dependency Inversion Principle (DIP): This principle suggests that high-level modules (which provide complex logic) should not depend on low-level modules (which implement details), but both should depend on abstractions. Additionally, abstractions should not depend on details; details should depend on abstractions.
Example in C#:
// Incorrect implementation
class LightBulb {
public void TurnOn() {
// ... logic to turn on the light bulb
}
public void TurnOff() {
// ... logic to turn off the light bulb
}
}
class LightSwitch {
private LightBulb _bulb;
public LightSwitch() {
_bulb = new LightBulb();
}
public void Toggle() {
if (/* some condition */) {
_bulb.TurnOn();
} else {
_bulb.TurnOff();
}
}
}
// Correct implementation using dependency inversion
interface ISwitchable {
void TurnOn();
void TurnOff();
}
class LightBulb : ISwitchable {
public void TurnOn() {
// ... logic to turn on the light bulb
}
public void TurnOff() {
// ... logic to turn off the light bulb
}
}
class LightSwitch {
private ISwitchable _device;
public LightSwitch(ISwitchable device) {
_device = device;
}
public void Toggle() {
if (/* some condition */) {
_device.TurnOn();
} else {
_device.TurnOff();
}
}
}
Hope it will help
Comments
Post a Comment