Exploring SOLID Principles in .NET Core Applications — part 1

Abiodun Maborukoje
3 min readSep 24, 2023

--

New to .NET Core development? Let’s delve into SOLID principles to enhance your coding skills:

1. Single Responsibility Principle (SRP): Keep it simple! Make sure each class does one thing and does it well.

2. Open-Closed Principle (OCP): Design your code so you can extend it without changing the existing code. Think about inheritance and interfaces.

3. Liskov Substitution Principle (LSP): Inherit with care! Derived classes should always be usable in place of their base classes.

4. Interface Segregation Principle (ISP): Don’t force what’s not needed! Create small, focused interfaces for specific use cases.

5. Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions. Invert the control!

Learning these principles will set a strong foundation for your coding journey. Watch this space I will be posting examples or sample code implementation of each of these principles using the C#.

Single Responsibility Principle (SRP)

The Single Responsibility Principle (SRP) is one of the SOLID principles, and it focuses on ensuring that each class has a single responsibility or reason to change.

Here’s an explanation followed by a code sample demonstrating SRP in a .NET Core application:

Explanation:
• SRP suggests that a class should have one and only one reason to change. In other words, it should have a single responsibility or task.
• When a class has multiple responsibilities, it becomes more challenging to maintain and understand. Changes in one area may inadvertently affect other areas of the class.
• By adhering to SRP, you promote a more modular and maintainable codebase, where each class focuses on a specific task or responsibility.

Code Sample:
Let’s consider a scenario where we need to model a user and send notifications to users. We’ll start with a class that violates SRP and then refactor it to follow SRP.

// Violation of SRP: User class handles both user data and notifications.

public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public string Email { get; set; }

public void RegisterUser(User user)
{
// Logic to register the user in the database
Console.WriteLine($"User '{user.Username}' registered.");
}

public void SendEmailNotification(string message)
{
// Logic to send an email notification to the user
Console.WriteLine($"Email sent to {Email}: {message}");
}
}

In the code above, the `User` class handles both user registration and sending email notifications. This violates SRP because it has two distinct responsibilities.

Now, let’s refactor the code to adhere to SRP:

// Adhering to SRP: Separate User and Notification classes.

public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}

public class NotificationService
{
public void SendEmailNotification(User user, string message)
{
// Logic to send an email notification to the user
Console.WriteLine($"Email sent to {user.Email}: {message}");
}
}

public class UserService
{
public void RegisterUser(User user)
{
// Logic to register the user in the database
Console.WriteLine($"User '{user.Username}' registered.");
}
}

In this refactored code:

- The `User` class now focuses solely on representing user data.
- The `NotificationService` class handles sending email notifications, isolating that responsibility.
- The `UserService` class handles user registration, providing a clear separation of concerns.

By adhering to the Single Responsibility Principle, we’ve improved the maintainability of the code by separating distinct responsibilities into their respective classes. This makes it easier to modify and extend the code without affecting unrelated parts.

Click here for Part — 2

--

--

Abiodun Maborukoje

A seasoned Software Engineer with years of experience specializing in crafting advanced software solutions.