Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document the rework of Product page #1331

Open
matks opened this issue Mar 28, 2022 · 0 comments
Open

Document the rework of Product page #1331

matks opened this issue Mar 28, 2022 · 0 comments

Comments

@matks
Copy link
Contributor

matks commented Mar 28, 2022

Draft

# Documentation product page v2

## Documentation

The product page of PrestaShop 1.7 was one of the first pages migrated to Symfony. It benefited from numerous improvements both for the user experience and for the technical implementation, however over years were reported various limitations that were due to its architecture.

## Known limitations

### One single and large form

The back-office product page allows the user to modify all aspects of a product, and this means as many as fifty fields and buttons can be managed by the shop administrator. All of these fields and buttons actually belong to the same HTML form.

This means that everytime the form is submitted, the entire product data is sent to the backend and persisted, even if the admin modified only the value of a single field. On the other hand this allows module developers who interact with the product page like a middleware to receive the full data being persisted and interact with it.

The fact that this is a single form also means the data being sent can be quite huge as some fields can grow very large for some configurations. Large data chunks mean it can be slow to process and sometimes even exceed server maximum capacities such as the post_max_size setting, making the server rejects the request.

### One page to control many aspects
As the back-office product page allows the user to modify all aspects of a product, it must be able to actually impact and modify dozen of different data models in PrestaShop. Related to products are product combinations, features, custom fields, specific prices, suppliers… the product page allows the shop admin to reach out and modify a very large number from a single webpage. This is powerful but on the technical side it means huge chunks of business logic have been written inside large classes rendering them hard to maintain. These chunks of code carry both complexity and size issues and generated a high maintenance burden.

### Limited for large shops
As the software was slowly adopted, many different shop admins started using the page and reported issues for large shops situations.

The first issue was that inside the product page, all combinations of a product are being rendered and presented to the administrator, no matter whether there are forty of them or four thousand. In the latter case, rendering four thousand combinations quite often freeze the browser because of too many objects to draw.

Other issues related to too much data being rendered were reported:
The Combinations generator which is able to generate the combinations based on a choice of features would timeout for large number of features
The Category widget which allows shop admin to associate the product to categories would fail to load for large number of categories

These are the design issues we acknowledged and that we hope to solve with the new product page architecture.

## First, a better code structure

The requirement for being able to build a fit architecture that does not require high maintenance is to structure it well. Code badly organized can turn a good idea into a failure.

The big chunks of business logic were splitted into subdomains, following the DDD approach towards organizing code. Each subdomain is supposed to be able to be updated and evolve independently from the others. The business logic remains mostly the same - although we fixed a few bugs while reworking the code - but is now located in a dedicated and separated area to make it easier to maintain.

Then, what happens when the shop admin modifies, inside the new product page, the product description, one specific price and one attribute?

As these 3 items do not belong to the same subdomains, the form submit will be received and split into 3 Commands, one per subdomain. Commands come from [CQRS](https://devdocs.prestashop.com/1.7/development/architecture/domain/cqrs/#what-is-cqrs).

Each Command handler has also been structured to separate 3 main concerns:
- How to validate whether input data is valid
- How to interact with the data model
- How to perform business logic rules (such as handling taxes, critical topic for e-commerce)

Each Command Handler can rely on
- Repositories to manage the data model and interact with it (cf. https://devdocs.prestashop.com/1.7/development/architecture/domain/domain-services/)
- Validators to validate input data (cf. https://devdocs.prestashop.com/1.7/development/architecture/domain/domain-services/)
- Updaters to perform business rules logic  (cf. https://devdocs.prestashop.com/1.7/development/architecture/domain/domain-services/)

## Leaving behind the single form

Relying on a single large form made the product page
- Easier to comprehend
- Allow module developers to interact with a single unique submit event to catch any data being submitted (and enrich the behavior)

But that backfired as mentioned above. This is why the new product page features multiple forms, each dedicated to a subdomain of the product, and supports partial update. Partial updates means that if the shop admin modifies one field value and saves, only this data is being sent to backend to be processed. The other fields of the form are not being carried by HTTP. This makes http payload lighter and greatly increases the page performance, but requires a subtle handling of those fields upon the return of the http response because the form needs to refresh only the modified part, not all of it. The form must be able to send a part of its data, and to receive the response (valid or not) for only this part.

## Dealing with large shops

The main performance issue was that the previous page would attempt to display every single combination associated with the product, whether there would be five of them or five thousand.

The problem of “displaying thousand of items on a webpage” has long been solved: the solution is naturally the use of pagination. Displaying pages of the list and allowing the user to navigate through the pages thanks to “previous / next” buttons, filters and sort capabilities has been implemented to the combinations list. This does impact a few related behaviors such as bulk actions and make the listing slightly more complex, but makes up for an obvious superior robustness.

The two other performance bottlenecks have also been addressed: the category widget inner behavior has been rebuilt to support thousand of pages with a combination of lazy loading the data and optimized data loading (loading only the needed data and nothing more).
The combination generator was also rebuilt with performance in mind in order to make it much faster. This should prevent timeouts to happen for manageable combination numbers.

## Let’s talk about multishop
When the product page of PrestaShop 1.7 was migrated to Symfony it benefited also from a rebuilt multishop mechanism, designed to optimize the merchant usage of the page. Unfortunately the feedbacks did not bring the wished outcome.

Following this, naturally the design team listened to user feedback and opinions and added features to make up for the reported issues. The main reported issue was that it was hard to stay aware of the changes being done on different shops. To fix this item, more and more information about what’s being changed and what impacts are to be expected have been added to the interface.

Additionally, just like the form data is now being split into different Commands, the data intended for different contexts is now being processed by different Commands.

This means that,
- If the shop admin does modify the product description for one shop only
- And then modifies the SEO tags for all shops
- Then once the shop admin clicks the “submit” button, 2 Commands will be sent: one for the “single shop” data and one for the “all shops” data


On the backend side, each received Command has a clear scope: what data it aims to impact, for which context. Clearly scoped data is easier to handle. The complexity however raises on the Controller side which must track each of the Commands sent, for which context, and gather numerous responses (whether data was valid or not, whether data was correctly persisted or not) to inform the shop admin of the result of his submit action.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant