Magento 2 Solid Principle

As soon as you start working with OOPs we came to know about sevral design pattern and SOLID principle is the first thing that we can across. As per magento technical guidelines (under class design)

Object decomposition MUST follow the SOLID principles

If you check the Magento code than you can clearly see that Magento code is following SOLID principles. We will look into it these principle one by one:-

SOLID stands for:

  • Single Responsibility
  • Open-Closed
  • Liskov Substitution
  • Interface Segregation
  • Dependency Inversion

Single Responsibility Principle

A class should have only and only one reason to change.

As its name suggest, it states that every object should have single responsibility i.e, single role to perform and that responsibility should be entirely encapsulated by the class. It means that when we are adding some unrelated feature they should not affect same class.
For example, In Magento 2 every controller has just one responsibility.

namespace Magento\Cms\Controller\Page;

class View extends \Magento\Framework\App\Action\Action {

    public function execute() {

        $pageId = $this->getRequest()->getParam('page_id', $this->getRequest()->getParam('id', false));
        $resultPage = $this->_objectManager->get(\Magento\Cms\Helper\Page::class)->prepareResultPage($this, $pageId);
        if (!$resultPage) {
            $resultForward = $this->resultForwardFactory->create();
            return $resultForward->forward('noroute');
        }
    return $resultPage;
    }
}

Open-Closed Principle

Objects or entities should be open for extension, but closed for modification.

The above statement itself explains everything that it should be always easy to make behaviour change of particular implementation but we should make changes directly into the original source code. We should make changes by extending the class.

For example, In Magento 2 if you check module-catalog/Controller/Adminhtml/Category.php it is just initiating category object and rest of the actions (such as:- move, refresh page) are using it by extending the \Magento\Catalog\Controller\Adminhtml\Category class and making behaviour changes as per the requirement.

namespace Magento\Catalog\Controller\Adminhtml\Category;

class Move extends \Magento\Catalog\Controller\Adminhtml\Category {

    public function execute() {
        
        $parentNodeId = $this->getRequest()->getPost('pid', false);
        $prevNodeId = $this->getRequest()->getPost('aid', false);
        ............
    }
}

Liskov substitution principle

This principle states that any substitute/child class (implemented by either extension or dependency injection) should adhere the same rules as its predecessor class i.e, it should not break the functionality that is already being used by keeping method signature consistent.

For example, in below example you can see that toOptionArray() in both class return an array


namespace Magento\Ups\Model\Config\Source;

use Magento\Shipping\Model\Carrier\Source\GenericInterface;

class Generic implements GenericInterface {

    public function toOptionArray()
    {
        $configData = $this->carrierConfig->getCode($this->_code);
        $arr = [];
        foreach ($configData as $code => $title) {
            $arr[] = ['value' => $code, 'label' => __($title)];
        }
        return $arr;
    }
}
namespace Magento\Ups\Model\Config\Source;

class OriginShipment extends \Magento\Ups\Model\Config\Source\Generic

{
    protected $_code = 'originShipment';
    public function toOptionArray()
    {
        $orShipArr = $this->carrierConfig->getCode($this->_code);
        $returnArr = [];
        foreach ($orShipArr as $key => $val) {
            $returnArr[] = ['value' => $key, 'label' => $key];
        }
        return $returnArr;
    }
    return $returnArr;
    }
}

Interface Segregation

This states that we should not use those method or properties in the interface that the client may not use. Rather than having all method which are related to responsibility it’s good to break it into multiple interfaces and let a single class extends multiple interface. For example see the below image:-

Dependency Inversion principle

High level module should not depend on low level moduleFirst of all keep in mind that dependency inversion is not same as dependency injection, although they go hand in hand.

Leave a Comment.