This is a summary of the current Migration Strategy. It provides an overview of our current vision, in the end of this year 2020, of the Symfony Migration project.
Back-Office pages can be classified in four categories:
These pages allow the user to modify configuration settings in PrestaShop.
These pages allow the user to browse PrestaShop content using listings. These listings usually provide some actions the user can trigger, such as “enable/disable”, “delete”, “bulk delete”.
These pages allow the user to create or edit records from PrestaShop data model (example: create/edit customers).
There are some pages that are unique: Carriers Edit page, Dashboard, Customer Service page …
Sometimes a page will have mixed content. For example there are pages that provide two listings or one listing and one configuration form.
In legacy pages, most of the time, these Back-office pages were structured following standard MVC PrestaShop model:
We believe PrestaShop project has grown too big to follow this 3-layers model, rather fitted for small applications. We have chosen to introduce more architecture layers.
The Migration project started by migrating Configuration Form pages.
The chosen structure to handle such pages was the following:
Since the DataProvider interacts with ObjectModel, it belongs to Adapter namespace.
For migrating Listing pages, the Grid component was built.
The chosen layer structure to handle such pages was the following:
If the Grid provides some actions, they are handled by dedicated Controller Actions.
The QueryBuilder ignores ObjectModel and use a Doctrine Connection to query directly the database. So there is no interaction with legacy code.
However the Grid Actions use ObjectModel, for example to enable/disable a Category status. In the beginning we used Adapter classes to handle these, but we could see that once again we were coupling legacy code with migrated code.
This is when we decided to introduce CQRS.
We wanted to build a strong frontier between migrated code and legacy code. Since re-writing all the code would be too long, we needed to continue relying on the business logic legacy code to power PrestaShop.
We however wanted to interact with it in a way that would allow us, in the future, to easily unplug it and replace it with a new implementation.
So we decided to introduce CQRS and a Domain.
CQRS was introduced into PrestaShop architecture in the following manner:
The Application layer (Forms, Controllers, Views …) dispatches Queries and Commands to the Domain to be handled, unaware of the inner workings of this domain.
Inside the domain are QueryHandlers and CommandHandlers that handle dispatched Queries and Commands. For now, they do use PrestaShop legacy business logic to handle it. This means classes like ObjectModel, Cart, Product are still being used inside migrated pages.
The communication between the two layers is performed by CommandBus and QueryBus, which carry the Commands and Queries.
Since the Handlers use legacy logic, they belong to the Adapter namespace. In the future they will be replaced with new implementations. The replacement will be very easy: a new Handler will be plugged in, previous Handler will be removed. No modification will be required in the code.
So the structure for a Grid action, using CQRS, is the following:
So “migrating a Grid action” means to “move the legacy logic into a Handler and building a Symfony layer on top of it”
These pages are form leveraging the concepts of CQRS.
You can read more about it by clicking on this link.
So “migrating a legacy Add/Edit page” means to “move the legacy logic into a Handler and building a Symfony Form on top of it with its management logic”.
We don’t want to render Form inputs manually, so we now rely on a Twig Form Theme allowing us to render all of our Symfony forms with a single block
{{ form_widget(form) }}
Between phase 1 and phase 4, two years passed. Two years where we experimented, explored, struggled and we got the hang of what was needed for PrestaShop to move forward.
We now have a better understanding of what the direction we are aiming for. We now know we want to build a full Core Domain for the future of PrestaShop.
The future PrestaShop architecture is based on 5 key elements:
The Core sits in the back-end and is at the center of it all. It accounts for all the business needs and use cases that PrestaShop is capable of doing (managing products, shopping carts, orders, etc.). The Core is domain-oriented, meaning that it is built around business use cases, expressed in an ubiquitous language. The Core is also master of its own Domain; in order to let it be the guardian of system-wide coherence, it has to be isolated from other services and be the only one capable of performing state transitions. Other services can only interact with the Core through well-defined interfaces, that we call the Core API. Incidentally, this also means that Core behavior can be extended, not modified, by other services or at least not in a way that it puts system coherence at risk. In addition, the Core is designed to be easily testable and is covered by automated tests.
In the future architecture, the Back Office (BO) and the Front Office (FO) are independent front-end applications, each one running entirely on the browser. They are fully component-based (our framework of choice is VueJs, and built using separate toolsets called Software Development Kits (SDKs): one for the FO, one for the BO. These SDKs would not only include reusable components, but also bidirectional communication channels based on stable contracts, both within the front-end application (events) as well as with the back-end (through APIs). The BO SDK also integrates the UI Kit, which provides an uniform style for the whole Back Office.
The Core and FO/BO applications communicate through two separate APIs, namely the FO API and the BO API. These APIs serve two distinct purposes: while the FO API is public and designed to serve customer-facing applications (e.g. the FO application, but also other custom clients, like mobile apps or Point of Sales in physical stores), the BO API is protected by access rights (much like the current Web services) and is meant to power the BO application, as well as third party integrations like ERPs. In order to maximize forward compatibility, APIs and SDKs are versioned.
Of course, the future architecture supports Extensions, which can be placed all over the system. Modules can hook on to existing features or add new ones, either on the front-end applications as well as in the back-end (for data processing). On the front-end, Modules are based on the FO/BO SDKs, whereas server-side they are built on top of the Back-end SDK. While Front-end SDKs allow Modules to interact with front-end applications and retrieve data through PrestaShop’s APIs, the Back-end SDK provides access to the Core API, which allows Modules to query data directly from the Core, perform state transitions, extend existing API endpoints and even create new ones. In order to ensure system stability, Extensions can only interact with PrestaShop through APIs and SDKs.
Finally, Themes are a particular kind of extension that sits on top of the front-end application and that defines the layout and style for components provided by the application, FO SDK, and any installed Modules.
Our Handlers started as “place where we put the legacy code we dont have the time to migrate now”. They must now become interfaces for the Core domain, defining the future API endpoints. You could think of them as Controllers for the Domain, and consequently they will become empty of business logic, only focused on validating incoming Commands and Queries and formatting the data in both directions.