SOLID Design Principles in C# with helpful examples

Introduction

Hi readers! This time, I have brought the new C# topic on ‘Solid Design
Principles in C#
’ along with some valuable examples.

Here, we will be discussing ‘C# Solid Design Principles’ along with some valuable examples that are based on various .net
applications including Web API, ASP.NET MVC, and Console Applications.

These C# design principles enable us to resolve most of the issues that are
created in software design. These C# design principles facilitate us with
different methods to shift the tightly bonded code between the software
components which gives rise to software designs more acceptable, adaptable,
and maintainable.

This article will be more helpful for beginners as well as experienced
professional developers who wish to learn more and solve errors in C# SOLID
Design Principles.

Why do we need SOLID Design Principles?

Often, the C# developers,
commence developing applications
utilizing their experience and proficiency. But over time, the applications
might need changes or improvements. Hence, we have to modify the application
design for each of the modification requirements or a new request type. The
required modifications may need a lot of effort as well as time, even for
simpler smaller tasks.

The above issues can be solved and the beginners as well as professional c#
developers who wish to learn how to develop good valuable software utilizing
SOLID Design Principles in C# within a short duration.

What do you mean by SOLID Design Principles in C#?

The C# SOLID Principles are generally utilized to control most of the software
design difficulties that are usually experienced in our day-to-day
programming. These Solid principles are furnished with some specific tools
that make the software designs more acceptable and easily maintainable.

What is the main reason behind most of the unsuccessful applications?

Find below some main reasons for the failure of many software.

  1. Applying more functionalities to some classes, even though those
    functionalities are not related to the respective classes.
  2. Enforcing Tight coupling between these classes. The changes in one of the
    interdependent classes ultimately affect other classes.

How do solve the C# application issues?

  1. A developer needs to follow the Principles of SOLID C# design.
  2. We need to use the accurate architecture (i.e. MVC, MVP, Layered, and
    3-tier, etc.) as per the project need.
  3. Again we have to select the precise Design Patterns as per the project
    provisions.

SOLID Acronym

In OOP (Object Oriented Programming), SOLID is an acronym for five crucial
C# design principles, which was introduced by Michael Feathers.

  1. S for the Single Responsibility Principle (SRP).
  2. O for the Open-Closed Principle (OSP).
  3. L for the Liskov Substitution Principle (LSP)
  4. I for the Interface Segregation Principle (ISP).
  5. D for Dependency Inversion Principle (DIP)

Let’s have a look at these 5 C# principles.

1. Single Responsibility Principle (SRP)

This principle indicates that ‘A class Needs to have only one reason to get
altered’. This definition comes from Robert C. Martin’s ‘Agile
Software Development
book which is based on the C# version along with Patterns, Principles, and
Practices.  

In layman terminology, it states that a class should not come with multiple
responsibilities as well as a single responsibility that need not be spread
across various classes or combined with other responsibilities. The reason is
that the more modifications are expected in the future, the more changes the
class has to apply.

Explanation

Single Responsibility Principle is the first principle among five SOLID
principles which enable
developers
as they write code or design an app.

In simple terms, a module or class needs to possess a very small area of
responsibility in the whole application. Or as it indicates that, a class or
module needs no more than one reason to modify.

If a class contains only a single responsibility, it will be very robust. It’s
easier to validate it’s working as per the logic explained. And it’s much
easier to alter in class as it possesses single responsibility. In this
responsibility principle, the Classes,  modules, and software components
that possess only single responsibility are much easier to elaborate,
implement and realize than the ones that provide the right solution for
everything.

This also decreases the number of bugs and increases the development speed and
most significantly reduces the work burden of developers.

Example

Let’s consider a real-time operation of a car Garage service station.
Generally, it contains 3 major functions such as open gate, close gate, and
provide service.

Working Example:

2. Open Closed Principle (OCP)

Most of the
C# software
entities like classes, functions, modules, and many more need to be open for
extension, but closed for alteration.

Bertrand Meyer in the ‘open/closed‘ principle in his popular book
Object-Oriented Software Construction

Explanation

This principle proposes that the class needs to be extended easily without
changing its core performances.

The
software/app
needs to be flexible to get altered. The way how modification management is
applied in a system has a crucial effect on the achievement of that
app/software. The OCP indicates that the aspects of the system can be expanded
without modifying its current performance.

It means, New features need to be enforced by utilizing the new code, but not
by modifying the current code. The main advantage of implementing OCP is that
it potentially simplifies code maintenance and lowers the risk of breaking the
current implementation.

Example

Let’s consider an example of bank accounts such as regular savings,
corporate,   salary savings, etc. for various customers. As for
every type of customer, with different rates of interest, and different rules,
the following code violates the principle of OCP if the bank initiates a new
type of Account. Hence, the required code changes this method to add a new
type of account.

We can incorporate OCP through the interface, abstract methods, abstract
class, and virtual methods when you wish to expand functionality. I have
utilized the interface here for example only you can proceed as per your need.

This can resolve the issue of change of class and by expanding the interface,
we can augment functionality ultimately.

Overall, the above code is enforcing both OCP and SRP principles, since each
class is performing a single task and we are not changing classes and only
performing an extension.

3. Liskov Substitution Principle (LSP)

Robert C. Martin states that functions that utilize references or pointers to
the base classes must utilize the derived class objects without having an idea
about it.

The LSP is a right definition of a subtyping association, named strong
behavioral subtyping, which was originally introduced in 1987 by Barbara
Liskov in the ‘Data abstraction and hierarchy’ conference keynote.

Explanation


LSP
states that the child classes need to be flawlessly exchangeable for their
parent class. If class C is obtained from P then C should be exchangeable for
P.

We can test through LSP whether inheritance is adequate or not in our code.


LSP
is an essential principle of C# SOLID Principles and asserts that if a
module or program is utilizing a base class then the derived class needs to
expand its base class without altering its actual performance.

Example

Let’s consider the following codes where LSP is obeyed perfectly

4. Interface Segregation Principle (ISP)

We can’t enforce any client to apply methods that it does not utilize, and the
contracts need to be broken down into thin ones.

However, the ISP was first utilized and defined by Robert C. Martin at the
time of guiding for Xerox.

ISP is employed to get the design issues of the application resolved. When the
whole tasks are accomplished by a single class or we can say, one class is
utilized in most of the
application
classes then it turns into a fat class with the extra burden.
Inheritance
of such class results in getting the sharing procedures that are not relevant
to originated classes but it’s available in the base class so that will be
able to inherit in the
originated class.

Through ISP, we can create different interfaces for each requirement or
operation rather than possessing a single class to accomplish similar work.

Example

In the following code, ISP is cracked with the following example:

5. Dependency Inversion Principle (DIP)

This principle explains the reliances among elements. The DIP is defined well
by Robert C. Martin as follows:

  • High-level modules need not depend on lower-level modules. So, both need to
    depend on abstractions.
  • Abstractions need not rely on detailed information, whereas detailed
    information needs to depend on abstractions.

Explanation

This principle states that higher-level modules need to rely on abstraction,
not on the detailed information of lower-level modules. It means a tight bond
among components of software should not be available and to skip that, the
components need to rely on abstraction.

The terms Inversion of Control (IoC) and Dependency
Injection
(DI) are commonly utilized interchangeably to explain the equivalent design
structure. The structure was called IoC in the beginning, but Martin Fowler,
the enterprise software designer anticipated the name as DI since most of the
frameworks or runtime reverse the control in some path and he was keen to know
which characteristic of control was being reversed.


IoC
is the right method to apply the DIP in the application of C#. Inversion
of control can be applied through either an interface or an abstract class.
The Dip rule states that the lower-level entities need to join the agreement
to a single interface and the higher-level entities utilize only entities that
are carrying out the interface. This procedure reduces the dependency between
the different entities.

Example

In the following code, we have enforced DIP through IoC utilizing an injection
developer. There are multiple approaches to enforcing Dependency injection.
Here, In the following example, I have utilized interface as a reference, but
anybody can utilize an abstract class or interface as per necessity.

We utilize injection through builder but you inject the reliance into the
constructor (constructor injection) of class, method (Method Injection), set
property (Setter Injection), events, fields, index properties, and practically
any members of the public class.


DI
is a software application design structure that enables us to get developed
loosely bonded code. Through DI, we could lower the tight bonding between
software elements. DI also enables us to better achievement of future
modifications and other complications in our software application. The
objective of DI is to enable code sustainability.

What are the Advantages of using SOLID Design Principles in C#?

We will have the following benefits of utilizing C#  SOLID Design
Principles.

  1. Attain the lowering in the complicatedness of the code
  2. Improve the readability, maintenance, and extensibility with lowering of
    error and incorporation Reusability
  3. Obtain Better testability and lower tight bonding.

More about advantages

While the developers are designing and developing any app/software, then you
need to assess the following points.

Flexibility and extensibility

Nowadays flexibility and extensibility are very much necessary for the
development of enterprise applications. So we need to design the application
in such a method that it needs to be flexible so that it can be modified to
work in various methods and expandable so that we can incorporate new
characteristics easily with lesser changes.

Maintainability:

Maintaining the software application is the greatest challenge for the
Industry. Day to day, the hen volume of business increases for the
organization and as the business rises you have to improve the software with
new alterations. So you have to design and develop the software in such a
manner that it could receive future modifications with the least effort and
without any single issues.

Test-Driven Development (TDD)


TDD
is one of the most crucial key characteristics when you wish to design and
develop a specific application that is large-scale level. We have to design
the software application in such a manner that we could test every individual
performance for better utility and future provision.

Parallel Development:

The Parallel Development of a software application is one of the most
significant key elements. As we realize it is not feasible to retain the whole
development team performing on a similar module at the same moment. So we need
to design the software in such a manner that multiple teams can perform on
multiple modules at a time.

Conclusion

The above 5 C# SOLID design principles are most valuable for Object Oriented
design. Most of the above principles implicated include a layer of abstraction
among classes that would differently rely on each other, thus making a loose
coupling bonding which outcomes in less rigorous and fragile code. Often, it
is recommended to keep the above solid principles in mind when writing new
code.

Leave a Reply