BP242: Follow SOLID principles to write maintainable and scalable code

Follow SOLID principles to write maintainable and scalable code. SOLID is an acronym that stands for five principles of object-oriented design. These principles help developers to write code that is easy to maintain, extend, and test.

S - Single Responsibility Principle (SRP)
A class should have only one reason to change. This means that a class should have only one responsibility. If a class has more than one responsibility, it becomes difficult to change the class without affecting other parts of the system.

O - Open/Closed Principle (OCP)
A class should be open for extension but closed for modification. This means that you should be able to extend the behavior of a class without modifying its source code. This principle promotes the use of interfaces and abstract classes to define contracts between components.

L - Liskov Substitution Principle (LSP)
Subtypes should be substitutable for their base types. This means that you should be able to use a derived class wherever a base class is expected. This principle ensures that the behavior of the system is consistent and predictable.

I - Interface Segregation Principle (ISP)
Clients should not be forced to depend on interfaces they do not use. This means that you should define small, cohesive interfaces that are tailored to the needs of clients. This principle helps to avoid the problem of "interface bloat," where interfaces become too large and complex.

D - Dependency Inversion Principle (DIP)
High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. This means that you should use dependency injection to decouple components and promote the use of interfaces and abstract classes.

// Example of SRP
class Order {
  public void CalculateTotalPrice() {
    // calculate total price
  }

  public void SaveOrder() {
    // save order to database
  }
}

// Refactored example of SRP
class Order {
  public void CalculateTotalPrice() {
    // calculate total price
  }
}

class OrderRepository {
  public void SaveOrder(Order order) {
    // save order to database
  }
}

// Example of OCP
interface IShape {
  double Area();
}

class Rectangle : IShape {
  public double Width { get; set; }
  public double Height { get; set; }

  public double Area() {
    return Width * Height;
  }
}

class Circle : IShape {
  public double Radius { get; set; }

  public double Area() {
    return Math.PI * Radius * Radius;
  }
}

// Example of LSP
class Rectangle {
  public virtual double Width { get; set; }
  public virtual double Height { get; set; }

  public double Area() {
    return Width * Height;
  }
}

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

  public override double Height {
    get { return base.Height; }
    set { base.Height = value; base.Width = value; }
  }
}

// Example of ISP
interface IOrder {
  void CalculateTotalPrice();
}

interface IOrderRepository {
  void SaveOrder(Order order);
}

class Order : IOrder {
  public void CalculateTotalPrice() {
    // calculate total price
  }
}

class OrderRepository : IOrderRepository {
  public void SaveOrder(Order order) {
    // save order to database
  }
}

// Example of DIP
interface ILogger {
  void Log(string message);
}

class FileLogger : ILogger {
  public void Log(string message) {
    // log message to file
  }
}

class Order {
  private ILogger _logger;

  public Order(ILogger logger) {
    _logger = logger;
  }

  public void SaveOrder() {
    // save order to database
    _logger.Log("Order saved");
  }
}

Comments

No Comments Yet.
Be the first to tell us what you think.

Download Better Coder application to your phone and get unlimited access to the collection of enterprise best practices.

Get it on Google Play