how i ended up touching magento core

89
© 2017 Magento, Inc. Page | 1 ‘17 @aleron75 How I ended up touching Magento core Alessandro Ronchi - Bitbull

Upload: alessandro-ronchi

Post on 29-Jan-2018

122 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 1 ‘17@aleron75

How I ended up touching Magento core

Alessandro Ronchi - Bitbull

Page 2: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 2 ‘17@aleron75

Nice to meet you! “I believe in passion, innovation, and continuous improvement.” ~ @aleron75

Nice to meet you!

First of all, let me say thank you to the people who wanted me here on stage, the ones who let me be here and you that chose to dedicate some of your time to listen to me.

My name is Alessandro Ronchi, I’m from Italy and I work as COO and Developer at a fully remote company named Bitbull.

We help other companies to grow their business on-line building up solutions that involve Magento platform.

Page 3: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 3 ‘17@aleron75

Introduction

I’m here today to tell you:

- the story of how I was involved into the Multi-Source Inventory project,

- the lessons I learned along the way

- and why and how you can contribute and finally feel proud and not ashamed of touching the Magento core :)

Page 4: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 4 ‘17@aleron75

Multi-Source Inventory(MSI)

First of all, let me briefly introduce what the Multi-Source Inventory Project is.

Page 5: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 5 ‘17@aleron75

Catalog Inventory ++

Multi-Source Inventory (MSI)

MSI is an evolution of the Catalog Inventory module.

It allows to:* define multiple sources for product items (e.g. physical

warehouses or brick & mortar stores)* aggregate different sources into stocks that determine

the real availability of a product* bind stocks to sales channels, that is, where a user can

buy items from. Channel example: website.

It allows to defer source selection during checkout thanks to reservations mechanism thus avoiding slowdowns during that conversion-critical phase.

It allows to apply different source selection algorithms when processing an order; more algorithms will be likely added in future releases and can also be developed by 3rd parties.

Page 6: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 6 ‘17@aleron75

Magento 2.3

Multi-Source Inventory (MSI)

MSI is a set of modules that will be bundled with Magento Open Source edition, so it will be a freely available resource for Magento Community.

MSI will be likely released with Magento 2.3.

Initially it will co-exist with Catalog Inventory that will be deprecated in the future.

Page 7: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 7 ‘17@aleron75

MVP

Multi-Source Inventory (MSI)

The first release is considered an MVP, that stands for “Minimum Viable Product” and represents the very first set of functionality intended to satisfy early adopters of the module and to begin collecting feedback from them.

Business value: ability to manage inventory data in Admin Panel and through import/export functionality; source selection by-priority.

The module will be continuously improved, a set of additional functionality for future releases has already been created and will grow in time.

Note that you can take part in this evolution.

Page 8: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 8 ‘17@aleron75

Community + MCE team

Multi-Source Inventory (MSI)

The project was presented on May 2017 during the Contribution Days of Meet Magento Germany.

It represents a new approach to contributing to Magento: to achieve the result, an open group of volunteers from the community works together with the Magento Community Engineering team.

I joined the group on July 2017 because I:- was interested in the module’s functionality,- wanted to grow my knowledge of Magento 2 core and - was attracted by this new kind of collaboration.

My first pull request was merged after only one month. In that short period I learned a lot of things and I’m here to share some of them with you right now.

Page 9: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 9 ‘17@aleron75

MSI: Opportunities

First of all, let me tell you what are the most valuable opportunities that working on this project offers in my opinion.

Page 10: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 10 ‘17@aleron75

Learn by working

on M2 core

MSI: Opportunities

Magento 2 is a big framework and it can’t be learned in a week or so.

I’m a big fan of learn by doing and this project is a great opportunity to delve into Magento 2 core by doing something practical and useful at the same time.

Page 11: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 11 ‘17@aleron75

Best Practices

from the architects

MSI: Opportunities

The project offers the chance to learn best practices directly from Magento architects.

Thus, writing code supervised by them represents a great learning opportunity.

Page 12: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 12 ‘17@aleron75

See the future

MSI: Opportunities

Since a project like this is intended to work with future releases, it pushes to learn and apply new concepts and achitectural changes in advance.

I will indeed show some of them during this presentation.

Page 13: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 13 ‘17@aleron75

Work with smart people

MSI: Opportunities

Last, but not least, I have the privilege to work and train with smart people, both from the Magento core team and the Community: Igor Miniallo, Valeriy Nayda, Lars Roetting, Vadim Justus only to mention some of them.

You can be the next ones.

Page 14: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 14 ‘17@aleron75

MSI: Benefits

There are also concrete benefits that this project offers.

Page 15: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 15 ‘17@aleron75

Self improvement

MSI: Benefits

The very first benefit I recognized by joining such a project is self improvement.

Not only as a professional but also as an individual, since it is a way to give back something to a community that nurtured and inspired me for years.

Page 16: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 16 ‘17@aleron75

The module itself!

MSI: Benefits

The MSI module is a benefit itself because it’s a very valuable piece of functionality that will be used by thousands of merchants and will also open up new possibilities in Magento like, for example, drop-shipping.

Page 17: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 17 ‘17@aleron75

Inspiration

MSI: Benefits

All the work I do generates inspiring material to share.

I’m here speaking about it, as you can see, and I already wrote a couple of articles on the subject and more will come.

Not to mention the value of applying all the lessons learned to our everyday job.

Page 18: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 18 ‘17@aleron75

SWAG!

MSI: Benefits

All nerds love stickers, tees, and swag in general and Magento is a company that doesn’t spare about this.

I received my tee, my stickers and other cool gadgets that make me feel so happy and appreciated.

I’m sure the same will apply to you.

Page 19: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 19 ‘17@aleron75

Lessonslearned

Ok, my overview of the MSI Project ends here, now it’s time to delve into more technical details.

Page 20: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 20 ‘17@aleron75

Domain Driven Design

Let’s start introducing Domain Driven Design.

How many of you already know DDD?

Ok good, let’s begin with the basic principles of DDD.--Note: if almost everyone raises hand, skip to DDD in

MSI

Page 21: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 21 ‘17@aleron75

DDD - Principles

Let’s start introducing Domain Driven Design principles.

Page 22: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 22 ‘17@aleron75

"DDD is about designing

software based on models

of the underlying domain." M. Fowler

DDD - Principles

In this quote by Martin Fowler I highlighted the most important words describing DDD.

DDD is not a methodology or a paradigm; it’s an approach (a set of tools) that helps us making decisions about how our software should be designed to address a business problem (domain).

It is focused on modeling the domain & the domain logic because that’s where the business value is.

DDD changes our data-driven perspective and pushes focusing on business intents.

Page 23: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 23 ‘17@aleron75

"DDD is developing

Ubiquitous Language within

Bounded Context."

V. Vernon

DDD - Principles

In this definition of DDD, Vaughn Vernon doesn’t even mention software and focuses on two fundamental concepts.

The development of an ubiquitous language that speaks the language of the domain experts, reducing its distance from the development team.Remember: there is no CRUD in real life.

The contextualization of models by defining the domain boundaries in which models are simpler, not ambiguous.

E.g.: what does “book” mean? We need to identify a context to answer properly.

Page 24: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 24 ‘17@aleron75

Behaviour

vs

Properties

DDD - Principles

This is another principle that helps to change how our data-driven brains think: expose behavior rather than properties.

This way we are forced to avoid reducing the domain to an abstraction of the data model.

Page 25: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 25 ‘17@aleron75

OrderInterface { // exposing properties  public function setCustomerName(string $name);  public function setCustomerEmail(string $email);  public function setCustomerPhone(string $phone);}

­ vs ­

OrderInterface { // exposing behavior  public function assignCustomer(CustomerInterface $customer);}

DDD - Principles

Here is a code example of what exposing the ‘Behavior vs Properties’ principle means.

Instead of exposing a list of setters, we can expose a single method that has the same effect of the above setters but clearly identifies the intent.

Page 26: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 26 ‘17@aleron75

● DRY

DDD - Principles

In DDD we abandon the “Don’t Repeat Yourself” principle.

Staying away from sharing domain models helps reducing scope and complication and facilitates the definition of an ubiquitous language within a context.

Page 27: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 27 ‘17@aleron75

Contextual validation

DDD - Principles

This is one of the most discussed topic in DDD.

Does validation belong to domain models or contexts?

One practical opinionated answer is: both.

E.g. an Order needs a Number and a Customer to be an Order; it can't exist (can't be instantiated) without these two properties (called invariants); validate all other properties in proper contexts; e.g.: only when we want to issue an invoice for the order, we need a billing address.

Page 28: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 28 ‘17@aleron75

DDD - Building blocks

Now that we have seen the basic principles of DDD, let’s see which are some of its building blocks, since we will encounter them in MSI and in Magento.

Page 29: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 29 ‘17@aleron75

Domain Models

DDD – Building blocks

Using the words of Martin Fowler, we can summarize the definition of a Domain Model in

"an object model of the domain that incorporates both behavior and data."

Domain models are typically composed of elements such as entities, value objects, aggregates, and described using terms from an ubiquitous language.

Page 30: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 30 ‘17@aleron75

<Domain Model>

Entity

DDD – Building blocks

Domain Models can be implemented in several ways, depending on what they need to express.

Entities are objects defined by their unique indentity that is persisted over time.

E.g. an Order can be an entity in the Sales context.

Page 31: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 31 ‘17@aleron75

<Domain Model>

Value Object

DDD – Building blocks

Value objects are identified by their immutable state, that is, the values of their properties.

Typically they are not persisted “stand alone” but as part of an Entity.

E.g. a Billing Address can be considered a Value Object in the context of a Sales Order: we don’t necessarily need to assign an identity attribute to it; we persist that value object in the Order Entity.

But in the context of Customer Profile, a Billing Address becomes an entity to allow the Customer to persist it over time and to set it as the “default” address among others.

Page 32: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 32 ‘17@aleron75

<Domain Model>

Service

DDD – Building blocks

Services are stateless processes defined by their behavior.

In an object oriented paradigm, a service is implemented as a functional object.

We will return to this topic later, when I’ll show you how Services are implemented in Magento.

Page 33: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 33 ‘17@aleron75

<Domain Model>

Aggregate

DDD – Building blocks

Aggregates are entities and VOs that are grouped together to express consistent relations.

Generally they represent a transactional unit.

E.g.: think to a Sales Order as an aggregate, that is, a combination of entities (Order master data, Order Items, Transactions) and value objects (Customer email, Shipping address, Billing address).

Page 34: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 34 ‘17@aleron75

<Domain Model>

Aggregate Root

DDD – Building blocks

An aggregate root is the main object of an aggregate, its entry point.

In the Sales Order example, the Order is the aggregate root through which we can access to its Order Items, Customer data, Transactions, etc.

Page 35: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 35 ‘17@aleron75

Bounded Contexts

DDD – Building blocks

Bounded Contexts are units that define the context for a model and the scope of a ubiquitous language.

Think to the previous example of an Address: within a Sales Order context, we don’t need to treat it as an entity meanwhile in the Customer Profile context an Address, other that an identity, has also other properties (for example “is_default”).

Sharing the same model in different contexts isn’t recommended: e.g. the “is_default” property hasn’t any meaning in the Sales Order context.

Bounded Contexts help us focusing on what an object really represents in a specific context.

Page 36: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 36 ‘17@aleron75

Anti-corruption Layers

DDD – Building blocks

Anti-corruption layers mediate communication b/w different Bounded Contexts to keep models clean and consistent.

E.g.: a Customer doesn’t need a Billing Address to be valid in the Customer Profile but a Billing Address is required if the Customer wants to submit an Order.

Page 37: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 37 ‘17@aleron75

DDD in MSI

Now that we have seen what are the main principles and building blocks of DDD, let’s see some examples of DDD applied in MSI Project.

Page 38: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 38 ‘17@aleron75

<Domain Model>

Reservation

DDD in MSI

A Reservation is an example of Domain Model in MSI.

It has an identity which is persisted over time, this makes it an Entity, even if it doesn’t extend Magento’s AbstractModel.

In Magento, an AbstractModel is used for extensible entities but Reservations are not extensible so we had no need to “share domain models”.

This is an example of DRY.

Page 39: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 39 ‘17@aleron75

<Bounded Contexts>

Inventory modules

DDD in MSI

In MSI, there are several modules (all beginning with the “Inventory” prefix) each of which represents a Bounded Context.

The Inventory module contains the domain models and the behaviors that belong to the stock management context.

When it comes to concepts that are not directly related to stock management, they are modeled elsewhere.

E.g., the concept of a “default source” has a meaning when managing a catalog of products. There is no “default source” in stock management, so the “default source” concept is modeled under the InventoryCatalog module.

For analogous reasons we have InventorySales, InventoryImportExport and more could come.

We know, this seems a lot or repetition but we have seen that, in DDD, this brings to simplification and it is preferred to DRY principle.

Page 40: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 40 ‘17@aleron75

Behavior = Services

DDD in MSI

As mentioned before, Services are a way to model behaviors.

In MSI we have domain services like ReservationsAppend or AssignSourcesToStock.

They are modeled as atomic behaviors and speak the domain’s language.

Services like the ones above, offer the additional benefit to save multiple entities in one step, thus avoiding multiple calls and reinforcing data consistency.

Page 41: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 41 ‘17@aleron75

DDD in MSI

I take the chance to show how much Magento is open to considering the opinion of the Community, asking how a functional object should be implemented:

1) exposing a single method, typically named “execute”, or

2) implementing the __invoke magic method

As you can see, the preference goes to the expose method.

Page 42: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 42 ‘17@aleron75

Valid entities

DDD in MSI

In MSI we deal with valid entities: entities that can only be instantiated with their invariants in a valid state.

The object instantiation process has the responsibility to create valid entities.

Creational patterns (factory and builder) exploit a chain of validators that can be composed (and extended) via di.xml.

Validators returns a ValidationResult object and a ValidationException is thrown as a part of the contract of the service in which validation occurs.

Page 43: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 43 ‘17@aleron75

<preference     for="Magento\Inventory\Model\Source\Validator\SourceValidatorInterface"         type="Magento\Inventory\Model\Source\Validator\ValidatorChain"/>  <type name="Magento\Inventory\Model\Source\Validator\ValidatorChain">    <arguments>      <argument name="validators" xsi:type="array">        <item           name="name"           xsi:type="object">Magento\Inventory\Model\Source\Validator\NameValidator</item>        <item           name="postcode"                       xsi:type="object">Magento\Inventory\Model\Source\Validator\PostcodeValidator</item>        ...   </argument>  </arguments> </type></preference>

DDD in MSI

Here is an example of validation chain declaration for the Source entity.

The SourceValidatorInterface is injected into the service and is used to validate the entity.

SourceValidatorInterface::validate() return a ValidationResult; if the result contains validation errors, a ValidationException is thrown, as declared in the service contract.

Page 44: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 44 ‘17@aleron75

Command Query

Responsibility Segregation

Now let’s see another important topic: the Command Query Responsibility Segregation pattern and its usage into the MSI Project.

Page 45: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 45 ‘17@aleron75

Architectural pattern

CQRS

CQRS is a low-level software design pattern that guides us to think of data reads (queries) and writes (commands) as separate systems that may require distinct models and architectures (but not necessarily separated data stores).

Not to be confused with a Reporting DB: CQRS is an architectural pattern.

Page 46: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 46 ‘17@aleron75

DDD not required, but...

CQRS

DDD is not required but they often go together because they have some things in common.

For example, both focus on domain and on same concepts like the DRY principle.

Page 47: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 47 ‘17@aleron75

Better understanding

of state changes

CQRS - PROs

Let’s start examining some benefits of using CQRS pattern.

CQRS gives a better understanding of what does and what does not change the state of the system.

Page 48: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 48 ‘17@aleron75

Domain simplification

CQRS - PROs

Separation of read/write responsibility brings to domain simplification: a single model is no more responsible for both operations, thus it can be split into two simpler models.

Page 49: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 49 ‘17@aleron75

Easier changes

CQRS - PROs

Simpler models makes it easier to apply changes in business rules.

After all, the possibility for a software to change and adapt to business requirements is what makes it really valuable.

“A working program that is practically impossible to change will become useless very soon; a non-

working program that is easy to change will become and remain useful over time”

Robert Martin (Clean Architecture)

Page 50: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 50 ‘17@aleron75

Task-based UIs

CQRS - PROs

Given the task-oriented nature of CQRS, it helps designing better task-based UIs.

Let’s remember what we said about DDD: CRUD is not how the real world always works; real world is mostly based on behaviors and commands activate behaviors.

Mapping the UI to domain commands could improve user interaction, guiding the user through a process instead of forcing him/her to adapt to our data-driven mental model.

Page 51: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 51 ‘17@aleron75

Better scalability

CQRS - PROs

Think to a typical situation in which many users continuously access a product catalog, that means they are reading information from our system.

But only a few of them (collaboratively) update those products.

Put differently, in many situations reads exceed writes.

In those situations, separating reads from writes allows us to better scale our application.

Page 52: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 52 ‘17@aleron75

More analysis

CQRS - CONs

We don’t have to forget that with great benefits come great drawbacks.

First of all, applying CQRS requires more effort in analysis and modeling.

We don’t have to underestimate the impact of this additional complication.

Page 53: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 53 ‘17@aleron75

Duplication handling

CQRS - CONs

The benefits that come from separating read and write models must be compared to the effort needed to handle model duplication.

Remember that in CQRS, like in DDD, the DRY principle is not applied.

And, again, with duplication comes complication.

Page 54: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 54 ‘17@aleron75

Eventual consistency

CQRS - CONs

With CQRS, consistency is no more guaranteed by the underlying system.

We must handle data consistency and analyze in which circumstances data can be inconsistent.

There are contexts, especially those implying transactions, in which CQRS could not be the right choice.

Page 55: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 55 ‘17@aleron75

"If all you have is a hammer,

everything looks like a nail"

A. Einstein

CQRS - CONs

To summarize, stay away from the “Hammer syndrome”: CQRS is not “the answer to life the universe and everything”;

CQRS is only a pattern that can bring great benefits in some contexts and unwanted drawbacks in others.

Joke :-) since I don’t know who coined this sentence, I adopted the good practice of attributing it to Albert Einstein: when in doubt, say it’s from Albert Einstein, nobody will question it

(note, a valid alternative is Mark Twain)

Page 56: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 56 ‘17@aleron75

CQRS in MSI

Now that we have seen what CQRS is, let’s see how we apply it MSI.

Page 57: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 57 ‘17@aleron75

Source items

vs

Stock items

CQRS in MSI

One of the core concept of MSI, is the separation between these two entities: source Items and stock Items.

A source is typically a physical place where our goods are stored, like a warehouse, a depot, a brick & mortar store.

A source item is the entity in which we write product availability.

A stock is the aggregation of different sources that determines the general availability of a product across different sources.

A stock item is the entity in which we read product availability.

The following picture will help us better understand the segregation described above.

Page 58: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 58 ‘17@aleron75

CQRS in MSI

To simplify, this picture shows the quantities of a single product.

In the yellow sources we have the available quantity of a product.

The green stocks pick from different sources so their product availability is the sum of that of the sources they pick the product from.

Reservations represent an amount of product that can’t be considered available being reserved for incoming orders that still have to be fulfilled.

Blue sales channels are where we buy products; the salable quantity is given by the available quantity of the stocks they are related to.

Page 59: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 59 ‘17@aleron75

Index tables != CQRS

CQRS in MSI

The very first thing that I thought when I saw this kind of separation was: “Magento already has indexes, that are an aggregation of data, so it already applies CQRS!”

Not at all.

In Magento (1 and 2), indexes work under the hood, models hide how this aggregation works, we read and write data through the same model.

That’s not how CQRS works.

In MSI there is a clean separation between command and query models, that's what makes the real difference.

Page 60: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 60 ‘17@aleron75

Before switching to the next topic, let’s have a short motivational break.

I know that some things may seem hard to understand or put into practice.

It’s perfectly normal and that’s the reason why when you achieve a result, that is “special moment”, because it cost us something.

One of my favorite quotes is from Randy Pausch says: “brick walls are there to give us a chance to show how badly we want something”.

If you want to achieve a result bad enough, focus on it, work hard, avoid shortcuts and that special moment will come.

Page 61: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 61 ‘17@aleron75

Design Patterns

Now let’s see a couple of interesting design patterns that we use in MSI project.

The reason why I want to focus on them is because after having adopted them in Magento I realized how useful they can be in our everyday work.

Page 62: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 62 ‘17@aleron75

Design Patterns: Builder

https://refactoring.guru/design-patterns/builder

Builder is a creational pattern.

Creational patterns are responsible for flexible and reusable object creation mechanisms.

Other creational patterns that we have likely the chance to use in Magento 1 and 2 are factories and singletons.

A builder is used to construct complicated objects step by step.

It produces different representations of an object using the same building process.

Page 63: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 63 ‘17@aleron75

Reservation Builder

interface ReservationBuilderInterface{  public function setStockId(int $stockId): self;    public function setSku(string $sku): self;    public function setQuantity(float $quantity): self;    public function setMetadata(string $metadata = null): self;    /** @throws ValidationException */  public function build(): ReservationInterface;}

An example of builder that I personally implemented in MSI is the Reservation builder.

It encapsulates validation thus avoiding the instantiation of an invalid model.

Here we see its interface that’s the typical interface of a builder: a list of setters and a build() method which can either produce a valid model or throw a ValidationException.

Page 64: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 64 ‘17@aleron75

Reservation Builder

public function build(): ReservationInterface{  $validationResult = $this­>validate();  if (!$validationResult­>isValid()) {      throw new ValidationException(__(‘Validation error’));  }  // ...  // create instance using object manager and reset state  $this­>reset();  return $reservation;}

Here is a piece of code extracted from the build() method; here we can see that the very first step is checking validity of given properties (invariants).

Note also that before returning the instance, we reset the state of the builder to be sure that the next call won’t affect object creation.

Page 65: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 65 ‘17@aleron75

Reservation Builder

$reservation = $this­>reservationBuilder  ­>setStockId(10)  ­>setSku(‘somesku’)  ­>setQuantity(­8.5)  ­>build();

Finally, here is an example of how the builder is used.

The step by step creation process is clearly visible.

Page 66: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 66 ‘17@aleron75

Design Patterns: Facade

https://refactoring.guru/design-patterns/facade

Facade is a structural pattern.

Structural patterns are responsible for building simple and efficient class hierarchies and relations between different classes.

Other structural patterns that we have the chance to use in Magento 1 and 2 are adapters.

A Facade provides a simplified interface to a larger sub-system (classes, library or framework).

Page 67: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 67 ‘17@aleron75

Repository Facade

/** * @api */interface RepositoryInterface{  public function save(DataInterface $entityData);  public function get($entityId);  public function delete(DataInterface $entityData);  public function deleteById($entityId);  public function getList(SearchCriteriaInterface $searchCriteria);}

In MSI and in Magento in general, Repositories are an example of Facade: they make APIs more readable.

They allow the access to persisted entities exposing a subset of the predefined methods listed here.

This way, they reduce dependencies of business logic code on the inner workings of a module.

Note that repositories don’t apply the DDD principles since they adopt the CRUD convention.

Page 68: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 68 ‘17@aleron75

API/SPI

Let’s discuss about another relevant topic introduced on MSI, the segregation between two kind of interfaces: APIs (Application Programming Interfaces) & SPIs (Service Provider Interfaces).

Page 69: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 69 ‘17@aleron75

Service Contracts

API/SPI

APIs & SPIs are service contracts, that is, formal interface specifications for modules made up of (simpler) data interfaces (hiding entities complication) + service interfaces (encapsulating behavior/business logic)

The benefit of exposing public contracts is that they allow better modularization.

Segregation b/w API & SPI is important because it allows more customization, decreases coupling of components and clearly defines how our code will be affected by future releases of Magento.

The benefit of writing modules that rely only on API/SPI interfaces (public code) is that future changes in Magento’s private code won’t affect backward compatibility.

Page 70: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 70 ‘17@aleron75

Segregation given by us

API/SPI

It is the responsibility of third party developers to decide how they use interfaces declared in external modules.

Segregation is not not mutually exclusive: we can use the same interface both as an API and as an SPI.

Page 71: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 71 ‘17@aleron75

APIs are used

API/SPI

An interface is considered an API if we use it in our module without implementing it.

In other words: we inject a dependency from an API in our classes.

Future changes in Magento’s private code won’t affect backward compatibility.

Future changes in Magento’s public code won’t affect backward compatibility until the MAJOR version of the used API changes.

Page 72: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 72 ‘17@aleron75

SPIs are implemented

API/SPI

An interface is considered an SPI if we implement it in our module.

In other words: we write a class that implements an interface.

Future changes in Magento’s private code won’t affect backward compatibility.

Future changes in Magento’s public code won’t affect backward compatibility until the MINOR version of the implemented SPI changes.

Page 73: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 73 ‘17@aleron75

Backward compatibilityAPI: "require":{"magento/module­inventory": "~100.3"}

SPI: "require":{"magento/module­inventory": "~100.3.0"}

API/SPI

Here is a recap of how we should declare the dependency from a module in our composer.json based on how we used its interfaces.

Page 74: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 74 ‘17@aleron75

Repositories = APIs

Class commands = SPIs

API/SPI in MSI

MSI modules use Repository interfaces as APIs and implement CRUD Command Interfaces as SPIs.

An example of implemented SPI is:

Magento\Inventory\Model\Source\Command\SaveInterface

Page 75: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 75 ‘17@aleron75

Testing

Magento has put a great effort in providing a test-friendly framework with its new release.

Not by chance a new test automation framework has been just launched and presented at this conference.

Page 76: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 76 ‘17@aleron75

“Testing shows the presence,

not the absence of bugs”

E. W. Dijkstra

Testing

I like to start from this quote from Dijkstra: all we can do by writing tests is proving that our software is incorrect, we can’t demonstrate the opposite.

This is important to understand that a code coverage of 100% only means that we searched for bugs in 100% of our code and our research may be unsuccessful.

This doesn’t necessarily mean our sw is bug-free.

Put differently: testing doesn’t guarantee software correctness but it’s a very useful tool to discover bugs.

The more we decompose our sw in smaller components, the easier it will be to test it.

Page 77: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 77 ‘17@aleron75

Static

Testing

Static tests check the structure and the style of source code to guarantee the respect of defined coding standards.

Some examples: line length, interface names not ending with Interface, correct usage of short array notation, etc.

Page 78: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 78 ‘17@aleron75

Unit

Testing

Unit tests check the design and behavior of a single unit of code (e.g. a class in OOP) in isolation.

“In isolation” means that all the other components our single unit depends on are fake objects.

In comes without saying that less dependencies make it easier to write unit tests.

This is the reason why functional programming is gaining popularity, because it is based on pipelining functions rather than composing objects and on reducing the side effects typically due to mutable state objects.

This is an interesting topic but I don’t master it yet, sorry. I’m still on my way learning it and what motivates me to study it is to write less & simpler tests.

Page 79: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 79 ‘17@aleron75

Integration

Testing

Integration tests check the correct interaction between two or more components of the system.

Page 80: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 80 ‘17@aleron75

Functional

Testing

Functional tests are a sub-set of integration tests.

They check a feature end-to-end and can involve the interaction with the User Interface.

The new Magento Functional Testing Framework is just focused on writing functional tests.

Page 81: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 81 ‘17@aleron75

Testing in MSI

In MSI a TraviCI suite runs multiple tests and helps spotting out the introduction of coding style issues and software regressions.

The suite is composed by:

● Static tests● Unit tests● Integration tests● Functional tests for web APIs

We will likely delve into the new testing framework very soon.

Page 82: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 82 ‘17@aleron75

Contributing to MSI

Our journey has come to the end.

Now let me briefly give you some description of how contribution happens and how you can jump into the project.

Page 83: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 83 ‘17@aleron75

Open stand-up meeting

Contributing to MSI

Each Friday at 16.00 UTC there is a weekly remote stand-up meeting; it is open to everyone and is used to present the project progress and discuss next steps.

It’s the right way to approach the project and it’s how I actually jumped into the project.

Page 84: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 84 ‘17@aleron75

From questions

to development

Contributing to MSI

Any contribution is appreciated, even a question or a small fix to a comment or to documentation.

Dream big but start small: asking questions is how I started getting into the internals of MSI before writing and submitting any code.

Page 85: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 85 ‘17@aleron75

Pull Requests

Contributing to MSI

When you are ready to submit something (remember, even a single line of comment is precious), fork the repo, make a branch, apply changes and submit a Pull Request.

A PR is a way of proposing and discussing changes before they are integrated into the main development branch.

The review of a PR is a great opportunity to discuss and learn.

Don't be afraid of deleting code: deleted code doesn't break and doesn't require maintenance.

Page 86: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 86 ‘17@aleron75

[email protected]

Contributing to MSI

The best way to engage with the project is by dropping a line to [email protected].

You will be welcomed with open arms, just like happened to me.

Page 87: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 87 ‘17@aleron75

Conclusion

To recap a little bit, we’ve seen that contributing to MSI brings a lot of benefits and opportunities.

Participating in the project gives chances to learn and apply many new concepts and practices: after all, we can’t improve if we don’t get out of our comfort zone.

Last, but not least, we have the possibility to give back to an extraordinary project backed by a great company and an equally great community.

Page 88: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 88 @aleron75@aleron75

Thank you!A.M.A. @aleron75

Thank you so much for your time, I hope you’ve found something to take away from this story and if you have any questions, feel free to ask me here or to reach me out elsewhere.

You will find me on twitter at @aleron75 and in the MSI Slack Channel.

If nobody asks a question, I can ask a question to get some feedback: “is there someone that is now curious and thinks that will attend our next stand-up meeting?”

Page 89: How I ended up touching Magento core

© 2017 Magento, Inc. Page | 89 @aleron75@aleron75

Resources

Books● Domain-Driven Design - Eric Evans● Domain-Driven Design Reference - Eric Evans● Implementing Domain-Driven Design - Vaughn Vernon● Clean Architecture - Robert Martin

On-line resources● MSI Project wiki

https://github.com/magento-engcom/msi/wiki● php[architect] Nov 2017: Modern Magento – free issue

https://www.phparch.com/magazine/2017-2/november/● Coding for Domain-Driven Design - Julie Lerman

https://msdn.microsoft.com/en-us/magazine/dn342868.aspx● Validation and DDD - Vladimir Khorikov

http://enterprisecraftsmanship.com/2016/09/13/validation-and-ddd/● Validation in Domain-Driven Design (DDD) - Lev Gorodinski

http://gorodinski.com/blog/2012/05/19/validation-in-domain-driven-design-ddd/

● Exploring CQRS and Event Sourcing - Dominic Betts et al.https://msdn.microsoft.com/en-us/library/jj554200.aspx

● Refactoring.Guru https://refactoring.guru/