Skip to content

Latest commit

 

History

History
107 lines (78 loc) · 3.65 KB

File metadata and controls

107 lines (78 loc) · 3.65 KB

Analysis of the Example Code

<?php

namespace App\Solid\DIP\Bad;

class Calculator
{
    public function Add(float $x, float $y) : float
    {
        return $x + $y;
    }

    public function Minus(float $x, float $y) : float
    {
        return $x - $y;
    }

    // what happen if we want to add more method ex: Multiply?
}

Poor Design Analysis

  1. Lack of Abstraction:

    • Violation of Dependency Inversion Principle (DIP): The Calculator class is not designed with abstractions. According to DIP, high-level modules should not depend on low-level modules. Instead, both should depend on abstractions. In this code, the Calculator class is a concrete implementation that lacks an abstraction (an interface or abstract class). As a result, any change to the calculation logic or addition of new operations (like Multiply) requires modifying the Calculator class directly, which is a violation of the open/closed principle as well.
  2. Difficulty in Extensibility:

    • Rigid Design: Adding new methods (such as Multiply, Divide, etc.) requires modifying the Calculator class. This approach tightly couples the functionality with the class itself. A better design would use interfaces or abstract classes to define a contract for calculations, allowing different implementations to be swapped in without modifying existing code.
  3. Scalability Issues:

    • Potential for Monolithic Class: As more methods are added, the Calculator class could become large and unwieldy. This makes it harder to maintain and understand. For example, if you need to support more complex operations or different types of calculators, the class will need to be modified extensively.
  4. Violation of Single Responsibility Principle (SRP):

    • Mixing Concerns: The Calculator class is responsible for performing various calculations. By adding more methods directly to this class, it starts handling multiple responsibilities, which can be split into different classes or interfaces. Each class should have a single responsibility to keep the design clean and maintainable.

Improved Design

To adhere to the Dependency Inversion Principle and improve the design, you could refactor the code as follows:

  1. Define an Interface:

    <?php
    
    namespace App\Solid\DIP;
    
    interface CalculatorInterface
    {
        public function calculate(float $x, float $y): float;
    }
  2. Implement the Interface:

    <?php
    
    namespace App\Solid\DIP;
    
    class AddCalculator implements CalculatorInterface
    {
        public function calculate(float $x, float $y): float
        {
            return $x + $y;
        }
    }
    
    class MinusCalculator implements CalculatorInterface
    {
        public function calculate(float $x, float $y): float
        {
            return $x - $y;
        }
    }
  3. Use Dependency Injection:

    <?php
    
    namespace App\Solid\DIP;
    
    class CalculatorService
    {
        private $calculator;
    
        public function __construct(CalculatorInterface $calculator)
        {
            $this->calculator = $calculator;
        }
    
        public function performCalculation(float $x, float $y): float
        {
            return $this->calculator->calculate($x, $y);
        }
    }

In this improved design:

  • Abstraction is introduced by using CalculatorInterface.
  • Dependency Injection is used to inject the specific implementation of the calculator into the CalculatorService.
  • New functionalities can be added without modifying existing code, adhering to the open/closed principle.
  • Each class has a single responsibility, making the design cleaner and easier to maintain.