Solid Principles Full Tutorial In C# - Interview Answers - Design Patterns In .NET - Coding Examples #318
FurkanGozukara
announced in
Tutorials
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Solid Principles Full Tutorial In C# - Interview Answers - Design Patterns In .NET - Coding Examples
Full tutorial: https://www.youtube.com/watch?v=034zM9MQdkU
In this lecture video I am explaining what are solid design principles. I am composing a .NET Core 7 WPF project to demonstrate each one of the principles of the solid design in C-Sharp programming language. I believe that the best methodology for learning something is doing an actual programming example. Therefore, we will make examples together.
SOLID is acronym of:
S - SRP - Single responsibility principle
O - OCP - Open/closed principle
L - LSP - Liskov substitution principle
I - ISP - Interface segregation principle
D - DIP - Dependency inversion principle
Foreach principle, I am composing 2 classes that shows violation and correct approach.
The source code of the lecture is available on : 🔗 https://github.com/FurkanGozukara/Solid-Principles-Full-Tutorial-In-C-Interview-Answers-Design-Patterns-In-.NET-Coding-Examples
The subtitles of the video is manually corrected so please watch with subtitles.
Please join Our Discord server for asking questions and have discussions: 🔗 https://discord.gg/rfttctFewW
Please follow us on Twitter: 🔗 https://twitter.com/SECourses
Please follow us on Facebook: 🔗 https://www.facebook.com/OfficialSECourses
If you are interested in programming our playlists will teach you how to program and code from scratch: 🔗 https://www.youtube.com/c/SECourses/playlists
[1] Introduction to Programming Full Course with C# playlist
[2] Advanced Programming with C# Full Course Playlist
[3] Object Oriented Programming Full Course with C# playlist
[4] Asp #NETCore V5 - MVC Pattern - Bootstrap V5 - Responsive Web Programming with C# Full Course Playlist
[5] Artificial Intelligence (AI) and Machine Learning (ML) Full Course with C# Examples playlist
[6] Software Engineering Full Course playlist
[7] Security of Information Systems Full Course playlist
Video Transcription
00:00:00 Hello everyone. I am Dr. Furkan Gözükara. Today I am going to explain to you what are
00:00:06 solid design principles. I will compose a .NET Core 7 WPF project to demonstrate each one of
00:00:12 the principles of the solid design in C-Sharp programming language. I believe that the best
00:00:18 methodology for learning something is doing an actual programming example. The code written
00:00:22 in this lecture will be uploaded to our public GitHub repository so that you can download and
00:00:27 use it yourself. I will put the link of the repository in the description of the video.
00:00:33 So let's start with composing our WPF project. You see I have clicked create a new project in
00:00:40 Visual Studio Community Edition and I have filtered the result with WPF.
00:00:46 There are two versions of WPF. The first one is WPF application which is .NET Core and
00:00:53 there is also another version which is WPF of .NET Framework. .NET Framework is the older one and it
00:00:59 is not updated anymore. So be careful with that. I am picking the WPF application with .NET Core
00:01:09 and let's pick our folder name as solid design principles.
00:01:19 I will pick the .NET 7 standard term support. Okay, so our application is starting. So
00:01:26 let's quickly review and understand what are the solid design principles and why do we need them.
00:01:37 Okay. Why do we need solid design principles? As a developer, we start developing applications
00:01:46 using our experience and knowledge. But over time, the applications might arise bugs.
00:01:53 We need to alter the application design for every change request or for a new feature request.
00:01:59 After some time we might need to put a lot of effort, even for simple tasks, it might require
00:02:04 the full working knowledge of the entire system. But we can't blame change or new feature requests
00:02:11 as they are part of the software development. We can't stop them and refuse them either.
00:02:17 So who is the culprit here? Obviously, it is the design of the application.
00:02:23 Okay, this is so true. I have 13 years of software development experience and I assure you that you
00:02:30 will have to fix and improve so many parts of your application after its initial release.
00:02:39 You will encounter bugs and you will and you will get a new feature request.
00:02:44 So if you design your application with following the state of art principles, then you will have
00:02:55 less problems. Okay, this is why solid design principles is really important in application
00:03:03 development. So let's continue reading. Advantages of solid design principles in C#.
00:03:12 As a developer, while you are designing and developing any software applications,
00:03:17 then you need to consider the following points. Maintainability. Nowadays,
00:03:23 maintaining the software is the biggest challenge for the industry. Day by day, the business grows
00:03:29 for the organization and as the business grows, you need to enhance the software with new changes.
00:03:35 So you need to design the software in such a way that it should accept future changes with minimum
00:03:40 effort and without any problem. Okay, I am pretty sure that you have already noticed this in the
00:03:48 applications that you use in your real life. You see that your applications always gets new updates
00:03:55 and gets new features. So this is something that you can't avoid in your software development life.
00:04:07 Testability. Test-driven development TDD is one of the most important key aspects
00:04:14 nowadays when you need to design and develop a large-scale application. We need to design the
00:04:20 application in such a way that we should test each individual functionalities. Okay, this is
00:04:25 another thing in the nowadays programming trends that your code has to be automatically testable.
00:04:35 This is also mandatory in continuous development and continuous integration scheme
00:04:42 following application development. Okay.
00:04:50 Flexibility and Extensibility.
00:04:54 Nowadays, flexibility and extensibility both are very much required for enterprise applications.
00:05:01 So we should design the application in such a way that it should be flexible so that it
00:05:05 can be adapted to work in different ways and extensible so that we can add new features
00:05:10 easily with minimum modifications. Okay, this is also another important thing and
00:05:15 when we follow correct design principles, we won't have a hard time to achieve this.
00:05:24 Parallel Development. The parallel development of an application is one of the most important
00:05:31 key aspects. As we know, it is not possible to have the entire development team will work
00:05:36 on the same module at the same time. So we need to design the software in such a
00:05:42 way that different teams can work on different modules. The solid design principles and design
00:05:48 patterns play an important role in achieving all of the above key points. All right.
00:05:58 The solid design principles in C# are the design principles that basically used to manage most of
00:06:04 the software design problems that generally we encountered in our day-to-day programming.
00:06:09 These design principles are provided with some mechanism that will make the software designs
00:06:14 more understandable, flexible and maintainable. What is the main reason behind most of the
00:06:21 unsuccessful applications? The following are the main reasons for most of the software failures.
00:06:28 Putting more functionalities on classes. In the simple word a lot of functionalities we
00:06:34 are putting into the class even though they are not related to the class.
00:06:39 Implementing tight coupling between the classes. If the classes are dependent on each other,
00:06:45 then a change in one class will affect the other classes also.
00:06:49 How to overcome the unsuccessful application development problem? We need to use the correct
00:06:56 architecture, (i.e. MVC, Layered, 3-tier, MVP, and so on) as per the project requirements.
00:07:05 As a developer, we need to follow the design principles, i.e. solid principles.
00:07:11 Again, we need to choose the correct design patterns as per the project requirements.
00:07:17 Introduction to solid design principles in C-sharp. The solid design principles are
00:07:24 basically used to manage most of the software design problems that generally as a developer
00:07:28 we face in our day-to-day programming. Solid principles represent five design principles
00:07:34 that basically used to make the software designs more understandable, flexible, and maintainable.
00:07:41 Solid acronym: Okay, this is important. Usually, nowadays, in the job interviews,
00:07:48 they are asking you what does solid mean. They are asking you to explain each one of these
00:07:55 design principles. I have been asked actually. And so let's try to memorize and understand them.
00:08:05 S stands for the single responsibility principle, which is also known as SRP. Okay,
00:08:10 don't worry that I will explain each one of these principles with details.
00:08:18 O stands for the open-closed principle, which is also known as OSP.
00:08:24 L stands for the Liskov substitution principle, which is also known as LSP.
00:08:30 I stand for the interface segregation principle, which is also known as ISP.
00:08:36 D stands for dependency inversion principle, which is also known as DIP.
00:08:42 What are the advantages of using solid design principles in C-sharp?
00:08:47 We will get the following advantages of using solid design principles in C-sharp. Achieve the
00:08:54 reduction in complexity of the code. Increase readability, extensibility, and maintenance.
00:09:02 Reduce error and implement reusability. Achieve better testability. Reduce tight coupling. Okay,
00:09:11 so actually we can say that each one of these is matching these ones. The first
00:09:18 one achieves reduction in complexity of the code with single responsibility, because each
00:09:23 class is responsible for only one thing. Okay, one job, and it reduces complexity. You see,
00:09:31 open-closed principle increases readability, extensibility, and maintenance, because our
00:09:39 code will be closed to modify, but it will be open to extend, and with Liskov substitution
00:09:49 principle, we will reduce error and implement reusability. It will allow us to reuse our code
00:09:55 as much as possible with easiness, and with interface segregation principle, we will achieve
00:10:01 better testability, and with dependency inversion principle, we will reduce tight coupling. Okay,
00:10:09 so let's start programming with single responsibility principle.
00:10:15 Okay, so let's quickly read what does it do, what is the meaning of it.
00:10:24 What is the single responsibility principle in C#? The single responsibility principle
00:10:31 in C# states that each software module or class should have only one reason to change.
00:10:37 In other words, we can say that each module or class should have only one responsibility to do.
00:10:44 So we need to design the software in such a way that everything in a class or module should be
00:10:49 related to a single responsibility. That does not mean your class should contain only one method or
00:10:56 property, you can have multiple members, methods, or properties, as long as they are related to a
00:11:01 single responsibility or functionality. So with the help of SRP in C-sharp, the classes become
00:11:09 smaller and cleaner and thus easier to maintain. Okay, so you see why it is becoming easier to
00:11:15 maintain. So let's start with coding. The first example is the opposite of single responsibility.
00:11:22 Assume that we have invoice class. Let's start implementing it. All right. Okay,
00:11:32 so the first example will be an example that violates single responsibility principle.
00:11:48 Okay. By the way, I have written this correctly, I think. Okay, let's
00:11:58 make it like this. Okay, example that violates single responsibility. Okay.
00:12:13 All right. So let's add a class. I'm going to add single responsibility violation class.
00:12:31 And I will copy-paste the code here. All right.
00:12:42 Okay, so what do we have? Let's analyze it. We have a class invoice. It has a
00:12:51 long invoice amount. We have daytime invoice date. They are, as you can see, attributes.
00:13:03 Okay, and we have add invoice method. You see it in add invoice method. We are also sending
00:13:11 an email. Okay. And if if an error happens, we are also logging the error. So this method
00:13:19 actually doing three separate things. With direct implementation, we have delete invoice method.
00:13:38 Which also logs, as you can see here, and we have send invoice email. All right.
00:13:51 And okay. Okay, so with this way, we are violating our principle. Why? Because we are doing three
00:14:07 separate things in a single class like this. Okay, let me show single responsibility violation. Okay.
00:14:17 And
00:14:25 here we are just calling. Okay, these are not public or. Okay. We need to generate.
00:14:44 One second. Okay, we don't need actually this.
00:14:53 Like this. Violated invoice or let's say incorrect invoice.
00:15:06 And incorrect invoice. Add invoice. Okay, like this. So this usage is not the correct way. Okay.
00:15:16 How then if it is incorrect, then how can we fix this? To fix this, we need to separate the tasks
00:15:26 that each the task here inside here into different classes. Okay, so first let's start adding with
00:15:38 a logger system. That login logger class will handle the logging if an error happens. Okay.
00:15:46 So to adding the logger system, I will just copy and paste this. You see,
00:15:52 all of these can be inside the parent class, but they will have different subclasses names.
00:15:59 So we are separating the concern. I mean, they can be inside this same CS file. Or you could
00:16:06 also do you could also insert different CS files as well. Maybe we should add
00:16:15 different CS files so it will be easier to manage. So let's add a logger CS file. Okay,
00:16:25 in parent class logger, so I will just change it.
00:16:33 Like this. Okay, so we have an interface and with interface we define which methods this inheriting
00:16:43 class or yes, inheriting class should have. So we have a logger class that uses interface iLogger
00:16:51 and inside we are constructing the methods. We have constructor, we have info method,
00:16:58 we have debug method and we have error method. You can fill anything inside here. The purpose of this
00:17:05 lecture to demonstrate how to do proper solid design principles following programming. So we
00:17:14 also need to now modify our code. Oh, we also need to add another class for mail messaging. Okay.
00:17:26 So let's add a mail sender class.
00:17:34 All right, let's name it as mail sender. And inside here, make it as
00:17:44 public class mail sender. You see mail sender has only one purpose and it is send email.
00:17:50 All right. Okay, now finally we can modify our invoice class properly to be following solid
00:18:00 design principles. And for that, okay, let's add another button. You know, you can fill
00:18:09 anything inside these methods. Okay, and let's call it as proper single responsibility. Okay.
00:18:30 All right, so I am going to add another class and I will say proper invoice.
00:18:37 Okay, let's name it as proper invoice.
00:18:43 Okay, we can leave it as internal as well for the demo and let's copy and paste code.
00:18:52 Okay, so I also need to change the constructor name. All right. So what is the difference in
00:19:03 this case? In this case, you see, we have a logger and mail sender as injection dependency injection.
00:19:17 Actually, not this. Okay. And then we use those initialized objects
00:19:25 to add info or send email. Okay, you see, if an error occurs, then we are
00:19:37 using the error method like here. All right. And why does it show error?
00:19:47 Okay, because I need to send it like this. And in the other case, we also modify it like this.
00:19:57 You see, instead of sending email directly inside in the first case.
00:20:03 In the violation method. In the violation method methodology, we were sending mail directly like
00:20:11 this. The code was also written in the same class and we were also logging the errors like
00:20:17 this. However, now we have separate classes for each task. We have mail sender class and we have
00:20:25 file logger. Okay. And now we can use each one of them. So if we change anything in these separate
00:20:36 classes that it won't affect anything in our application workflow runtime. This is a single
00:20:48 responsibility principle. And let's see if the author of this article said anything.
00:20:58 Okay. As you can see, the invoice class delegating the logging activity to the logger class.
00:21:07 In the same way, delegate the email sending activity to the mail sender class.
00:21:13 Now the invoice class now only concentrates on invoice related activities.
00:21:18 All right, now we can move to the next principle, which is open-closed principle.
00:21:30 What is the open-closed principle in C-sharp?
00:21:35 The open-closed principle states that software entities such as modules, classes, functions,
00:21:41 etc. should be open for extension, but closed for modification.
00:21:46 Let us understand the above definition in simple words. Here we need to understand two things.
00:21:53 The first thing is open for extension and the second thing is closed for modification.
00:21:59 The open for extension means we need to design the software modules / classes in such a way
00:22:05 that the new responsibilities or functionalities should be added easily when new requirements come.
00:22:11 On the other hand, closed for modification means we should not modify the class / module until we
00:22:17 find some bugs. The reason for this is we have already developed a class / module and it has
00:22:24 gone through the unit testing phase. So we should not have to change this as it affects
00:22:29 the existing functionalities. In simple words, we can say that we should develop one module / class
00:22:36 in such a way that it should allow its behavior to be extended without altering its source code.
00:22:46 Implementation guidelines for the open-closed principle, OCP, in C-sharp. The easiest way
00:22:54 to implement the open-closed principle in C-sharp is to add the new functionalities
00:22:59 by creating new derived classes which should be inherited from the original base class.
00:23:05 Another way is to allow the client to access the original class with an abstract interface.
00:23:13 So, at any given point of time when there is a change in requirement or any new requirement
00:23:18 comes then instead of touching the existing functionality, it's always better and suggested
00:23:22 to create new derived classes and leave the original class implementation as it is. Okay,
00:23:28 so this is the key issue, the key point. Whenever you need a new functionality, then you shouldn't
00:23:36 change the existing implementation. You should extend it and then implement that new feature with
00:23:45 that extension. Okay, this is really important, the key part of the open-closed principle.
00:23:53 By the way, in an interview I was asked what is open-closed principle and I was asked to explain
00:24:00 it, so this is really important. Problems of not following the open-closed principle in C-sharp.
00:24:08 If you are not following the open-closed principle during the application development process,
00:24:13 then you may end up your application development with the following problems. If you allow a class
00:24:20 or function to add new logic then as a developer you need to test the entire functionalities which
00:24:25 include the old functionalities as well as new functionalities of the application.
00:24:31 As a developer, it is also your responsibility to tell the QA, quality assurance, team about
00:24:37 the changes in advance so that they can prepare themselves in advance for regression testing
00:24:41 along with the new feature testing. If you are not following the open-closed principle,
00:24:47 then it also breaks the single responsibility principle as the class or module is going to
00:24:52 perform multiple responsibilities. If you are implementing all the functionalities in
00:24:58 a single class, then the maintenance of the class becomes very difficult.
00:25:06 Because of the above key points, we need to follow the open-closed principle in C-sharp
00:25:12 while developing the application. Okay, so let's start coding it.
00:25:18 The first example will be an example that
00:25:23 breaks the open-closed principle. Let's name it as example breaks open-closed principle. Alright,
00:25:49 let's copy and paste the code.
00:26:12 So I'm going to add another class breaks open-closed.
00:26:25 Okay, so let's check it out. And what does that mean? We have invoice class
00:26:32 and that invoice class has get invoice discount, which takes two parameters,
00:26:38 which is amount and the invoice type. So according to the invoice type,
00:26:43 we are returning the discount amount. And what is wrong here? You see that this method
00:26:56 is doing different tasks based on the invoice type. Okay, so if I want to add another invoice
00:27:06 type here, let's say extra invoice, then what do I need to do for implementation? For implementation,
00:27:14 then I need to add more else if like this. And you see as I add more invoice types,
00:27:24 then I need to modify this existing class further. And this totally breaks open-closed
00:27:33 principle because I am modifying the existing class method for extending its functionality.
00:27:41 Okay, and this breaks the open-closed principle. And as explained in the article,
00:27:50 this forces us to retest all of the functionality and report to the quality assurance team and
00:27:59 other things. So I need to modify this in a way that it won't break it anymore.
00:28:06 Let's make example of this in our application. Okay,
00:28:30 now let's fix it in a way that it won't break our functionality. I mean the open-closed principle.
00:28:41 Okay, let's say proper open-closed principle.
00:29:05 So what do we need to do is we need to generate a base class and extend it. In this case, it will be
00:29:12 like this. Let's copy paste and analyze it. Let's add another class and name as proper open-closed.
00:29:25 Okay, so now we have a base class as invoice and this invoice class has a virtual method. Virtual
00:29:36 methods can be overridden by the inheriting classes and it has a get invoice discount
00:29:47 and double amount. Okay, and it's just deducts 10 point from the amount and return it. Then we have
00:29:57 final invoice, which has a get invoice discount method and it overrides the base method with
00:30:05 double amount. Then it gets the base. It calls the base get invoice and minus 50. This is the
00:30:14 final invoice. You see, these are the actual invoice types that we have in. Let me show again.
00:30:23 Okay, here we had final invoice, which was deducting 100 percent.
00:30:30 And we had proposed it, which was deducting 50 and we had extra invoice, which was deducting 75. So
00:30:38 for final invoice, we need to deduct 90 actually to make it equal and for proper proposed invoice,
00:30:47 it is minus 50. Yeah, this is correct. And okay, by the way, when we provide amount. Okay.
00:30:57 Yes, it's true. And there is a recurring invoice. Okay, let's fix this in this case.
00:31:18 Yeah, now fix it. It is minus 30. Let's make it minus 65. Okay. So you see, this is how
00:31:28 we are extending the functionality of the class with inheritance. Okay. I can add so many other
00:31:39 new invoice types here like super invoice. Okay. And I can say that just minus five.
00:31:49 Okay. So it is totally up to you to extend it. Now it looks much better. It is easier to read.
00:31:55 It is easier to manage and it won't break our existing code. It won't require retesting and
00:32:04 validating our existing code because it is just extending the base class. Okay. And let's make
00:32:13 an example call of that. By the way, this is not valid anymore. Yeah. In this case, proper. Okay.
00:32:28 So you see, now I can define each one of them. Let's say recurring invoice, recurring invoice.
00:32:40 And then just I can say get invoice discount with something like this. Okay.
00:32:49 All right. And yeah, they all made an example such that they.
00:32:59 Now the invoice class is closed for modification,
00:33:03 but it is open for the extension as it allows creating new classes deriving from the invoice
00:33:08 class, which clearly follows the open closed principle in C sharp. In the next article. Okay.
00:33:15 So let's move to Liskov substitution principle and let's just read its definition. All right. Okay.
00:33:27 What is the Liskov substitution principle in C sharp? The Liskov substitution principle is
00:33:35 a substitutability principle in object oriented programming language. This principle states that
00:33:41 if S is a subtype of T, then objects of type T should be replaced with the objects of type S.
00:33:49 In simple words we can say that, when we have a base class and child class relationships i.e.,
00:33:55 inheritance relationships, then, if we can successfully replace the object / instance
00:34:00 of a parent class with an object / instance of the child class, without affecting the
00:34:05 behavior of the base class instance, then it is said to be in Liskov substitution principle.
00:34:11 If you are not getting this point properly, don't worry, we will see some real time examples to
00:34:16 understand this concept. For example, a father is a teacher whereas his son is a doctor. So here,
00:34:25 in this case, the son can't simply replace his father even though both belong to the same family.
00:34:31 Okay, so let's make an example. First, we will make an example that violates Liskov's principle.
00:34:58 Alright, so to demonstrate a violation of Liskov's principle, I will just add a class here.
00:35:20 Okay, and we have two classes. The first class is apple and the second class is orange. You know,
00:35:28 apples and oranges are totally different things. So, we shouldn't be able to define apple
00:35:40 as an orange and get its color. Okay, this is a violation. Let's see what does that mean.
00:35:52 Okay, so let's define first, okay, Liskov violation, apple dot, okay, apple,
00:36:03 and let's see, MessageBox.Show apple, and let's say, apple color. One second, sorry about that.
00:36:23 And let's define orange. Okay, this will be an orange. Let's say orange color.
00:36:44 And now I am going to define
00:36:48 an apple from orange type. Okay, what does that mean? It means that something like this.
00:36:56 Let's say apple, and let's get its color. Okay, apple orange color. Okay, orange type apple color.
00:37:15 So, what we want in this case is to get the type of, get the color of orange, not the,
00:37:23 I mean to get the type of apple, not the orange. Because this is apple type and orange can't
00:37:30 replace it. However, in this case, we are going to get the color of orange instead of apple. Okay,
00:37:38 so let's run our application to verify. We have apple color red, we have orange color red, and
00:37:46 we have orange type color orange. Why do we have an error here? Let's fix it. Okay, now it will be,
00:37:55 okay, apple color red, orange color orange, and we have orange type apple color orange. And
00:38:02 this is the violation of Liskov principle. Why? Because, as you can see in the above example,
00:38:11 apple is the base class and orange is the child class i.e. there is a parent-child relationship.
00:38:18 So, we can store the child class object in the parent reference variable i.e. apple
00:38:23 apple equals new orange, and when we call the get color i.e. apple dot get color,
00:38:28 then we are getting the color of the orange not the color of apple. That means once the
00:38:33 child object is replaced i.e. apple storing the orange object, the behavior is also changed. Okay,
00:38:40 this is the key issue. The behavior is changed and this is violation of Liskov substitution
00:38:49 principle. This is against the LSP principle. The Liskov substitution principle in C sharp states
00:38:57 that even the child object is replaced with the parent, the behavior should not be changed. So,
00:39:03 in this case, if we are getting the color of apple instead of orange, then it follows the Liskov
00:39:09 substitution principle. So if we were seeing the color of apple then it would be following
00:39:14 the Liskov substitution principle. That means there is some issue with our software design.
00:39:21 Let us see how to overcome the design issue and makes the application follow
00:39:25 Liskov substitution principle. Okay, so let us make the proper example.
00:39:39 Okay, I will name it as Liskov.
00:39:55 All right, and let's add a new class as here proper Liskov. And let's copy and paste the code.
00:40:32 Okay, so let's check out the difference. So now we have an abstract class which is fruit. So in
00:40:40 this abstract class, we have get color method and it is also abstract as you can see. So any
00:40:48 class that inherits this abstract class has to define this method. So we have apple which has
00:40:56 red and it is overriding the abstract class in the fruit abstract class abstract method in the in the
00:41:06 abstract class of fruit and we have orange. You see, we didn't override the base class method. We
00:41:14 overrided the abstract class method different than the first example. And now let's make our test
00:41:26 in the same way. So this time it will be proper Liskov principle.
00:41:39 Okay, and you see now I am not able to define
00:41:44 apple with the type of orange. Okay, so let's call this as fruit orange.
00:41:53 And it will be fruit orange and you see how it makes sense now.
00:42:01 Okay, fruit orange and fruit apple. Okay, yes, and now it is much more sense making and it will work
00:42:16 correctly. Okay, apple color red, orange color orange, fruit orange color orange and fruit
00:42:23 apple color red. As expected, working perfectly fine and it's now follows the Liskov principle.
00:42:33 Okay, now time to see interface segregation principle.
00:42:45 What is the interface segregation principle in C sharp? The interface segregation principle states
00:42:52 that clients should not be forced to implement any methods they don't use. Rather than one fat
00:42:58 interface, numerous little interfaces are preferred based on groups of methods with
00:43:03 each interface serving one sub module. Let us break down the above definition into two parts.
00:43:11 First, no class should be forced to implement any methods of an interface they don't use.
00:43:18 Secondly, instead of creating large or you can say fat interfaces, create multiple smaller interfaces
00:43:24 with the aim that the clients should only think about the methods that are of interest to them.
00:43:29 Sorry about that, it was my baby child, my daughter.
00:43:37 Okay, as per the single responsibility principle of solid like classes, interfaces also should have
00:43:45 a single responsibility. That means we shouldn't force any class to implement any methods which
00:43:51 they don't require. Okay, so you see how these principles are, let's say, tightly coupled. So
00:43:59 one principle requires another principle and when you follow all of them, they are working like as
00:44:06 a team. Okay, so let's start with a violation of interface segregation principle. All right.
00:44:21 Okay, let's call it as violation of interface segregation.
00:44:42 All right. And let's copy and paste our class. So let's add a new class first. Interface violation.
00:45:03 And here, first, we have public interface, I printer tasks. Okay, and it defines four methods.
00:45:14 We can define this abstract class method like this return. Okay, let's say "white". Okay, this will
00:45:26 work. By the way, I need to. If I make it a method like this, I have to mark it as virtual so that it
00:45:35 can it can be overridden. If I make it abstract like this, then I can't it can't have a body.
00:45:45 Okay, so you can define body inside an abstract class with virtual methods that can be overridden.
00:45:54 Or you can make it abstract and it won't have a body. It won't have a body in method. Okay.
00:46:02 Okay, so for demonstration, let's also have another class here as
00:46:12 abstract class with body having method. And let's say virtual get color.
00:46:34 Okay, so both methodology is fine. Okay, let's continue with our interface violation,
00:46:41 interface principle violation. So we have I printer tasks and it has print, scan,
00:46:47 fax and print duplex methods. Interfaces can have method implementation, but they can't have they
00:46:57 can't have fields, data fields like public int. Okay, my property. Now it says that interfaces
00:47:07 cannot contain instance fields. Okay, so this is also valid. Okay, let's return back to our topic.
00:47:17 So we have I printer tasks. And not only that, we have. Okay, let's see.
00:47:28 HP laser jet printer, which inherits I printer task interface. So interfaces
00:47:36 are like blueprints and we have to implement each of the methods defined in the interface.
00:47:46 In the abstract class that we don't have to implement all of them. Actually, that was also
00:47:52 another mistaken information that I have given. For example, let's say we have abstract get color.
00:48:06 And these methods. Have to implement them, but. We can also define a body for that method and. Now.
00:48:29 Oh, it was true, so in both cases we have to implement both. Okay,
00:48:35 so let's just ignore that too. Okay, so I printer tasks is inherited with HP laser
00:48:45 jet printer and now we are defining each one of the methods and. You see, we have print, scan,
00:48:54 fax and print duplex. Each one of them, each one of the defined methods is also used here.
00:49:01 However, let's say I also have another class that inherits the I printer tasks. Interface and
00:49:12 this is liquid inject printer and in liquid inject printer. We don't have fax method or print duplex.
00:49:19 Therefore, they are not implemented exception. They are throwing not implemented exception.
00:49:27 And this is a violation of interface segregation principle. Why? Because
00:49:33 we are inheriting an interface. But we are not using all of the methods that it requires. Okay,
00:49:45 so how can we fix this problem? We can fix this problem by. Splitting this interface into multiple
00:49:54 interfaces and implementing necessary multiple interfaces in each class. Okay,
00:50:01 so let's first define this example. Then move to the proper interface design. Okay, for example.
00:50:28 Okay, now fix this interface violation problem.
00:50:41 Okay, proper interface segregation.
00:51:03 Let's fix the name segregation, yes.
00:51:17 Okay. All right, so let's add another class. And see the example proper interface
00:51:46 segregation. All right, let's copy paste. The fixed interface class implementations.
00:52:08 Okay, so we did split the IPrinter tasks in the first case in the first example into three
00:52:17 interfaces. The first one is IPrinter tasks. It has print and scan. What does this mean?
00:52:24 This means that every class that inherits IPrinter tasks interface will have these two methods. Okay,
00:52:33 so these are the basic methods that every printer will have print and scan. Then we
00:52:40 have I fax tasks, which means that whichever the class in inherits I fax tasks interface will have
00:52:48 fax method and whichever the class that inherits I printer duplex tasks will have print duplex.
00:52:55 So since these are interfaces, we can have multiple interfaces inheritance. However,
00:53:01 for abstract classes that you can have only one implementation.
00:53:09 Yes. Okay. For example, if we define two abstract classes, such as. Okay. And public abstract.
00:53:23 class ab2. Then our class can inherit only one of them. For example, it can inherit ab1. And
00:53:36 it has to come before any interfaces like this. However, if I also add ab2 here.
00:53:45 Then it will say that the base class cannot have multiple base classes. I mean, the child class
00:53:53 cannot have multiple base classes. However, it can have as many as interfaces as necessary.
00:54:01 Okay, so the HP laser jet printer will have both print, scan, fax and print duplex methods. All of
00:54:11 them and the liquid inject printer will have only print and scan, which are the very basic functions
00:54:17 of printers. Okay, so this is the corrected way, the proper way of interface segregation principle.
00:54:30 Okay, now time to move the last one.
00:54:34 The last principle in the solid design principles is what dependency inversion principle.
00:54:45 What is the dependency inversion principle in C sharp?
00:54:49 The dependency inversion principle DIP states that high level modules / classes should not
00:54:55 depend on low level modules / classes. Both should depend upon abstractions.
00:55:01 Secondly, abstractions should not depend upon details. Details should depend upon abstractions.
00:55:10 The most important point that you need to remember while developing real time applications,
00:55:14 always to try to keep the high level module and low level module as loosely coupled as possible.
00:55:22 When a class knows about the design and implementation of another class,
00:55:26 it raises the risk that if we do any changes to one class will break the other class. So we must
00:55:32 keep these high level and low level modules / classes loosely coupled as much as possible.
00:55:38 To do that, we need to make both of them dependent on abstractions instead of knowing each other.
00:55:45 Okay, so let's start with an example to understand better. Okay. Okay,
00:55:55 I'm adding a button.
00:56:01 Violation of dependency inversion.
00:56:23 Let's click and oh, we also need to fix this as proper Interface separation.
00:56:36 Okay. And then I can call. Okay, so let's add a new class for dependency inversion violation.
00:56:55 All right. And in here, let's copy and paste the code. Okay, we have a public
00:57:03 class employee and it has four attributes, which are ID, name, department and salary.
00:57:15 And we have public class employee business logic. Okay. And we have public class data
00:57:26 access factory. Let's paste it in above the employee data access and. Okay. We also have.
00:57:45 Okay, one second. Here. Yes. Now all is fixed. Okay.
00:58:01 So we have employee class, which holds the data of each employee. We have employee data access class,
00:58:08 which implements the logic of accessing employee data. You see, it has a public
00:58:15 method that returns employee data. It is named as get employee details. It takes ID of the employee.
00:58:24 Then it generates an employee, an example employee and returns it.
00:58:29 Okay. And we have two other classes, which are data access factory.
00:58:35 It has a public static method that returns a new instance of employee data access class.
00:58:45 Okay. We have employee business logic class, which implements employee data access.
00:58:55 Which uses employee data access and generates an instance of employee data access class in
00:59:04 the constructor. And it returns the details. Okay. So how is this violating the dependency inversion?
00:59:19 Okay. Let's read it to find out. Let us compare the above example with the dependency
00:59:29 inversion principle in C sharp. As per the dependency inversion principle definition,
00:59:35 a high level module should not depend on low level modules. Both should depend on the abstraction.
00:59:43 So first we need to figure out which one is the high level module class and which one is the
00:59:49 low level module class. In our example, a high level module is a module that always depends on
00:59:56 other modules. So in our example, the employee business logic class depends on employee data
01:00:03 access class. So here the employee business logic class is the high level module and the employee
01:00:09 data access class is the low level module. So as per the first rule of the dependency inversion
01:00:16 principle in C sharp, the employee business logic class / module should not depend on the concrete
01:00:22 employee data access class / module. Instead, both the classes should depend on abstraction.
01:00:29 The second rule of the dependency inversion principle state that abstractions should
01:00:34 not depend on details. Details should depend on abstractions.
01:00:39 Before understanding this, let us first understand what is an abstraction. What is abstraction? In
01:00:47 simple words, we can say that abstraction means something which is non concrete. So abstraction
01:00:54 in programming means we need to create either an interface or abstract class which is non
01:00:59 concrete so that we cannot create an instance of it. In our example, the employee business
01:01:04 logic and employee data access are concrete classes that mean we can create objects of it.
01:01:11 As per the dependency inversion principle in C sharp, the employee business logic high
01:01:16 level module should not depend on the concrete employee data access low level module class.
01:01:23 Both classes should depend on abstractions, meaning both classes should depend on either
01:01:28 an interface or an abstract class. OK, so let's see how employee business logic is depending on
01:01:35 concrete employee data access in our application. And we are right away seeing it. So you see,
01:01:43 OK. OK, as you can see, it is dependent on the concrete instance of employee data access class
01:01:53 with here. And that is a violation of dependency inversion principle. So we need to modify our
01:02:05 logic with abstraction abstract classes or interfaces. Instead of depending on concrete
01:02:15 instance of a class. OK, so let's make an example of this with violation. Actually,
01:02:41 that's the point is yes.
01:02:49 Yes,
01:03:09 OK, so let's also see the proper fixed version of the dependency inversion. Right,
01:03:23 it will be proper dependency inversion.
01:03:35 OK, and let's add another class and name it as
01:03:47 proper dependent version. OK, so how are we going to separate? We are going to separate it as
01:03:59 an interface IEmployeeDataAccess which has employee get employee details method.
01:04:06 And we are going to have. OK, employee data access class which inherits IEmployeeDataAccess
01:04:14 interface. We have data access factory which still has the same method and we have
01:04:33 employee business logic. You see, in this case, it has a field of IEmployeeDataAccess. OK, and
01:04:50 IEmployeeDataAccess is an interface. Therefore, it is using the interface instead of concrete
01:05:04 instance of a class. So employee data access was a class. Therefore, this was a concrete instance.
01:05:13 However, in here we are just using the interface instead of a concrete instance of a class.
01:05:22 And this is the proper way of doing dependency inversion. OK,
01:05:35 that's it. We have implemented the dependency inversion principle in our example where the
01:05:41 high level module employee business logic and low level module employee data access depend
01:05:47 on abstraction IEmployeeDataAccess. Also abstraction IEmployeeDataAccess
01:05:54 does not depend on details employee data access, but details depend on abstraction.
01:06:01 Advantages of implementing the dependency inversion principle in C sharp.
01:06:07 Now the employee business logic and employee data access classes are loosely coupled classes
01:06:12 because employee business logic does not depend on concrete employee data access class. Instead,
01:06:18 it includes a reference of IEmployeeDataAccess interface. So now we can easily use another
01:06:25 class that implements IEmployeeDataAccess with a different implementation. OK, this is it. And
01:06:34 let's also make an example of this. Proper dependency inversion. And we have IEmployee logic.
01:07:02 And now when we run our application, it will compile.
01:07:09 OK, if you have any questions, you can join our Discord channel. Also,
01:07:19 I will upload this into a GitHub repository and I will put the link of the repository in
01:07:25 the description of the video. So make sure that you check it out. Thank you for watching. I hope
01:07:32 you have enjoyed. Please make a comment and let me know what you think. Hopefully see you later.
Beta Was this translation helpful? Give feedback.
All reactions