Skip to main content

Practical Guide to SOLID Software Design Principles

SOLID software design principles are guidelines that help developers create more maintainable, understandable, and flexible code. These principles apply to any object-oriented design, and they aim to reduce the complexity of software development, making it easier to manage and scale. 


The acronym SOLID stands for:

  • Single Responsibility Principle (SRP): A class should have only one reason to change, meaning it should have only one job or responsibility.
       Example: Instead of one class handling multiple responsibilities (calculating, printing, saving), each class has a single responsibility.  

    public class Invoice {

        public void CalculateTotal() { /* ... */ }

    }

    public class InvoicePrinter {

        public void Print(Invoice invoice) { /* ... */ }

    }

    public class InvoiceSaver {

        public void SaveToFile(Invoice invoice) { /* ... */ }

    }

  • Open/Closed Principle (OCP): Software entities should be open for extension but closed for modification, allowing the behaviour to be extended without modifying existing code.
       Example: You can extend the Shape class by adding new shapes like Circle without modifying existing code.   

    public abstract class Shape {

        public abstract double Area();

    }

    public class Rectangle : Shape {

        public double Width { get; set; }

        public double Height { get; set; }

        public override double Area() => Width * Height;

    }

    public class Circle : Shape {

        public double Radius { get; set; }

        public override double Area() => Math.PI * Radius * Radius;

    }

  • Liskov Substitution Principle (LSP): Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program.
       Example: The Ostrich class violates LSP because it doesn't behave as expected when used as a Bird. A better design might avoid having Ostrich inherit from Bird if it can't fly.

    public class Bird {

        public virtual void Fly() { /* ... */ }

    }

    public class Sparrow : Bird { }

    public class Ostrich : Bird {

        public override void Fly() {

            throw new InvalidOperationException("Ostriches can't fly.");

        }

    }

  • Interface Segregation Principle (ISP): Clients should not be forced to depend on interfaces they do not use, meaning smaller, more specific interfaces are better than a large, general-purpose one.
      Example: Instead of one large interface, smaller interfaces (IPrinter, IScanner) are created, so clients only implement what they need.

    public interface IPrinter {

        void Print();

    }

    public interface IScanner {

        void Scan();

    }

    public class MultiFunctionPrinter : IPrinter, IScanner {

        public void Print() { /* ... */ }

        public void Scan() { /* ... */ }

    }

    public class SimplePrinter : IPrinter {

        public void Print() { /* ... */ }

    }

  • Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules; both should depend on abstractions. Additionally, abstractions should not depend on details, but details should depend on abstractions.
     Example: Notification depends on the IMessageSender abstraction, not on a concrete class like EmailSender. This allows easy substitution with other implementations (e.g., SMS sender).

    public interface IMessageSender {

        void SendMessage(string message);

    }

    public class EmailSender : IMessageSender {

        public void SendMessage(string message) { /* ... */ }

    }

    public class Notification {

        private readonly IMessageSender _messageSender;

        public Notification(IMessageSender messageSender) {

            _messageSender = messageSender;

        }

        public void Send(string message) {

            _messageSender.SendMessage(message);

        }

    }

Happy coding.

Comments

Popular posts from this blog

How to fix Git push error: "RPC failed; curl 56 HTTP/2 stream 7 was reset send-pack: unexpected disconnect while reading sideband packet fatal: the remote end hung up unexpectedly"

Problem Today I saw the following problem when I tried to push my changes to a Git server after doing some work for upgrading an Umbraco v7 project to v8.18.8.  Possible reasons After some investigations, it seems like this could be because of the following reasons; Git is not happy with the amount of changes that are being pushed into the server.  There are possible limitations on the server about the size/amount of files that you can push. Your internet connection is not good and stable enough. Your Git client's version is old. Solution options For me, the easiest option was connecting to another Wifi and trying again. Apparently, this option helped quite a few people, so it is worth giving it a try. Unfortunately, it didn't work for me. A bad internet connection wasn't an option for me either, as my internet is pretty fast (500 Mbps). Similarly, my Git client version was the latest version (git version 2.41.0.windows.3).  On StackOverflow, there were a lot of recommend...

How to use JQuery Ajax Methods for Async ASP.NET MVC Action Methods

Making repeatedly calls to async methods can be a nightmare. In this case, it makes sense to use 2 ajax methods, instead of one. Here is a simple solution to overcome this problem. See that  ajaxcalls   is emptied after the success response for the first ajax call and then the second ajax method is used to make one single call to the async action method. Hope it helps. View: @section Scripts{     < script type ="text/javascript">         var smartDebitObject = new Object();         smartDebitObject.MembershipNumber = $( "#MembershipNumber" ).val();         smartDebitObject.ProfileId = $( "#ProfileId" ).val();         smartDebitObject.FirstName = $( "#FirstName" ).val();         smartDebitObject.LastName = $( "#LastName" ).val();     ...

How to fix "Microsoft SQL Error SQL71564: Error validating element [USERNAME]: The element [USERNAME] has been orphaned from its login and cannot be deployed."

I needed to export a database in BACPAC format today in order to restore it somewhere else, and I encountered the following error. To resolve this issue, I deleted all of the users mentioned in the error log. After successfully creating the BACPAC file, I used it to create a new database with no problems. Error: TITLE: Microsoft SQL Server Management Studio ------------------------------ One or more unsupported elements were found in the schema used as part of a data package. Error SQL71564: Error validating element [USER1]: The element [USER1] has been orphaned from its login and cannot be deployed. Error SQL71564: Error validating element [USER2]: The element [USER2] has been orphaned from its login and cannot be deployed. Error SQL71564: Error validating element [USER3]: The element [USER3] has been orphaned from its login and cannot be deployed. Error SQL71564: Error validating element [USER4]: The element [USER4] has been orphaned from its login and cannot be deployed. Error SQL71...