Programing consepts made easy !

Learn learn learn, do not stop learning.

Back to all posts

PHP SOLID PRINCIPLES MADE EASY

Posted by Lotfio Lakehal on May 20, 2018

As stated in Wikipedia SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible and maintainable. The principles are a subset of many principles promoted by Robert C. Martin. Though they apply to any object-oriented design, the SOLID principles can also form a core philosophy for methodologies such as agile development or adaptive software development. The theory of SOLID principles was introduced by Martin in his 2000 paper Design Principles and Design Patterns, although the SOLID acronym itself was introduced later by Michael Feathers.

The SOLID acronym consists of :

  • (SRP) The Single Responsibility principle
  • (OCP) The Open Closed principle
  • (LSP) The Liskov Substitution principle
  • (ISP) The Interface Segrigation principle
  • (DIP) The Dependency Inversion principle

1 SRP The Single Responsibility Principle :

Uncle Bob explains that "A class should have one, and only one, reason to change" meaning when changing a class there must be only one reason for this change

Here is an example of a class that doesn't follow the single responsibility



<?php

// Single Responsibility Principle Violation

class Report
{
  /**
   * get report title method
   * @return  string
   */
  public function getTitle()
  {
      return 'Report Title';
  }

  /**
   * get report date method
   * @return  string
   */
  public function getDate()
  {
      return '2016-04-21';
  }

  /**
   * get report contents
   * @return  array
   */
  public function getContents()
  {
      return [
          'title' => $this->getTitle(),
          'date' => $this->getDate()

      ];
  }

  /**
   * format report to json
   * @return  object
   */
  public function formatJson()
  {
      return json_encode($this->getContents());
  }
}
?>



This class Is violating the SRP since it is doing more than one job it is getting the report information from one side and formatting the report information from the otherside. a good solution for this is to have a separate formatter class.

Here is a refactored version which respects the single responsibility principle.




<?php

//Refactored

class Report
{

  /**
  * get report title method
  * @return  string
  */
  public function getTitle()
  {
    return 'Report Title';
  }

  /**
   * get report title method
   * @return  string
   */
  public function getDate()
  {
    return '2016-04-21';
  }

  /**
   * get report contents method
   * @return  array
   */
  public function getContents()
  {
    return [
        'title' => $this->getTitle(),
        'date' => $this->getDate()
    ];
  }
}

class ReportFormatter
{
    /**
     * report formatter
     * @param    Report $report
     * @return  object
     */
    public function format(Report $report)
    {
        return json_encode($report->getContents());
    }
}
?>


              

Now it looks better, we have two separate classes with two different responsibilities so if we have a report error we w'll head directly to the Report class and if we have a formatting error w'll head to the Formatter class.

Some people may say that by using the SRP we are going to end up having too many classes which is true. However having a lot of organised separate classes will make it easy to maintain and change these classes in the future rather than having one monolithic class.

2 OCP The Open Closed Principle :

Uncle Bob considered this principle as the “the most important principle of object-oriented design”.

The principle states that software entities (classes, modules, functions, etc..) should be open for extension, but closed for modification.
It means that the behavior of the module can be extended. That we can make the module behave in new and different ways as the requirements of the application change, or to meet the needs of new applications. However The source code of such a module is inviolate. No one is allowed to make source code changes to it.
Every time we need to implement new requirement and we modify existing code, it’s OCP violation.
Here is an example That violates the open closed principle :




<?php

class Programmer
{
    public function code()
    {
        return 'coding';
    }
}
class Tester
{
    public function test()
    {
        return 'testing';
    }
}

class ProjectManagement
{
    public function process($member)
    {
        if ($member instanceof Programmer) {
            $member->code();
        } elseif ($member instanceof Tester) {
            $member->test();
        };
        throw new Exception('Invalid input member');
    }
}

?>

Here we are violating the open closed principle since we need to change our ProjectManagement class each time we need a new functionality

Terefore we need to focus on Abstraction which is the key.

Here is an example a good code that does not voilate the OCP

               


<?php

interface Workable
{
    public function work();
}

class Programmer implements Workable
{
    public function work()
    {
        return 'coding';
    }
}

class Tester implements Workable
{
    public function work()
    {
        return 'testing';
    }
}

class ProjectManagement
{
    public function process(Workable $member) // by using DI w'll have less decoupled code !
    {
        return $member->work();
    }
}

?>