how i ended up touching magento core
TRANSCRIPT
© 2017 Magento, Inc. Page | 1 ‘17@aleron75
How I ended up touching Magento core
Alessandro Ronchi - Bitbull
© 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.
© 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 :)
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 2017 Magento, Inc. Page | 14 ‘17@aleron75
MSI: Benefits
There are also concrete benefits that this project offers.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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
© 2017 Magento, Inc. Page | 21 ‘17@aleron75
DDD - Principles
Let’s start introducing Domain Driven Design principles.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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).
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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)
© 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.
© 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.
© 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.
© 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.
© 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.
© 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)
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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).
© 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.
© 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).
© 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.
© 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.
© 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.
© 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.
© 2017 Magento, Inc. Page | 73 ‘17@aleron75
Backward compatibilityAPI: "require":{"magento/moduleinventory": "~100.3"}
SPI: "require":{"magento/moduleinventory": "~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.
© 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
© 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.
© 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.
© 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.
© 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.
© 2017 Magento, Inc. Page | 79 ‘17@aleron75
Integration
Testing
Integration tests check the correct interaction between two or more components of the system.
© 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.
© 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.
© 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.
© 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.
© 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.
© 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.
© 2017 Magento, Inc. Page | 86 ‘17@aleron75
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.
© 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.
© 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?”
© 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/