About Me

  • Magento addict since May 2007
  • I love to take challenges
  • I love to optimize performance
  • I love to train others on those matters

Are there any Software Architects?

Are there any Senior Developers?

Are there any Junior Developers?

Every developer in this room is an architect

We are all responsible for our Software Design

Architecting software is hard...

For example in the beggining of 2007

ZF1 just went into first beta (0.8.0)

Symfony 1.0 just got released

Composer?

Unit testing was not yet a thing

Everyone was using Subversion (SVN)

I wish I knew everything I know now back then

But then we wouldn't have this talk today

Majority of Magento 2.x modules are refactor of legacy 1.x ones

Challenge #0: Using Magento 1.x approach

Magento 2.x is a huge step ahead, learning new concepts hard at first

I am happy Magento 2.x does not use Symfony and Doctine

Symfony has an excessive configuration boilerplate

Doctrine is bound to its multi-vendor approach and forces your code style

Challenge #1: Looking at the core modules to create your own functionality

There are some new code, but mostly it is still good old Magento 1.x code

Do not look at the core module for an example of implemenation.

Even Magento_Customer module is not the best example.


namespace Magento\Customer\Model\Customer;

class Customer extends \Magento\Framework\Model\AbstractModel
{
    public function __construct(
    	\Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Eav\Model\Config $config,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Customer\Model\ResourceModel\Customer $resource,
        \Magento\Customer\Model\Config\Share $configShare,
        \Magento\Customer\Model\AddressFactory $addressFactory,
        \Magento\Customer\Model\ResourceModel\Address\CollectionFactory $addressesFactory,
        \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder,
        GroupRepositoryInterface $groupRepository,
        \Magento\Framework\Encryption\EncryptorInterface $encryptor,
        \Magento\Framework\Stdlib\DateTime $dateTime,
        CustomerInterfaceFactory $customerDataFactory,
        DataObjectProcessor $dataObjectProcessor,
        \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
        \Magento\Customer\Api\CustomerMetadataInterface $metadataService,
        \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = []
    ) {
    }
}

So avoid looking into Magento core modules

Look at http://devdocs.magento.com/ instead

Challenge #2: Data model dependencies

Global Website Store (GWS)

Binding your data model to GWS leads to scaling issues of your implementation

Example

  • EU Merchant can sell to 28 member states
  • Countries might have more then one language
  • Every country might get own domain name
  • Price might differ per country

Problem

  • You might end up with 100+ store views
  • Language+Country results in data duplications in EAV structure

Avoid existing structures where possible and inverse your dependencies

Challenge #3: Extending existing functionality

Rewrite (preference) is a bad thing

Plugin is not a good thing either

Plugin disadvantages

  • It is very hard to debug
  • It is global for an area
  • It can affect performance

Local Dependency override is a good thing

How To

  • Find exact dependency you need to modify for customization
  • Create a decorator that implements same interface
  • Pass it into a class via di.xml

Challenge #4: Depending on concrete implementation

Injecting concrete class from another component leads to fragile dependency


namespace Vendor\ProductCustomization\Model;

class SomeClassThatDependsOnProduct
{
    public function doSomethingWithProduct(\Magento\Catalog\Model\Product $product)
    {
    	// Bunch of code lines
        $category = $product->getCategory();
        // Bunch of other code lines
    }
}

Protect your code by introducing own abstractions

How To

  • Find functionality you want to use from Magento 2 module
  • Create your own interface for that implementation
  • Create an adapter based on that interface with Magento 2 module class as dependency

Over-engeneering?

  • You have to modify only adapter in case of breaking change
  • Your code is easier to test
  • Your code is protable

You are abstracting your business logic from concerete framework implementation

It means you can re-use your business logic in Magento 1.x or any other platform

We have to learn from Magento 1.x mistakes

Thank You

Q&A