DEPENDENCY INJECTION in MAgento 2



Agenda Motivation Object Composition Object Lifestyle Interception

Motivation: Complexity

Software Entropy

Wrong Approach Service location

new => Mage::getXXX();

Problems with service location Implicit dependencies

God classes

Code coupling made easy

Complexity Made Easy

Complex things should be hard to do in application while simple things should be easy. ~Rich Hickey



Solution Dependency Injection

Object is abstracted from dependencies through constructor signature

Explicit dependencies

Honest interfaces

Controlled code coupling

Unit testable code

Pillar 1: Object Composition



class Magento_Acl_Resource { protected $_resourceProvider; protected $_resourceFactory; public function __construct( Magento_Acl_ResourceProvider $resourceProvider, Magento_Acl_ResourceFactory $resourceFactory, $prefix = 'prefix' ) { $this->_resourceProvider = $resourceProvider; $this->_resourceFactory = $resourceFactory; $this->_prefix = $prefix; } }



Composition ROOT http://blog.efvincent.com/di-bootstrap/

class Magento_Acl_Resource { protected $_resourceProvider; protected $_resourceFactory; public function __construct( Magento_Acl_ResourceProvider $resourceProvider, Magento_Acl_ResourceFactory $resourceFactory, $prefix = 'prefix' ) { $this->_resourceProvider = $resourceProvider; $this->_resourceFactory = $resourceFactory; $this->_prefix = $prefix; } }



class Magento_Acl_Resource { protected $_resourceProvider; protected $_resourceFactory; public function __construct( Magento_Acl_ResourceProviderInterface $resourceProvider, Magento_Acl_ResourceFactory $resourceFactory, $prefix = "somePrefix" ) { $this->_resourceProvider = $resourceProvider; $this->_resourceFactory = $resourceFactory; $this->_prefix = $prefix; } }



<config> <type name="Magento_Acl_Resource"> <param name="resourceProvider"> <instance type="Magento_Acl_ResourceProvider" /> </param> </type> </config>

<config> <preference for="Magento_Acl_ResourceProviderInterface" type="Magento_Acl_ResourceProvider" /> </config>

Virtual Types Provide ability to configure set of instances for some class. <config> <virtualType name="customAclResource" type="Magento_Acl_Resource"> <param name="prefix"> <value>someOtherPrefix</value> </param> </virtualType> <type name="Magento_Acl_Builder"> <param name="resource"> <instance type="customAclResource"/> </param> </type> </config> Provide ability to configure set of instances for some class.

Pillar 2: Object Lifetime

Injectables

Non-Injectables

Injectables Mostly services or value objects

Mostly stateless

Mostly singletons

Can be shared or non-shared

Don't confuse with Singleton Pattern

Non-shared injectable <config> <type name="Magento_Acl_ResourceProvider" shared="false" /> </config> or

<config> <type name="Magento_Acl_Resource"> <param name="resourceProvider" shared="false" /> </type> </config> or

Factories Created for non-injectables

Are injectables

Can be auto-generated

Optional dependencies class Magento_Acl_Resource { protected $_resourceProvider; protected $_resourceFactory; public function __construct( Magento_Acl_ResourceProviderInterface $resourceProvider, Magento_Acl_ResourceFactory $resourceFactory, $prefix = "someId" ) { $this->_resourceProvider = $resourceProvider; $this->_resourceFactory = $resourceFactory; $this->_prefix = $someId; } }



Proxies Object-oriented way to do lazy-loading

Resposible for lazy-loading only

Can be auto-generated <config> <type name="Magento_Acl_Resource"> <param name="resourceProvider" type="Magento_Acl_ResourceProviderProxy" /> </type> </config>



Pillar 3: Interception



Interception Description Ability to observe public calls.

Interception Demo

Interception Limitations Private calls

Methods with final classes

Performance

The book

