SOLID principles in .NET and C# | Fiodar Sazanavets | Skillshare

Playback Speed

  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

SOLID principles in .NET and C#

teacher avatar Fiodar Sazanavets

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

6 Lessons (34m)
    • 1. SOLID intro

    • 2. Single responsibility principle

    • 3. Open closed principle

    • 4. Liskov substitution principle

    • 5. Interface segregation principle

    • 6. Dependency inversion principle

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.





About This Class

SOLID principles are the most fundamental principles of object oriented programming that are absolutely essential to make your code clean, readable and maintainable. In this class, we will go through each of these principles and apply it in C# code in a .NET console application.

Meet Your Teacher

Senior software developer specializing in .NET with several years of experience

See full profile

Class Ratings

Expectations Met?
  • Exceeded!
  • Yes
  • Somewhat
  • Not really
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.


1. SOLID intro: Hello. Looking to my channel, My name is Fielder, says Ana, but Ana Messina does not develop. This video is part of a serious about solid principles and how to implement them in c sharp dot net. So its principles. It's something that every object oriented program absolutely needs to know. And in these videos, I will show you how to implement them in dot, net and see shop. For those of you who don't know what solid principles are solid is an acronym. It stands for a single responsibility principle. Open closed principle. Let's cough substitution principle interface Segregation principle, Aunt dependency inversion principle. 2. Single responsibility principle: in this video, we'll go through single responsibility principle. I will show you an example of its usage in a program that reads Content of specified file Applies be Hey, Schimmel talks toe issueless paragraphs and saved the output in a separate HTML file. At the beginning, we started with just a single program class. I want entire logic is in this class As soon as we launch our program, we asking for the operator to specify that path the rain profile with them to read the file content. We do it here. After all, it's by using rejects. We're splitting the content of the file into separate paragraphs, our input paragraphs, just a collection of strings. After that, we're going through each individual paragraph on the plane opening. I'm closing tax to it. After that were placed in break element of the end, and then we're saving the content of the file. You turn your HTML file with the same name as the original file. So as you can see it, there are quite a few things going on in a single class. In our case, we can get away with it because our class is fairly small. However, in a real life situation. This would be totally unacceptable. If we ever have to change part of the logic, we will have to change the entire class. This is why we need to separate our class into separate classes, each 100 particular part of the logic. In our case, we can separate text processing logic from file processing logic. So we will start by creating a new class and we'll call it Filed processor to make a start. We'll move riddle text on right to file into this new class because full file path is being used as a parameter in both of them. We can just make it a class variable and this is how we get rid off redundant parameters. Aunt Redundant uses statements. Now we're going to create a separate class on a little color text processor. File processor will be a glass variable of it well out to the method. Without the return type, I will call it convert text. This matters will contain all the text person logic. Full file path will become its parameter on all responsibility for reading content of the file and save the new files will be passed on to file process of variable. - So now we have a separate class of process and files on the separate class for processing text . So now we will bring it all together, you know, program class. So this is our finished product. Whenever we need to make any changes to our final processing capabilities, we only make them in the final processor and nowhere else on Same applies to text processing logic, text process. A class is the only place where we need to make any changes. Therefore, I was soft restructured, similar to a car engine in a car engine. Every single component is self contained. However, all the components brought together former one working unit. In our case, it was very easy to determine what responsibility each glass should have because we were doing on the two distinct things processing text on the process and files. However, in real life scenario, it's not always as easy to determine single responsibility for each class. And this is where the concept of class cohesion plays its part. If certain class variables only every used in some methods but not the others, then the class is known to have low class cohesion. However, whenever class variable is used in, every method of the class isn't the class is known to have the maximum class cohesion. In our case, our text processor class has the marks in a classic occasion because it has only a single public method which uses the entire logic on all class variables of the same applies to file processor. In this case, we have only a single glass variable full file path which is used in both of our class methods. What we have before we reflected our cold into separate classes was known as good object. Gold object is exactly opposite to single responsibility principle. Just like God, it is almighty. It does everything possible. It has many responsibilities. Having good objects in your cold is a really bad approach on at the beginning of this video , I have already stated some dangers off it. If you have to change just a small part of the logic, you will have to change the entire class. This is how you may introduce. There's when you are using single responsibility principle. Each individual class has always had been tested multiple times, so chances are if you are at any point going to introduce there's You will only ever introduced the Heiress into the class that you're changing on nothing else in the system. But single responsibility principle doesn't only apply to classes. It applies to Memphis to this is, for example, why in file processor, we have a separate method for regional the text from file on a separate methods for right and text into al profile. And this is it for today. You know, in future videos, we will cover the rest of solid principles. So happy cordon and keep your cold clean. And if you want to see more educational contact related to programming, don't forget to subscribe. 3. Open closed principle: in this lesson, we will talk about the second source principle Open closed principle In the previous lesson when we were looking at single responsibility principle, we ended up with the following solution. We have a classical text processor which has the only responsibility off converting text from one form to another. We also have a file process, a class which on the responsibilities to res files and survived the output of formal program. It's a new files and we also have a class called program which acts as an entry points to a program. This glass forces the other two glasses to work and produce the result, and so the next principle that we will be talking about it's called open closed principle on this principle states that every class should the close for modification but open for extension. If we have a look at our text processor class, then we'll see that it does not follow this principle. Right now, the only thing that we are doing in this class is really the text on applying caged animal paragraph tugs to every single part of. But what if we receive new requirements and we'll have to apply additional changes to all program, so it will be able to recognize markdown tags. I'm converted them into a correspondent. Hey, HTML tags, Markdown or M D is a textual four month that is very frequently used to ride recommendation . For example, Get Hub. Use it extensively as a documentation for month for its repositories. And here are some examples off mark down tags. So this one's if we come back to our text process, a class that will see that is completely closed. And to have this new functionality, we need to completely change it. This is precisely why our current solution does not adhere to open close principle. This is why we changed our called based on the existing cold. This is where this, for example, the first thing that we did is remove dependency on the final process of class from inside of the text process of class. Onley do. Now it's sends in pre prepared texting into convert text method. Other than that, we haven't changed the logic in any way. We are reading the paragraphs and we're applying, opening and closing part of tax to every single paragraph, but this time to enable us to extend the functionality we have out of these keyword virtual . And so by using object oriented inheritance, we have created a new class, and we called it M D text processor on to stand shaped. MZ takes protester class. We're passing a dictionary insert where M D tug is the key on opening and closing HTML tags of the values over here where it isn't all the right keywords, which means that we can add functionality to the existent class from the base class on in this place where using convert sex from the base class the same way as we've been using it before. And so this variable already contains the text where each paragraph is already surrounded by opening and closing paragraph HTML. Tags I've done were just returning the output text, but afterwards we are going further. We go through every single key off our dictionary, every single MD element, and then we're replacing the currencies of this element to correspond in opening and closing. Hey, HTML tags. First, we're making sure that this tax hooker, in text as an even number on afterwards, were replaced in MD tags to Casey mealtimes. Whether they're closing opening tugs depends on their position. Now this is what our program closet became final processor text process and not work separately, and we can configure the dictionary. Foreign detects processor as we want. The main reasons he used open close principle is to make sure that you're changing as little cold. It's possible if requirements change. We made this dictionary configurable for exactly the same reason. For example, our client may want to ask some CSS quests into this elements. This is why we separated consideration from the cold that is using it. Open. Closed principle was invented in the 19 eighties when the process of development on deploying the cold was expensive, so it was really relevant about then to make sure that the cause changes as rarely as possible. Off course, we live in a different day and age of these days. Requirements change really frequently, but still, even these days, reason cold in such a way that you don't have to change its frequently will help us to keep our cold clean. I will also help us to prevent introducing bugs into it. For example, if you have already written unit tests covering existing classes, you won't have to change here. This This is why it's important to write code in such a way that it's lost for modifications but is open for extension not to do so. You will need to develop inability to foresee in what way requirements amore slightly to change off course. It's not always possible to foresee that, and this is why it will not always be possible. So adhere to this principle 100%. After all, principle is not the same thing as the law. But in any case, you will save yourself from major headache if you try to write cold in such a way. But they're not here, so this principle most of the time. 4. Liskov substitution principle: Today we will talk about Liska substitution principle. This principle states that if you substitute ablaze, glass with a Klausner inherits from it. The behavior of the Memphis inside the blaze class should not be changed by the inheritors class. In any object oriented programming language, this is a very important principle because any variable off a base class type can be set. So any instance off any inherited class and now I will show you the importance of it by showing you a concrete example. In our previous video about open close principle, we have ended up with a solution that converts text from MD four months, two html. The first thing that we are doing to achieve that is converting text with a class called text processor, although this class does exposing the text into paragraphs on applying P tax opening and closing once to each paragraph. We also have the following Class M D text processor, which inherits from text processor. It does exactly the same thing, but after us it also converts certain empty specific tags to HTML equivalent tags. We have a dictionary that takes MD tired as a key and as a value has a couple, which has opening his team of tug of closing HTML tag. First thing that we do is count occurrences off each dictionary key on afterwards. Every order occurs is replaced with opening HTML tag, and every even parents is replaced with clothes and html tug. And we only do this conversion if an even number of occurrences is found in the first place . This is where we're replacing the tugs in our case, this particular class that here's well to open close principle because you can have new functionality to text processor class without modifying anything in text processor. However, in our case, this class does not adhere to a risk of substitution principle, and now I will explain the problem that may occur because of it. If you have a variable that takes the type of text processor, we can place an instance off empty text processor into that variable. I'm because both of the types have might have called convert text. We may end up with a different value, coming out of convert text than expected. For example, if a particular Coleman system was not expecting any replacement off MD specific tabs and was on the expectant inversion of paragraphs into HTML paragraphs. Then what that system would get may know this something that the system was have expected. These can be demonstrated quite well. With help off unit tests. For example, we may have the following test. The in protest of this test contains some empty specific characters that are present in the dictionary. The variable that we're applying the test to is of the type text processor the base type. Because of this, we are not expecting this singles to be converted. However, if we place empty text processing to this variable than our test will fail exactly as we expected. This is because some additional processing was applied to the text. Which system was not expected in our case is just a test, but in a real life scenario, it might be part of the working system that caused this method. Because of this, we have changed our logic. Our text processor class has not changed at all. However, you know empty text processor class, there's a new method and not what were inherited from text processor. We're not changing its convert text method. Instead, we have created a brand new methods called convert M D text convert text is not mentioned in our class at all and this means that this method is still accessible to us. But its behavior is not changed in any way at all. Our test has not changed at all, but if we run it now, our test will pass successfully. I'm now let's summarize importance off list of substitution principle. This principle is needed so you don't unintentionally introduced bugs into your system. So the behavior that your system receives its still 100% that behavior it expects. 5. Interface segregation principle: Today we will talk about interface segregation principle. In all all previous videos, we have been using classes without interfaces, but in a real life situation, your classes will probably be implemented interfaces, which will show your classes which methods and properties the classes should implement of the application that we are building. Read some texts from a file, apply some case TML process into it on saves it in a separate HTML file. And our application consists of three main parts fire processor that reads Text from files on rice. Text into files Text processor, which splits text into separate paragraphs on applies opening and closing. HTML talks to each paragraph on M D text processor, which, besides this, apply some additional MD specific conversion. Converse in detox. It's a correspondent. HTML tags and the text processor inherits from text processor close, and so we create interface For every single one of this part, I'll file process. A class will be implemented. This interface I have filed processor, which tells our class that it's just have a matter to read old text that returns a string and right to file, which takes string as an input parameter. It's very simple in this case, but it's not as simple. With M de text processor, class and D text processor contains two months convert M D text, which was introduced in this class. I'm convert text, which comes from the base class text processor that empty text processing inherits from on . We can just place those to Mrs into an interface that empty text processor will be implemented. It seems that his works, But if we open text processor, then we'll see that we have a problem. It's a method called to converse. Empty text is not contained within text processor. I'm the only thing we can do. In this case, it's create an empty method. And so we have a method that will never, ever be used, which isn't right at all. And now we'll have a look how to solve this problem in an object oriented language you can not just inherits from classes you can inherit from interfaces to I'm. Because of this, we have created interface called I Am See Text processor. Because of this in our I text processing interface, there's no only one method. Our M D text processor class implements I am detects processing interface while text processor class implements I text processor interface and now we'll summarize what we have learned. Interface segregation principle is needed so none of your classes will have any methods that those classes will never use. This principle is strong looming towards the single responsibility principle. In some situations without interface segregation principle, the single responsibility principle is impossible to implement. 6. Dependency inversion principle: In today's video, we will talk about dependency inversion principle. So in our previous videos, we have created an application that Reese text from a specified file converted into HTML format from Andy Format and then saved it in separate HTML file. We have a file process of class which implements I file processing to face. This class reads text from a file on right sex into a file. Also, we have text processor class which implements I text processor interface This class, please the input text into separate paragraphs that applies opening and closing his thermal part of tags to each paragraph. And also we have empty text processing class which inherits from text process a class on implements. I am the text processing interface. This class, with help of a dictionary, looks for various MD specific tax and convince them into HTML opening and closing tugs. Until now, all of these classes were launched from the entry point of the program, the program class, but now we have created a new class text conversion coordinator which coordinates all the work between the classes. This class contains only a single method convert text which returns conversion status object file process and empty text processor. Our low level dependence is for this class on this logic kind of works, but in this case, it's next to impossible to write unit tests for this method. If we have a look inside file, process that class, then we'll see that this class Reza content off a really file from a real file system and save the content into real file unit tests must be tested only a single method and nothing else. But in our case, if we're right unit test for this method, instead of just test in the cold inside of this method, we will also be tested where the files are properly read on written into. First of all, it's a different type of test and secondly, so even launch this test. We have to have a properly configured file system, but unit tests are not supposed to depend on file system and folder structure. Plus, if we have a look inside of the logical this method, then we'll realize that this matter itself doesn't even care how exactly files the read on how the Texas converted. All that our method is concerned about is that text is successfully read from the file and that the text is changed after we have converted it. And to achieve all of this, all that we need to know. It's what the Memphis on the dependence is look like what they signatures are. This is precisely why we will change classes in our dependencies to interfaces. In this case, we can still use any classes that implement those interfaces as promises. But now we can easily right unit tests for our method. In our case, where use an ex unit on the mark framework. We're turning our interfaces into temporary implementations and we're telling our implementations what kind of data they should return. So we contest every single scenario we can think off. For example, we can check what status this method will return if the text that we read from the file is different from process text. Likewise, we can check if the status is correct. If the system hasn't detected any changes between input, text and output text. Likewise, we can check whether our system is working correctly, if any off our dependence and methods is throwing an exception. But the ability to write units s is not the only reason why I should be using pendency inversion principle. For example, in our case, when we really implements and I file processing to face, we're working with a file system, but likewise we can create a different class. This class will contain the identical methods. But in this case, it will be working with files on a cloud storage. After all, it doesn't make any difference at all. Total coordinator class What is the in protects come from and what does it go after us?