Design Principle (1-1): SOLID in Code Demo

Note: this article is published on 07/28/2024.

This series of articles will discuss Software Design Principles.

  • Design Principle (0): Design Principle vs Design Pattern
  • Design Principle (1): SOLID in Concept
  • Design Principle (2): Inversion of Control (IoC) Principle

    Introduction

    The SOLID are long-standing principles used to manage most of the software design problems you encounter in daily programming process. In the previous article, Design Principle (1): SOLID in Concept, we have discussed the concept for SOLID, this article will discuss the implementations and the understanding based on the implementations.

    We will discuss SOLID one by one --- the content of this article:

    • Single Responsibility Principle
    • Open/Close Principle
    • Liskov Substitution Principle
    • Interface Segregation Principle
    • Dependency Inversion Principle

    The code we use here are from Microsoft, DesignPatternSOLID,  

    Single responsibility

    Problem:

    Here we have a class with a method to sum two number and also a method to log those operations. Two different responsabilities:

    • Sum --- Line 11
    • LogCauculations --- Line 18

    Solution:

    We fix the problem by using the Single Responsibility Principle. We make two independent classes, each one has only one responsibility:

    • class Solution --- Line 8
    • public static class Logging --- Line 17

    Open/Close Pinciple

    Problem:

    Here we have a class does math calculation with 3 operations (Line 15, 18, and 21), how would we do if need to include others?

    Solution:

    We fix the problem by using the Open/Close Principle. We make a abstract class:

    • public abstract class BaseCalculation --- Line 7

    For each action or operation, we make a concrete class inheritaed from the base class with specific implementation:

    • AdditionCalculation : BaseCalculation --- Line 12
    • MultiplicationCalculation : BaseCalculation --- Line 19
    • SubtractionCalculation : BaseCalculation --- Line 27
    • DivisionCalculation : BaseCalculation --- Line 35

    Second Problem:

    Here we have a class does checking validations with 2 operations (Line 21 and 2), how would we do if need to include others?

    Solution:

    We fix the problem by using the Open/Close Principle. We make an interface, a abstration:

    • public interface IValidation --- Line 17

    For each action or operation, we make a concrete class inheritaed from the base class with specific implementation:

    • public class DomainValidation : IValidation<MailClass> --- Line 23
    • public class BodyValidation : IValidation<MailClass> --- Line 33

    this is the main (client) class:

    Liskov Principle:

    Problem:

    For Liskov principle, these statements should be valid [ref] that

    • Child class is a parent class.
    • Subclass is a Superclass.
    • Derived class is a base class.

    In the following example:

    • class SubstractionCalculation is class AdditionCalculation --- false statement, it is void to Liskov Substitution Principle.

    Solution:

    We fix the problem by using the Liskov Substitution Principle. We make a abstration:

    • public abstract class MethCalculate --- Line 7

    For each action or operation, we make a concrete class inheritaed from the base class with specific implementation:

    • public class Addition : MathCalculate --- Line 19
    • public class Subtraction : MathCalculate --- Line 30

    Interface Segregation Principle

    Problem:

    One interface IAnimal (Line 7) with 4 methods are used by two subclasses:

    • class Human : IAnimal --- Line 15
    • class Whale : IAnimal --- Line 37, this does not use all 4 methods in the interface.


    Solution:

    We fix the problem by using the Interface Regregation Principle. We make 4 smaller interfaces:

    • public interface IFeed --- Line 8
    • public interface IArgument--- Line 12
    • public interface IGroundMoviment--- Line 17
    • public interface IAirMoviment--- Line 21
    • public interface IWaterMoviment--- Line 25

    We make the concrete classes inheritaed from the specific interfaces they used:

    • public class Human :  IGroundMoviment, IArgument, IFeed--- Line 30
    • public class Whale : IWaterMoviment, IFeed --- Line 47


    Dependency Inversion Principle

    Problem:

    class BusinessLayer is tightly dependent on class RepositoryLayer on Line 11.

    Solution:

    We fix the problem by using the Dependency Inversion Principle. Use Dependency Injection technique

    • Make interface for IRepositoryLayer --- Line 23
      • Implemented by another concrete class
    • Let class BusinessLayer dependent on the abstract, the interface of IrepositoryLayer --- Line 11
      • that is injected into BusinessLayer through the interface of IRepositoryLayer --- Line 11

    References: