SOLID Principles

Applying S.O.L.I.D. Principles in .NET/C#

Applying S.O.L.I.D. Principles in .NET/C#

S - SRP - Single responsibility principle (a class should have only a single responsibility (i.e. changes to only one part of the software’s specification should be able to affect the specification of the class))

There can be only one requirement that, when changed, will cause a class to change…

More detailed:

When we build a class, we look at all the requirements for our systems,

or all the requirements that affect that class,

and we build in such a way that only one of those requirements will cause ever one class to have to change.

Nouns are classes, verbs are their functions and adjectives are their properties.

We might need to turn verbs/functions to classes as well,

As soon as we pull different small functions turned them into classes,
We get a class responsible for one thing and it can only change if only one requirement changes,

It makes a whole lot easier to change the way of our application works, because we can switch out functionality without have to modify classes but changing the class do the functionality.

put different functions into different classes.

Benefits

I can switch out components and up other components. Components are really really small.
Simply to read, simply to use, simple to understand.

O - OCP - Open/closed principle (software entities … should be open for extension, but closed for modification.)

“Software entities should be open for extension, but closed for modification.”

Once a class is done, it is done! You do not modify it.

More detailed:

A changing requirement/Once a requirement changes, you do not modify your class, you do not go in and make changes in your existing class.
You creates a new class inheriting from the old class, make changes in the new class instead.

Best part of it:

No changes for the unit tests since new class has been created, and new tests have been adding to the new class instead of changing unit tests for old class.

Meyer vs. Polymorphic

Meyer: You build a class put into your system. You build another class which inheritanced from the pervious class then put into your system.

Polymorphic: Not nessersaily have to inherited from a specfic implementation, inheriting from abstract base classes or could be implemented in a interface.

Three ways of doing OCP

  1. Inheriting the exising class, Overridding the existing class function.
  2. Inheriting Abstract class
  3. Implementing the existing interface.

Benfits

You dont change your code. No need to rework on existing unit tests.

L - LSP - Liskovs Substitution Principle (objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program)

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

More detailed:

A subclass should behave in such a way that it will not cause problems when used instead of the superclass.

Rules:

1. Contravariance(n.反[抗,逆]变性,逆[抗]变; 抗变性) of method arguments in sub class

if I have a class, I create a new class that inherits from that player class, I am allowed to change the input arguments term to my method in such a way that they accept a base class of the arguments that my base class accepted it

I am allowed to change the input parameters in such a way that any parameters that has ever been passed in to the parent type can be passed into the new type suite

if I have a class, then I create a new class that inherits from the old class, I am allowed to change the input arguments to my method in such a way that they accepts a base class of the arguments that my base class accepted.

TL;DR
I am allowed to change the input parameters in such a way that any parameters that has ever been passed into the parent type can be passed into the new type.

2. Covariance( n.协方差;变异数;协变性;共变性) of return types in the sub class.

the return of my class, the return value of my method is allowed to be any type that is a the same as the parent or a descendant class

I’m allowed to in return anything as long as it it’s at some point inherits from whatever the base class returned

The return value of my method in my class is allowed be any type is the same as the parent or a discendent class.

TL;DR
I am allowed to return anything as long as it somepoint inherits from whatever my base class returns.

3. No new exceptions types are allowed to be thrown, unless they are sub classes of previously used ones.

TL;DR
In your new classes, you are not allowed to introduce new exceptions.

Why?

If you introduced new exceptions, whatever code has been using in other class you base class, might be prepared to handle whatever exception that class is throwing.

If you introducing new ones, your application might be broken.

4. Preconditions cannot be strengthened in a subtype.

you cannot be expecting things that wasn’t expected in the base class.

I cannot make changes that that you’re only allowed to call this method if this property is set to this value if the base class hasn’t had that that’s limitation before

so you’re not allowed to introduce things that might cause once again any class using the base class cannot break because you’ve introduced new features or new limitations.

You can not define limitation in subclass which the base class hasnt that limitation before.

You are not allowed to introduce things that might cause any class that uses the base class cant not break because you introduces new feature or new limition.

5. Postconditions cannot be weakened in a subtype.

I’m not allowed to change the class in such a way that you cannot do things you could do before

so I can’t start throwing not implemented exception or say you’re not allowed to do this or that or whatever

because once again if I introduce a change like that code that was using the base class cannot use the new type and might actually fail.

I am not allowed to change the class in such a way that you can not do things you could do before.

I cant start throwing “not implemented exception” or you are not allowed to do this or that.

6. The history constraint(n.强制; 限制; 约束)

More Detailed:
You can not make an immutable class mutable.

You have a class that can not be changed, you have a property of the class that can not be changed in the base class.
You are not allow to change that class in such a way that you can change the value in your new class.

Because any type or any class are using the base class might be excepting that the value can not be changed.
If you introduced the possibility to changing it, you might break things.

The general guide:

You are not allowed to change a class in a way that it can break any the existing applications.

The rules to define what could break the existing application.

You should most likely to be possible to take your new class and throw it in and run it through all of your existing unit tests. And they should fail in the way that they break down.

Benfits

create new versions of classess
that will actually be able to plug in and replace the existing implementations without you breaking existing applications

I - ISP - Interface segregation principle

“Clients should not be forced to depend upon interfaces that they don’t use.”

Benfits

Breaking down interfaces in smaller pieces make them easier to implement, and offers more control over who sees what.

you get really small tiny pieces easy to implement easy to switch out it

you can have tiny little interfaces

you can have your class implement ten of them if you wanted that’s not a big problem

but the guy needing the functionality can ask for a little bit a little bitty piece of it he doesn’t need to have the whole thing.

D - DIP - Dependency inversion principle

one should “Depend upon Abstractions. Do not depend upon concretions.”

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

B. Abstractions should not depend on details. Details should depend on abstractions.tags: [S.O.L.I.D, Object-oriented Programmming]

Without DIP

DIPwithout

With DIP
DIPwith

With DIP Alternative
DIPwith