DEV Community

a1excpunk
a1excpunk

Posted on

Understanding SOLID Principles with C# (short intro)

The SOLID principles are a set of design guidelines in object-oriented programming aimed at creating robust, maintainable, and scalable software. Coined by Robert C. Martin (Uncle Bob), these principles help developers avoid common pitfalls and write cleaner code.

S: Single Responsibility Principle (SRP)

Definition: A class should have only one reason to change.

Explanation: Each class should focus on a single responsibility or functionality. This makes code easier to understand, test, and maintain.

Example:

Instead of creating a User class that handles data storage and email notifications, split it into User for managing user data and EmailService for handling email notifications.

public class UserService { public void AddUser(string name) { // Implement logic  } } public class EmailService { public void SendEmail(string email) { // Implement logic  } } 
Enter fullscreen mode Exit fullscreen mode

O: Open/Closed Principle (OCP)

Definition: Classes should be open for extension but closed for modification.

Explanation: Code should allow new functionality to be added without altering existing code. This promotes stability and reduces the risk of bugs.

Example:

Instead of modifying a class to add a new type of payment method, use interfaces or inheritance to extend functionality.

public interface IPayment { void Pay(); } public class CardPayment : IPayment { public void Pay() { // Card payment  } } public class PaymentProcessor { public void Process(IPayment payment) { payment.Pay(); } } 
Enter fullscreen mode Exit fullscreen mode

L: Liskov Substitution Principle (LSP)

Definition: Subtypes must be substitutable for their base types without altering the correctness of the program.

Explanation: If a class B is a subclass of class A, then objects of type A should be replaceable with objects of type B without breaking the application.

Example:

If Rectangle is a superclass and Square inherits from it, ensure the subclass doesn’t alter behavior, such as how dimensions are set.

public interface IShape { int Area(); } public class Rectangle : IShape { public int Area() => Width * Height; } public class Square : IShape { public int Area() => Side * Side; } 
Enter fullscreen mode Exit fullscreen mode

I: Interface Segregation Principle (ISP)

Definition: A class should not be forced to implement interfaces it does not use.

Explanation: Split large interfaces into smaller, more specific ones. This ensures classes implement only what they need.

Example:

Instead of one large Animal interface with methods like Fly(), Swim(), and Run(), create specific interfaces like Flyable, Swimmable, and Runnable.

public interface IFlyable { void Fly(); } public interface IWalkable { void Walk(); } public class Bird : IFlyable, IWalkable { public void Fly() { // Flying logic  } public void Walk() { // Walking logic  } } 
Enter fullscreen mode Exit fullscreen mode

D: Dependency Inversion Principle (DIP)

Definition: High-level modules should not depend on low-level modules; both should depend on abstractions.

Explanation: Rely on abstractions rather than concrete implementations to reduce coupling between components.

Example:

Instead of hardcoding a SQLDatabase in a class, use an interface like IDatabase, allowing easy switching to other databases (e.g., NoSQL).

public interface IDatabase { void Save(string data); } public class SQLDatabase : IDatabase { public void Save(string data) { // Save to SQL  } } public class DataManager { public DataManager(IDatabase db) { db.Save("data"); } } 
Enter fullscreen mode Exit fullscreen mode

Why Use SOLID?

  1. Better Maintainability: Easier to understand and modify code.
  2. Scalability: Adapts well to new features or requirements.
  3. Reduced Bugs: Minimizes side effects when changes are made.
  4. Reusability: Code can be reused across projects.

Top comments (0)