{"id":144,"date":"2025-01-20T21:24:14","date_gmt":"2025-01-20T21:24:14","guid":{"rendered":"https:\/\/www.fabricioruch.ch\/?p=144"},"modified":"2025-01-20T21:25:50","modified_gmt":"2025-01-20T21:25:50","slug":"heres-a-comprehensive-blog-post-about-solid-dry-wet-and-other-principles","status":"publish","type":"post","link":"https:\/\/www.fabricioruch.ch\/?p=144","title":{"rendered":"Software Design Principles: SOLID, DRY, WET, and More"},"content":{"rendered":"\n<p>When developing software, applying established design principles helps ensure your code is clean, maintainable, and scalable. In this article, we explore some of the most important principles, including <strong>SOLID<\/strong>, <strong>DRY<\/strong>, and <strong>WET<\/strong>, along with practical examples.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1. SOLID Principles<\/strong><\/h2>\n\n\n\n<p>The <strong>SOLID<\/strong> principles are five design principles aimed at improving object-oriented design.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>S: Single Responsibility Principle (SRP)<\/strong><\/h3>\n\n\n\n<p>A class should have only one reason to change.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example\npublic class ReportManager\n{\n    public void GenerateReport() { \/* Generate report *\/ }\n    public void SaveToFile() { \/* Save report to file *\/ }\n}\n\n\/\/ GOOD Example\npublic class ReportGenerator\n{\n    public void GenerateReport() { \/* Generate report *\/ }\n}\n\npublic class FileManager\n{\n    public void SaveToFile() { \/* Save report to file *\/ }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>O: Open\/Closed Principle (OCP)<\/strong><\/h3>\n\n\n\n<p>Software entities should be open for extension but closed for modification.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: Modifying the Shape class every time a new shape is added.\npublic class Shape\n{\n    public string Type { get; set; }\n}\n\npublic class AreaCalculator\n{\n    public double Calculate(Shape shape)\n    {\n        if (shape.Type == \"Circle\") { \/* Circle logic *\/ }\n        else if (shape.Type == \"Rectangle\") { \/* Rectangle logic *\/ }\n    }\n}\n\n\/\/ GOOD Example: Use polymorphism to extend functionality without modifying existing code.\npublic abstract class Shape\n{\n    public abstract double CalculateArea();\n}\n\npublic class Circle : Shape\n{\n    public double Radius { get; set; }\n    public override double CalculateArea() =&gt; Math.PI * Radius * Radius;\n}\n\npublic class Rectangle : Shape\n{\n    public double Width { get; set; }\n    public double Height { get; set; }\n    public override double CalculateArea() =&gt; Width * Height;\n}\n\npublic class AreaCalculator\n{\n    public double Calculate(Shape shape) =&gt; shape.CalculateArea();\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>L: Liskov Substitution Principle (LSP)<\/strong><\/h3>\n\n\n\n<p>Derived classes must be substitutable for their base classes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: Violates LSP because the Penguin class breaks expected behavior.\npublic class Bird\n{\n    public virtual void Fly() { Console.WriteLine(\"Flying\"); }\n}\n\npublic class Penguin : Bird\n{\n    public override void Fly() { throw new NotImplementedException(); }\n}\n\n\/\/ GOOD Example: Use interfaces to define appropriate behavior.\npublic interface IFlyable\n{\n    void Fly();\n}\n\npublic class Bird : IFlyable\n{\n    public void Fly() { Console.WriteLine(\"Flying\"); }\n}\n\npublic class Penguin\n{\n    public void Swim() { Console.WriteLine(\"Swimming\"); }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>I: Interface Segregation Principle (ISP)<\/strong><\/h3>\n\n\n\n<p>A class should not be forced to implement interfaces it does not use.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: A large interface forces unused implementations.\npublic interface IWorker\n{\n    void Work();\n    void Eat();\n}\n\npublic class Robot : IWorker\n{\n    public void Work() { Console.WriteLine(\"Working\"); }\n    public void Eat() { throw new NotImplementedException(); }\n}\n\n\/\/ GOOD Example: Split the interface into smaller, focused interfaces.\npublic interface IWorkable\n{\n    void Work();\n}\n\npublic interface IFeedable\n{\n    void Eat();\n}\n\npublic class Robot : IWorkable\n{\n    public void Work() { Console.WriteLine(\"Working\"); }\n}\n\npublic class Human : IWorkable, IFeedable\n{\n    public void Work() { Console.WriteLine(\"Working\"); }\n    public void Eat() { Console.WriteLine(\"Eating\"); }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>D: Dependency Inversion Principle (DIP)<\/strong><\/h3>\n\n\n\n<p>High-level modules should not depend on low-level modules. Both should depend on abstractions.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: Direct dependency on a low-level module.\npublic class EmailService\n{\n    public void SendEmail() { \/* Send email logic *\/ }\n}\n\npublic class Notification\n{\n    private EmailService _emailService = new EmailService();\n\n    public void Notify() { _emailService.SendEmail(); }\n}\n\n\/\/ GOOD Example: Use dependency injection with abstractions.\npublic interface IMessageService\n{\n    void SendMessage();\n}\n\npublic class EmailService : IMessageService\n{\n    public void SendMessage() { \/* Send email logic *\/ }\n}\n\npublic class Notification\n{\n    private readonly IMessageService _messageService;\n\n    public Notification(IMessageService messageService)\n    {\n        _messageService = messageService;\n    }\n\n    public void Notify() { _messageService.SendMessage(); }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2. DRY: Don\u2019t Repeat Yourself<\/strong><\/h2>\n\n\n\n<p>The <strong>DRY<\/strong> principle encourages reducing duplication in code by consolidating logic into reusable methods or modules.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: Repeated validation logic.\npublic class OrderService\n{\n    public void PlaceOrder()\n    {\n        Console.WriteLine(\"Validating order...\");\n        Console.WriteLine(\"Processing payment...\");\n    }\n\n    public void CancelOrder()\n    {\n        Console.WriteLine(\"Validating order...\");\n        Console.WriteLine(\"Processing refund...\");\n    }\n}\n\n\/\/ GOOD Example: Consolidate shared logic.\npublic class OrderService\n{\n    private void ValidateOrder()\n    {\n        Console.WriteLine(\"Validating order...\");\n    }\n\n    public void PlaceOrder()\n    {\n        ValidateOrder();\n        Console.WriteLine(\"Processing payment...\");\n    }\n\n    public void CancelOrder()\n    {\n        ValidateOrder();\n        Console.WriteLine(\"Processing refund...\");\n    }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3. WET: Write Everything Twice<\/strong> \/ We Enjoy Typing<\/h2>\n\n\n\n<p>The <strong>WET<\/strong> principle stands in contrast to DRY, emphasizing duplication and redundancy. WET often results from:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Copy-pasting code.<\/li>\n\n\n\n<li>Lack of abstraction.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Consequences of WET:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Harder to maintain.<\/li>\n\n\n\n<li>Increased risk of bugs due to inconsistencies.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4. YAGNI: You Aren\u2019t Gonna Need It<\/strong><\/h2>\n\n\n\n<p>The <strong>YAGNI<\/strong> principle advises against adding functionality until it is necessary. It helps avoid over-engineering and keeps the codebase simple.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: Adding unnecessary methods for future use.\npublic class UserService\n{\n    public void RegisterUser() { \/* Registration logic *\/ }\n\n    public void DeleteUser() { \/* Unnecessary functionality for now *\/ }\n}\n\n\/\/ GOOD Example: Focus only on what is required now.\npublic class UserService\n{\n    public void RegisterUser() { \/* Registration logic *\/ }\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>5. KISS: Keep It Simple, Stupid<\/strong><\/h2>\n\n\n\n<p>The <strong>KISS<\/strong> principle emphasizes simplicity in design and implementation. Complex solutions should be avoided when simpler ones suffice.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ BAD Example: Overly complex logic for summing two numbers.\npublic int Add(int a, int b)\n{\n    return Enumerable.Range(0, a).Sum() + Enumerable.Range(0, b).Sum();\n}\n\n\/\/ GOOD Example: A straightforward approach.\npublic int Add(int a, int b)\n{\n    return a + b;\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Adhering to principles like SOLID, DRY, and KISS ensures your code remains maintainable, scalable, and easy to understand. By following these guidelines, you can avoid common pitfalls, write better software, and create systems that stand the test of time. Start small by applying one principle at a time, and soon, they will become a natural part of your development process.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When developing software, applying established design principles helps ensure your code is clean, maintainable, and scalable. In this article, we explore some of the most important principles, including SOLID, DRY, and WET, along with practical examples. 1. SOLID Principles The&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,21,8,25],"tags":[],"class_list":["post-144","post","type-post","status-publish","format-standard","hentry","category-csharp","category-learning","category-software-architecture","category-software-engineering"],"_links":{"self":[{"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=\/wp\/v2\/posts\/144","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=144"}],"version-history":[{"count":3,"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=\/wp\/v2\/posts\/144\/revisions"}],"predecessor-version":[{"id":147,"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=\/wp\/v2\/posts\/144\/revisions\/147"}],"wp:attachment":[{"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=144"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=144"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fabricioruch.ch\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=144"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}