{"id":534,"date":"2023-09-07T07:36:03","date_gmt":"2023-09-07T13:36:03","guid":{"rendered":"https:\/\/kop.lat\/blog\/?p=534"},"modified":"2023-09-09T16:49:47","modified_gmt":"2023-09-09T22:49:47","slug":"solid-principles-in-c-and-net","status":"publish","type":"post","link":"https:\/\/kop.lat\/blog\/solid-principles-in-c-and-net\/","title":{"rendered":"SOLID principles in C# and .NET"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<p>SOLID principles in C# and .NET are guidelines for writing maintainable and scalable software. <\/p>\n\n\n\n<p>They help in creating code that is easier to understand, extend, and modify. <\/p>\n\n\n\n<p>An explanation of each principle as follows:<\/p>\n\n\n\n<ol>\n<li><strong>Single Responsibility Principle (SRP)<\/strong>:\n<ul>\n<li>Each class should have only one reason to change. It means a class should have only one responsibility or job, and it should do it well.<\/li>\n\n\n\n<li>This principle states that a class should have only one reason to change, meaning it <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">should have a single responsibility or job.<\/mark><\/strong><\/li>\n\n\n\n<li>It encourages the <strong>separation of concerns<\/strong>, where each class or module is responsible for a specific task.<\/li>\n\n\n\n<li>Benefits include easier code maintenance and a reduced likelihood of introducing bugs when making changes.<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Open\/Closed Principle (OCP)<\/strong>:\n<ul>\n<li>Software entities (classes, modules, etc.) should be<strong> <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">open for extension but closed for modification<\/mark><\/strong>. New functionality can be added by extending existing code rather than changing it.<\/li>\n\n\n\n<li>The Open\/Closed Principle states that software entities (such as classes, modules, and functions) should be open for extension but closed for modification.<\/li>\n\n\n\n<li>It encourages to design the code in a way that allows to add new functionality by extending existing code, rather than modifying it.<\/li>\n\n\n\n<li>Common practices to achieve this include using inheritance, interfaces, and polymorphism.<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Liskov Substitution Principle (LSP)<\/strong>:\n<ul>\n<li>Derived classes must be substitutable for their base classes without altering the correctness of the program. In other words, subclasses should behave in a compatible way with their parent classes<\/li>\n\n\n\n<li>The Liskov Substitution Principle emphasizes that <mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\"><strong>objects of a derived class should be able to replace objects of the base class without affecting the correctness of the program<\/strong>.<\/mark><\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">A base class, should have implementations that applies (are compatible) with\/to all subclasses.<\/mark><\/li>\n\n\n\n<li>It ensures that derived classes adhere to the contract established by the base class.<\/li>\n\n\n\n<li>Violating this principle can lead to unexpected behavior in a program.<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Interface Segregation Principle (ISP)<\/strong>:\n<ul>\n<li>Clients should not be forced to depend on interfaces they do not use. It suggests that it should create small and specific interfaces tailored to the needs of the clients that use them.<\/li>\n\n\n\n<li>The Interface Segregation Principle states that <em><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\"><strong>clients should not be forced to depend on interfaces they do not use.<\/strong><\/mark><\/em><\/li>\n\n\n\n<li>It encourages the creation of <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">small, specific interfaces rather than large, monolithic<\/mark><\/strong> ones.<\/li>\n\n\n\n<li>This principle helps avoid unnecessary dependencies between classes and reduces the impact of changes.<br><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Dependency Inversion Principle (DIP)<\/strong>:<br>\n<ul>\n<li>The principle states that higher-level modules should not depend directly on lower-level modules, but rather both should depend on abstractions. <\/li>\n\n\n\n<li><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\"><strong>Instead of depending on a concrete implementation, modules should depend on interfaces or abstract classes that define the expected behavior.<\/strong><\/mark><\/li>\n\n\n\n<li>High-level modules should not depend on low-level modules; both should depend on abstractions. It promotes the use of interfaces or abstract classes to decouple high-level and low-level components in the system.<\/li>\n\n\n\n<li>The Dependency Inversion Principle suggests that <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">high-level modules should not depend on low-level modules;<\/mark><\/strong> both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.<\/li>\n\n\n\n<li>It promotes the use of interfaces or abstract classes to define dependencies, allowing for flexibility and ease of testing.<\/li>\n\n\n\n<li>It enables the decoupling of high-level and low-level components, making the codebase more maintainable and adaptable.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>By following these principles, designs in C# and .NET applications are more maintainable, flexible, and resistant to changes.<\/p>\n\n\n\n<p>Applying these SOLID principles C#\/.NET code can lead to more modular, maintainable, and extensible software.<\/p>\n\n\n\n<p>By adhering to these principles, code quality improves, reduce the risk of introducing bugs, and facilitate collaboration among developers working on the same codebase.<\/p>\n\n\n\n<p class=\"has-x-large-font-size\"><mark style=\"background-color:#000000\" class=\"has-inline-color has-vivid-green-cyan-color\"><strong>Examples<\/strong>:<\/mark><\/p>\n\n\n\n<p>The SOLID principles in C# and .NET are a set of design principles that aim to address common problems and challenges in software development. Each principle focuses on solving specific issues related to code maintainability, flexibility, extensibility, and robustness. Here are the problems that each SOLID principle helps solve, along with examples for better understanding:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Single Responsibility Principle (SRP)<\/strong>:<\/h2>\n\n\n\n<p><strong>Problem<\/strong>: Classes with multiple responsibilities can become hard to understand, maintain, and change. They are also more prone to bugs because changes in one area can affect other areas.<\/p>\n\n\n\n<p><strong>Solution<\/strong>: SRP encourages that a class should have only one reason to change, meaning it should have a single responsibility.<\/p>\n\n\n\n<p><strong>Example<\/strong>: <\/p>\n\n\n\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\" snippet-height=\"\" style=\"background-color:#5E69FF\"><div class=\"control-language\"><div class=\"dm-buttons\"><div class=\"dm-buttons-left\"><div class=\"dm-button-snippet red-button\"><\/div><div class=\"dm-button-snippet orange-button\"><\/div><div class=\"dm-button-snippet green-button\"><\/div><\/div><div class=\"dm-buttons-right\"><a id=\"dm-copy-raw-code\"><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\" style=\"display:none\">Copied<\/span><span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a><\/div><\/div><pre class=\" line-numbers\"><code id=\"dm-code-raw\" class=\" no-wrap language-clike\">\/\/ Problematic class with multiple responsibilities\npublic class UserService\n{\n    public void AuthenticateUser() { \/* ... *\/ }\n    public void UpdateUserProfile() { \/* ... *\/ }\n    public void SendNotification() { \/* ... *\/ }\n}\n\n\/\/ SRP-compliant classes with separate responsibilities\npublic class AuthenticationService\n{\n    public void AuthenticateUser() { \/* ... *\/ }\n}\n\npublic class UserProfileService\n{\n    public void UpdateUserProfile() { \/* ... *\/ }\n}\n\npublic class NotificationService\n{\n    public void SendNotification() { \/* ... *\/ }\n}\n<\/code><\/pre><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Open\/Closed Principle (OCP)<\/strong>:<\/h2>\n\n\n\n<p><strong>Problem<\/strong>: Changing existing code to accommodate new features or requirements can introduce new bugs and impact the stability of the system.<\/p>\n\n\n\n<p><strong>Solution<\/strong>: OCP suggests that software entities (classes, modules, etc.) should be open for extension but closed for modification. You should be able to add new functionality without altering existing code.<\/p>\n\n\n\n<p><strong>Example<\/strong>: <\/p>\n\n\n\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\" snippet-height=\"\" style=\"background-color:#C9D8B6\"><div class=\"control-language\"><div class=\"dm-buttons\"><div class=\"dm-buttons-left\"><div class=\"dm-button-snippet red-button\"><\/div><div class=\"dm-button-snippet orange-button\"><\/div><div class=\"dm-button-snippet green-button\"><\/div><\/div><div class=\"dm-buttons-right\"><a id=\"dm-copy-raw-code\"><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\" style=\"display:none\">Copied<\/span><span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a><\/div><\/div><pre class=\" line-numbers\"><code id=\"dm-code-raw\" class=\" no-wrap language-clike\">\/\/ Problematic code that requires modification for new shapes\npublic class AreaCalculator\n{\n    public double CalculateArea(object shape)\n    {\n        if (shape is Rectangle rect)\n            return rect.Width * rect.Height;\n        else if (shape is Circle circle)\n            return Math.PI * Math.Pow(circle.Radius, 2);\n        \/\/ More shapes...\n        return 0;\n    }\n}\n\n\/\/ OCP-compliant code with extensible shape hierarchy\npublic interface IShape\n{\n    double CalculateArea();\n}\n\npublic class Rectangle : IShape\n{\n    public double Width { get; set; }\n    public double Height { get; set; }\n    public double CalculateArea() => Width * Height;\n}\n\npublic class Circle : IShape\n{\n    public double Radius { get; set; }\n    public double CalculateArea() => Math.PI * Math.Pow(Radius, 2);\n}\n<\/code><\/pre><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Liskov Substitution Principle (LSP)<\/strong>:<\/h2>\n\n\n\n<p><strong>Problem<\/strong>: Subclasses that do not fully conform to the behavior of their base classes can lead to unexpected and incorrect program behavior.<\/p>\n\n\n\n<p><strong>Solution<\/strong>: LSP states that objects of derived classes should be able to replace objects of the base class without affecting program correctness.<\/p>\n\n\n\n<p><strong>Example<\/strong>: <\/p>\n\n\n\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\" snippet-height=\"\" style=\"background-color:#7FC8A9\"><div class=\"control-language\"><div class=\"dm-buttons\"><div class=\"dm-buttons-left\"><div class=\"dm-button-snippet red-button\"><\/div><div class=\"dm-button-snippet orange-button\"><\/div><div class=\"dm-button-snippet green-button\"><\/div><\/div><div class=\"dm-buttons-right\"><a id=\"dm-copy-raw-code\"><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\" style=\"display:none\">Copied<\/span><span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a><\/div><\/div><pre class=\" line-numbers\"><code id=\"dm-code-raw\" class=\" no-wrap language-clike\">\/\/ Problematic violation of LSP\npublic class Bird\n{\n    public virtual void Fly() { \/* ... *\/ }\n}\n\npublic class Ostrich : Bird\n{\n    public override void Fly() { \/* Cannot fly! *\/ }\n}\n\n\/\/ LSP-compliant hierarchy\npublic interface IFlyable\n{\n    void Fly();\n}\n\npublic class Sparrow : IFlyable\n{\n    public void Fly() { \/* ... *\/ }\n}\n\npublic class Ostrich : Bird \/\/ Separating non-flyable from Bird\n{\n    \/\/ No Fly method\n}\n<\/code><\/pre><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Interface Segregation Principle (ISP)<\/strong>:<\/h2>\n\n\n\n<p><strong>Problem<\/strong>: Large interfaces with many methods force implementing classes to provide implementations for methods they do not need, leading to unnecessary dependencies and complexity.<\/p>\n\n\n\n<p><strong>Solution<\/strong>: ISP advises creating small, specific interfaces to avoid forcing clients to depend on methods they don&#8217;t use.<\/p>\n\n\n\n<p><strong>Example<\/strong>:<\/p>\n\n\n\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\" snippet-height=\"\" style=\"background-color:#FB8CFF\"><div class=\"control-language\"><div class=\"dm-buttons\"><div class=\"dm-buttons-left\"><div class=\"dm-button-snippet red-button\"><\/div><div class=\"dm-button-snippet orange-button\"><\/div><div class=\"dm-button-snippet green-button\"><\/div><\/div><div class=\"dm-buttons-right\"><a id=\"dm-copy-raw-code\"><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\" style=\"display:none\">Copied<\/span><span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a><\/div><\/div><pre class=\" line-numbers\"><code id=\"dm-code-raw\" class=\" no-wrap language-clike\">\/\/ Problematic interface with many methods\npublic interface IWorker\n{\n    void Work();\n    void Eat();\n    void Sleep();\n}\n\n\/\/ ISP-compliant interfaces with smaller responsibilities\npublic interface IWorker\n{\n    void Work();\n}\n\npublic interface IEater\n{\n    void Eat();\n}\n\npublic interface ISleeper\n{\n    void Sleep();\n}\n<\/code><\/pre><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Dependency Inversion Principle (DIP)<\/strong>:<\/h2>\n\n\n\n<ul>\n<li><strong>Problem<\/strong>: High-level modules depend on low-level modules, making the code less flexible and difficult to test.<\/li>\n\n\n\n<li><strong>Solution<\/strong>: DIP suggests that high-level modules and low-level modules should depend on abstractions, not on concrete implementations. Abstractions should not depend on details.<\/li>\n\n\n\n<li><strong>Example<\/strong>:<\/li>\n<\/ul>\n\n\n\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\" snippet-height=\"\" style=\"background-color:#5E69FF\"><div class=\"control-language\"><div class=\"dm-buttons\"><div class=\"dm-buttons-left\"><div class=\"dm-button-snippet red-button\"><\/div><div class=\"dm-button-snippet orange-button\"><\/div><div class=\"dm-button-snippet green-button\"><\/div><\/div><div class=\"dm-buttons-right\"><a id=\"dm-copy-raw-code\"><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\" style=\"display:none\">Copied<\/span><span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a><\/div><\/div><pre class=\" line-numbers\"><code id=\"dm-code-raw\" class=\" no-wrap language-clike\">\/\/ Problematic high-level module depending on low-level module\npublic class LightBulb\n{\n    public void TurnOn() { \/* ... *\/ }\n    public void TurnOff() { \/* ... *\/ }\n}\n\npublic class Switch\n{\n    private LightBulb bulb = new LightBulb(); \/\/ Dependency on concrete class\n\n    public void Toggle()\n    {\n        if (\/* condition *\/)\n            bulb.TurnOn();\n        else\n            bulb.TurnOff();\n    }\n}\n\n\/\/ DIP-compliant code with abstractions\npublic interface ISwitchable\n{\n    void TurnOn();\n    void TurnOff();\n}\n\npublic class LightBulb : ISwitchable\n{\n    public void TurnOn() { \/* ... *\/ }\n    public void TurnOff() { \/* ... *\/ }\n}\n<\/code><\/pre><\/div><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>SOLID principles in C# and .NET are guidelines for writing maintainable and scalable software. They help in creating code that is easier to understand, extend, and modify. An explanation of each principle as follows: By following these principles, designs in C# and .NET applications are more maintainable, flexible, and resistant to changes. Applying these SOLID [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":464,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[51,52,7,90],"tags":[53,95,94,23,54,96,93,91,92],"_links":{"self":[{"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/posts\/534"}],"collection":[{"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/comments?post=534"}],"version-history":[{"count":13,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/posts\/534\/revisions"}],"predecessor-version":[{"id":569,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/posts\/534\/revisions\/569"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/media\/464"}],"wp:attachment":[{"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/media?parent=534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/categories?post=534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kop.lat\/blog\/wp-json\/wp\/v2\/tags?post=534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}