Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
How I ended up contributing to Magento core
1.
2. HOW I ENDED UP
CONTRIBUTING
TO MAGENTO CORE
Good morning, welcome and thank you for being
here.
3. @aleron75
First of all, I would like to start telling you the story of
how this meme was born.
More or less, three years ago, at a dinner, Antony
Ferrara, a well known member of PHP community,
took a photo of an admonishing Ben Marks upon
which Talesh Seeparsan, a popular member of
Magento community, built the meme: “hey, did you
just edit the core?”
I was just the one who took those pieces together,
asked a friend to make the graphical version you
see here to produce some stickers and tees not for
profit.
The point of the story is that back in the days of
Magento 1, touching the core was considered a
very bad practice.
4. @aleron75
ALESSANDRO RONCHI
COO & Developer - Bitbull
My name is Alessandro Ronchi, I come from Italy and
I work at Bitbull as “Chief Operating Officer”.
But since I have no clue what it means, I prefer to say
I’m a developer :)
My passion for development and continuous
improvement brought me here, today, to tell you a
different story about how I ended up touching
the Magento 2 core and the lessons I learned
along the way..
5. @aleron75
Magento has always been an open source platform
but only with the advent of Magento 2 on GitHub
they completely embraced the open source spirit,
becoming open to community contributions.
6. @aleron75
+
Furthermore, Magento gave birth to the Magento
Community Enginering Team with the intent of:
- enabling the community itself to process pull
requests
- and making it easier for others to contribute.
7. @aleron75
++ +
All this pieces mixed with the extraordinary passion
of the company and the community for each other,
brought to great achievements:
- MSI of which I’ll be saying more in a few minutes
- PHP 7.2 support
- Import/Export functionality improvements
- Bulk APIs
All projects published on engcom’s GitHub repository.
The stats say that 25% of new Magento 2 code in
2017 was developed by the community.
This is a great achievement we should be really
proud of.
8. @aleron75
MSI: “the largest
community-developed
feature in Magento”
There is a session this afternon I warmly recommend
to attend, whose title is “MSI: the largest
community-developed feature in Magento”.
The talk is held by Mark Brinton and Igor Miniailo,
respectively the product manager and the main
architect of the project; they will tell us how MSI
started almost a year ago and evolved.
Nevertheless, I think that a brief introduction of MSI
is due.
It is a collection of modules that replace default
Catalog Inventory.
It will remain a free Open Source asset maintained
by the Magento Core team (+ volunteers) after the
first release.
9. @aleron75
MSI – BUSINESS VALUES
As the name suggests, it allows the definition of
multiple sources for product items and gives the
possibility to bind several of these sources to the
same sales channel.
Allows to manage inventory data via Admin panel
and through dedicated import/export functionality.
Defers stock deduction from order placement to
order processing when a source selection
algorithm is applied.
Different algorithms can be implemented (priority
based by default).
Enables full dropshipping support.
Brings performance improvements to checkout (no
more table locks) and indexing (multi-dimensional)
10. @aleron75
MSI - OPPORTUNITIES
M2 is a big framework that requires time to be
mastered.
I joined the project on July 2017 because:
- I wanted to grow my knowledge of M2 since as
COO I wasn’t assigned to any new M2 projects :)
- I had some experience on the development of a
multi-warehouse on Magento I wanted to share
My first PR was related to reservations functionality
and was merged after only one month.
In that short period I I had the opportunity to learn a
lot directly from the Magento architects and to
work and train with smart people both from
Magento and the community that continuously
inspire me and push me to improve.
11. @aleron75
MSI – LESSONS LEARNED
Joining the project gave me the opportunity to learn a
lot of new technical lessons and to put them into
practice.
It also gave me a preview of future standards in
Magento development.
I’m a fan of learning by doing and this was
definitively the opportunity I was looking for.
12. @aleron75
MSI – LESSONS LEARNED
We don’t have enough time to look at all these things
so I chose three topics because the are all related
to software design.
I think that sooner or later, in our development career,
we must understand the difference between
writing code and designing software.
13. @aleron75
DOMAIN-DRIVEN DESIGN
Let’s start with DDD (ask how many are familiar with
this concept).
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 that
we call domain
- defining languages that are ubiquitous within
specific contexts and are familiar to the domain
experts, typically our customers, reducing the
distance b/w the business and the dev team.
14. @aleron75
DDD – DOMAIN MODELS
So we have te domain expert, on the left, which is
the owner of the business knowledge.
Our role, as developers (on the right), is that of
extracting the domain models, that are, the
simplified abstractions that represent the
knowledge of the domain expert.
This simplification should not be seen as a limitation
but as an opportunity to ignore irrelevant details
and focus only on those that are related to solving
the problem we have in a specific context.
15. @aleron75
DDD – DOMAIN MODELS
It wouldn’t be a tech talk without some code :)
This class is not extracted from real code.
It’s a simplified example that I use to show you the
characteristics domain models that are not all
the same.
16. @aleron75
DDD – DOMAIN MODELS
This Order class represents an Entity.
Entities are objects defined by their unique identity
that is persisted over time.
Nothing new, in Magento we use the same term for
persisted objects.
17. @aleron75
DDD – DOMAIN MODELS
Not all the properties are the same.
Some, called invariants, are the ones without which
the entity can’t be considered a valid entity.
In this example, let’s say we cannot have an Order
without a number and an assigned customer.
We can implement this condition in several ways
(constructor, builders, validation), the point is:
identify the invariants.
18. @aleron75
DDD – DOMAIN MODELS
Some properties are not persisted “stand alone” but
as part of another Entity, just as shown here.
They are called value objects and are identified by
their immutable state, that is, the values of their
properties.
The Billing Address here is a Value Object: we don’t
need to assign an identity attribute to it; we persist
that value object in the Order Entity.
Forget the database, don’t think relationally. Our
customer doesn’t think that way.
19. @aleron75
DDD – DOMAIN MODELS
Taken as a whole, the Order Entity of this example is
called an Aggregate Root.
Aggregate: because it is a group of other domain
models that relate each other. And it should be
generally considered a transactional unit: save it
all or nothing.
Root: when it’s the only access point to those
models. Put differently, if we don’t have any way to
access the objects contained in an aggregate, that
aggregate is a root.
20. @aleron75
DDD – DOMAIN MODELS
Another kind of Domain Model is represented by
Services.
Services are stateless processes defined by their
behavior.
In object oriented programming, we can implement a
service as a functional object, that is, a class
without a state and with one execution method.
21. @aleron75
DDD – DOMAIN MODELS WRAP UP
As we have seen, not all models are the same, some
can be persisted and need an ID, some don’t;
not all models need all the properties set to be valid,
some are not even objects but stateless functions,
and so on.
To recap, DDD forces us to define the different
domain models so that we can effectively simplify
and assign the correct responsibility to each of
them, ignoring irrelevant details when not needed.
22. @aleron75
DDD – UBIQUITOUS LANGUAGE
Let’s talk about the second fundamental principle of
DDD that is: avoiding ambiguities.
Well, this illustration is obviously an exaggeration.
But chances are that any developer sooner or later
experiences the frustration given by
misunderstanding, especially when it is a bit too
late.
23. @aleron75
DDD – BOUNDED CONTEXTS
Context A Context B
DDD proposes a solution for this: contextualization.
A bounded context is a unit in which all the
elements that we design have a ubiquitous
meaning and possibly a single responsibility.
Splitting our domain into bounded contexts is what
allows us to apply the domain model
simplification we have previously seen.
24. @aleron75
DDD – BOUNDED CONTEXT
Let’s see this though a code example (again, not real
code): the namespaces represent our contexts.
Given the context in which we have to design our
model, we can apply different design.
So a Customer Address is an Entity that has to be
persisted and may be marked as default.
A Sales Order Address instead is a Value Object,
which doesn’t need any ID nor the $isDefault flag.
This may seem unnecessary repetition violating the
DRY principle. But at a closer look, this is not
duplicated code but specialized code with clear
responsibility and an ubiquitous meaning.
25. @aleron75
DDD - BOUNDED CONTEXTS IN MSI
Inventory InventoryCatalogInventoryBundle
InventoryConfiguration InventoryIndexer 23 modules (at date)
In MSI, we identified the bounded contexts of our
domain and created (at date) 23 modules.
Not all these modules represent different contexts,
some of them contain the service layer definition
(APIs) or are interrelated but in any case we have a
dozen different contexts.
This allowed us to simplify our domain models,
avoiding things like the concept of a “default
source” that is related to the catalog context but not
to the inventory.
26. @aleron75
DDD – BEHAVIORS vs PROPERTIES
Another important principle from DDD is the idea that
we should try to clearly express the business
intent.
To accomplish this mission we are recommended to
expose behaviors rather than properties.
Let’s remember that our customer, the domain expert,
doesn’t care about ORM, tables, field and all those
technicalities. They care about business intent.
We should avoid reducing the domain to an
abstraction of the data model.
Being able to express the business intent in terms
of models and behaviors is where we can make
the difference as developers.
27. @aleron75
DDD – BEHAVIORS vs PROPERTIES
And here is a code example, again not real one, that
shows the difference between exposing behavior
rather than properties.
Instead of exposing a list of setters, we can expose a
single method that has the same effect of the
setters but has the advantage of clearly
expressing the intent.
28. @aleron75
DDD - BEHAVIORS IN MSI
SaveStockItemConfiguration
GetProductSalableQty IsProductSalable
StockSourceLinksSave SourceItemsDelete
service layer
In MSI, we built up a service layer that models
behaviors rather than exposes the underlying data
structure.
Our service layer is made up of of service classes
modeled as atomic behaviors which speak the
domain’s language.
29. @aleron75
DDD – WRAP UP
So, to wrap up, the intent of DDD is reducing the
distance between us, the developers, and the
business by giving us the tools to model better
abstractions of the domain.
Contextualization and avoiding ambiguity are key
factors for a better design.
30. @aleron75
CQRS
CQRS stands for Command-Query Responsibility
Segregation (ask how many are familiar with this
concept).
Again, it’s not a methodology or a paradigm or a
framework; it is an architectural 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 separate data stores.
31. @aleron75
CQRS
Put differently, CQRS gives us a better
understanding of what is responsible for
changing the state of a system.
This separation brings to domain simplification: a
single model is no more responsible for both
operations, thus they can be assigned to two
simpler models which are also simpler to adapt to
business changes.
32. @aleron75
CQRS – BETTER SCALABILITY
Furthermore, since we separate the systems that
write and read, in situations where, for example,
read operations are more frequent than write ones,
we can better assign resources and scale our
application properly.
This should really sound familiar in the ecommerce
context.
33. @aleron75
CQRS & DDD
At this point, you are probably thinking: hey, this
really seems interrelated with DDD.
When applying CQRS, DDD is not required but they
often go together because they have some things
in common like the idea of identifying different
contexts (read, write) that brings to simplification
(over duplication).
34. @aleron75
CQRS IN MSI
7
3
2
8
SOURCE items
STOCK ITEMS
Let’s see how we applied CQRS in MSI: we used its
principles to model a concept that is core of MSI:
the separation b/w 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 stock is the aggregation of different sources that
determines the general availability of a product
across different sources.
35. @aleron75
CQRS IN MSI
7
3
2
8
SOURCE items
STOCK ITEMS
WRITE
READ
As you probably are already guessing:
- source item is the entity through which we write
product availability, changing the state of the
system (typically a backend operation)
- stock item is the entity through which we read
product availability (typically a frontend operation)
36. @aleron75
CQRS IN MSI
7
3
2
8
SOURCE items
STOCK ITEMS
INDEXATION
WRITE
READ
An indexation mechanism aggregates data from
sources to stocks, keeping data consistent b/w
backend and frontend.
37. @aleron75
CQRS – WRAP UP
So far, we’ve seen how CQRS can help us but there
is this saying: “if all you have is a hammer,
everything looks like a nail”
The point is that CQRS is not an universal solution.
Applying this design pattern comes with some
drawbacks and we should always take them into
consideration when deciding whether to apply it or
not to our application:
- more analysis due to additional complication
- duplication handling
- eventual consistency (avoid in transactions)
38. @aleron75
EVENT SOURCING
Let’s conclude our technical overview with Event
Sourcing (ask how many are familiar with this
concept).
Again, it’s an architectural pattern that can be very
useful in some circumstances as we will see.
According to Event Sourcing, we store the state of a
system by persisting a sequence of events that
brought us there.
This way not only we can determine the state of the
system at any time but we also have an insight of
how we got there.
39. @aleron75
EVENT SOURCING IN MAGENTO
ORDER TABLE
entity_id |state |status |created_at |updated_at
||||
51 |complete |complete |20130404 00:25:53 |20130404 00:26:25
ORDER STATUS HISTORY TABLE
entity_id |parent_id |status |created_at |entity_name
||||
57 |51 |pending |20130404 00:25:53 |order
59 |51 |processing |20130404 00:26:08 |invoice
60 |51 |complete |20130404 00:26:25 |shipment
We already have an example of Event Sourcing on
Magento 1 and 2.2.
The order status history table stores all the statuses
change events.
That’s a sort of Event Sourcing, because we have a
clue of how we got to the current order status.
41. @aleron75
EVENT SOURCING IN MSI
-2
-2
RESERVATIONS+2
-1
-1
In MSI we exploit both Event Sourcing structure and
behavior in the way we calculate product salable
quantities.
Reservations are append-only entities used to store
quantity increments and decrements at order
placement time.
42. @aleron75
EVENT SOURCING IN MSI
SOURCE ITEMS
STOCKITEMS
SALES CHANNEL
7
3
-2
-2
RESERVATIONS
4 2
+2
-1
-1
INDEXATION
Here is the big picture that shows us how
reservations go into action.
43. @aleron75
EVENT SOURCING IN MSI
SOURCE ITEMS
STOCKITEMS
SALES CHANNEL
7
3
-2
-2
RESERVATIONS
4 2
+2
-1
-1
INDEXATION
As shown before, indexation aggregates stock items
quantities from source items.
Index tables don’t take reservations int account.
44. @aleron75
EVENT SOURCING IN MSI
SOURCE ITEMS
STOCKITEMS
SALES CHANNEL
7
3
-2
-2
RESERVATIONS
4 2
+2
-1
-1
INDEXATION
Reservations are taken into account at service level,
when we want to know the salable quantity of a
product in a stock.
To recap, product salable quantity is a state that is
calculated at runtime taking into account all the
reservations that were placed until that moment.
This seems a slight change but thanks to it, we
achieve the great benefit of avoiding blocking
operations during checkout.
45. @aleron75
EVENT SOURCING IN MSI
UPDATE
STOCK
PLACE ORDER1
ORDER 1 PLACED
✋
PLACE ORDER 2
ORDER 2 PLACED
UPDATE
STOCK
Let me clarify with this simulation of what happens in
checkout without and with reservations.
When an order is being placed during checkout,
some records from the stock table are locked to
avoid stock breaks (via a SELECT FOR UPDATE
statement).
Those are the records related to the products we are
purchasing.
46. @aleron75
EVENT SOURCING IN MSI
UPDATE
STOCK
PLACE ORDER1
ORDER 1 PLACED
✋
PLACE ORDER 2
ORDER 2 PLACED
UPDATE
STOCK
APPEND
RESERVATIONS
PLACE ORDER1
ORDER 1PLACED
PLACE ORDER 2
ORDER2 PLACED
APPEND
RESERVATIONS
Thanks to how we designed the reservation
mechanism, we don’t have blocking operations
any more, still having consistent count of salable
quantity and avoiding stock breaks.
I think that this change alone is worth the upgrade to
MSI, even if not used for multi-source purpose.
47. @aleron75
WRAP UP
Time to wrap it all: gone are the days when Magento
core was untouchable.
With the advent of M2, the community was able to
actively contribute to Magento core, shaping a
new evolution model for Magento platform.
Taking part in this, I can testify, is a win-win situation
in which the more you give, the more you receive.
Some takeaways from today’s presentation (the tip
of the iceberg of all the lessons learned so far):
- DDD: design better software
- CQRS: separate responsibility, better scalability
- ES: remove table lock from checkout
48. @aleron75
Before going, let me share a last advice.
Even if touching the Magento core is no more
considered a bad practice, we should beware the
brand new bad practices in Magento 2 so let’s
remember that Ben is always watching us :)
Thank you very much for your time and your
attention, it’s been an honor to be here today.