With each principle which we are going to learn in this course, I want you to understand one specific one liner which is useful in understanding that principle actually. So, right as you can see on screen like just now, we have seen one principle which was single responsibility principle. Now, most of the time when people try to understand solid principles, they just remember the full forms of those principles. So, they remember that there is something like single responsibility principle, but they forget what exactly they have to keep in mind while writing a code. So, that's why we have this one liner for you, so that when you write a code more than the full form of the principle, I want you to remember this one liner which will help you to decide which is right and which is wrong in your code. Like for rule number one, which is single responsibility principle that one liner is your class should be focused, or it should be concerned about only single focus purpose for every class is going to be focused about single focus purpose.
Now, that's a one liner for solid Principle number one. Now it's a time for learning Principle number two, which is open close principle. Now again, the name itself is very contradictory, because we are using two different words which are opposite, open as well as closed. But I want you to remember the one liner for this rule is open for extension, but closed for modification. Now, this simply says that when you're going to write a core, your core should be in such a way that it should be open for extension. In future if I want to extend the functionality of the code, it should be open for that.
But it should be closed for modification. We know modifying the same code again, again, again, it's going to create a lot of problem for other developers. SLS in maintaining a project. That's why your course should be in such a way that it should be open for extension, but closed for modification. Now I know the moment I say this line, you guys are going to ask me the question that how is it possible that something is open for extension, but closed for modification. Now that something which is my job, you leave it on me, but to understand this rule, we need to write some code inside that application which we created in the previous video.
So let me go back to my videos to view up to this point. Inside this project, we have two classes invoice.cs and invoice printer.cs. And we are following rule number one, which is single responsibility principle. Now as you by following rule number one only, I'm adding one more class. So I'm adding a new class and assume that the purpose of this class is to check the validations of my invoice. So I'm giving a name of the class invoice validator dot CSS.
So this is going to be an invoice validator class. And as per rule number one, I am going to make sure that this class should have only one focus purpose which is checking validations. So inside this invalid class let's say I have a method with the name validate my method will date is taking one parameter of type invoice so that I can validate this specific invoice and if you check inside this the logic is very simple. I have one if condition which is checking that my subtotal should not be less than zero, if it is, is going to return false because this method returns a Boolean. Same way for the text rate also if it is less than zero, we are going to return false. If both of the things are not matched with this we are going to return true it means the validations pass successfully.
Now right now in this particular code, we are just checking validations and as per the rules, we are following single responsibility principle Which is rule number one. And in that, we are mentioning that this class is only focused about one purpose. So, we have one method with a date, which is just taking rotations inside that, but now, if we go ahead with the Rule number two or Principle number two, which is open close principle, open closed principle is trying to tell you that your core should be open for extension, but closed for modification. It means in this particular call, if I want to add one more relation in future suppose, with subtotal and tax rate, I want to add one more addition. In that case, that is something which is touted as extension. But if I want to do the extension, my course should be in such a way that it should not be modified.
So, without modifying this code we need to extend this day. Now, the question is how we are going to do this thing, and that's where I'm going to change this a little bit. But I hope you'll agree with me Look again, right now in this code there is nothing wrong from an output perspective, if I write this code and if I try to get my output properly this will check relations. But this code as per the principles is not right code because it is required to modify this code whenever I want to extend them new functionality inside this. Now, if I want to achieve my open closed principle, how am I going to achieve this thing? That's a big question.
And the answer is we are going to take a help of one of the good feature of C sharp, which is abstract class. So, to achieve open closed principle, I will take the help of abstract classes. And I'm assuming that you guys are familiar with abstract classes and interfaces. To achieve this, I'm going to right click on my application and I'm going to add a new class and I'm giving a name of this class validator. This little class is going to be public ever less abstract. So this is an abstract class.
And we know that inside the abstract class, we can have abstract as well as non abstract methods. I have a method which is public. It's going to be public abstract bool. And I'm giving a name of this method, same like my previous method, any date, which is going to have one parameter of type, invoice class, and the name of the parameter, I'm still giving invoice. Now, in our case, this is an abstract method. So we are just specifying a method here.
But we're not going to write the logic of this abstract method here. We know that this class is going to be behave like a parent, and that parent class is going to associate with the child class and then child class is going to override this method. So let's say I'm going to add a new class which is going to be a child class of this abstract class. So this new class is in white subtotal validator. Now this invoice subtotal validator is a class which will be public. And it's going to have one parent class, which is validator.
Now this validity class is an abstract class, which we are putting as a parent class. So we can just do one thing, we can override the methods of a parent class, so we have a valid date. The moment I override this method, you can see that I'm getting my method which is overridden right now, which is returning bool. And the name of this method is validate. Inside this will date, I just want to put a simple logic of my validator.cs which was associated with invalidated so because this is checking for subtotal, I'm just going to put that if my subtotal is less than zero, we're going to return false or otherwise we are going to return true Now the same logic is here and this is also following rule number one, which is single responsibility principle. So you can check that this is having only one focus purpose, as well as now this is checking only one relation which is for subtotal.
So the issue which which got created inside this invoice validator, because of this multiple he fails, he fails, it got resolved now. Now, same way like I have created invoice subtotal data, I hope you agree with me, we have to do the same thing for tax rate also. So I'm going to right click on this, and I'm going to add a new class with the name, invoice. Text tax rate validator inside this class, the core will go like this only because it's also going to take a validator class and it's going to make sure there is going to have a tax rate associated with that. So I'm quickly creating a copy and paste using this. So we have a validator which is having validate method inside this this class will be also public And in spite of subtotal, this one is going to make sure that my tax rate is not going to be less than zero.
And this is something which we are done. Now. Now, because we have added this to classes, invoice approval validator and invoice tax rate will return, I need to change the logic of my invoice related because this was the class which was having issue with the open close principle. So this was not open for extension and closed for modification. So I'm going to change the logic of individual data now. And to do that, inside this universal data, the first thing which I'm going to do is I'm going to create a constructor of this class.
So I'm just going to right click on this and I'm going to generate a constructor for invoice validator. So I got a constructor inside this and above this constructor we are going to create one collection which is going to be a private List of type validator, which is my abstract class, and I'm giving a name of my collection, which is validators. So underscore validators is the name of my private list collection. Now inside this constructor also I will set a parameter, I'm sure that you guys have done this kind of things earlier. So that is just to pass on the values in the parameter, the moment we create an instance of this class, and whatever value we have in the parameter, we are going to pass on that value into our variable, which is a private variable there. So I'm specifying that the value of this validators validators is going to be assigned to my underscore data which is a private variable.
And that's why this private variable can now use all the validations which are associated in this collection. Now after this invoice, data, I'm simply going to create one method of invoice later. And I'm giving the name of this method also validate. So I'm creating a public bool method name is going to be validate. And remember this method validate is not abstract. This is a normal method of a normal class, which is having a parameter of type invoice and I'm giving the name of the parameter also invoice because this is a non abstract method, we have to write a logic for this inside this and my logic is return underscore validators which is having all the validations inside that dot all and inside this all we are going to specify that whatever validations we have in that, we are going to specify that for all of these validators we are going to call validate method in which because it's asking for invoice parameter, passing the parameter Which is invoice.
And the moment we do this thing, this method is going to check all the relations which are associated with this collection. We know that because this collection is taking anything off I validator, my abstract class and data is associated with this too. And it's going to check both the relations inside that subtotal as well as for tax rate. Now, the moment we change the logic of this invoice with a class like this, you can just assume that in our application right now, we are going to have invoice data, which is having a collection with the tie validators, and whichever validators which are associated with this collection. We are going to check each and every validator associated with that. This means tomorrow if I want to add one more validation for another thing, like for example, if I add a new class with the name, invoice, invoice total validated If I add this invoice to related.cs class, and I make sure that this class is also going to have a parent class, which is validator, which is also abstract.
So inside this also I can override my abstract method of the class. So we are going to override validate, and very similar logic like invoice tax rate validator and all I am going to write the logic based on that inside this but this time it's not going to associate with invoice tax rate is going to check invoice dot total. And the total is something which I have to create inside this because it's coming from calculate total. So to define that invoice dot calculate total which is a method so we are calling that method and the method should not return zero or less than zero. Now the moment I do this thing, this is a new validation which I have added inside my project and even though if I Add this kind of new addition, I did not need to change a logic of my invoice will return a class.
So my class is right now open for extension, I can extend this class by adding new new relations inside that. But it is closed for modification, no matter how many validations, I'm going to add, I never need to come back to this code and I need to change this. So I never need to change this thing. That's why Rule number two or Principle number two is also satisfied, which is your code should be open for extension, but it should be closed for modification. And right now, if you follow and if you see our structure of our application, all the classes are following both the rules both the principles, as I discussed earlier with you. Most of the developers make this mistake that when they follow one rule, they break the other rule.
The goal is in the are going to create one project which will have all five rules Satisfied inside that, so we will make sure that when we are learning a new principle, we are not breaking any previous principle in that. Right now all the classes are following rule number one, which is single responsibility principle. And that's why each one is only focused on one purpose. And we are also following Rule number two, which is OCP, open closed principle. And that's why we are done with two principles right now. Thank you