Skip to content

Extendability

INFO

This document represents core guidelines and has been mirrored from the core in our Shopware 6 repository. Find the original version here

The Extendability of our software and its features is an essential part of development. Enabling external companies, as well as ourselves, to customize our software so it can be adapted to different business cases is the foundation of our software's success.

Regarding software extendability, different business cases and requirements must be considered, and we must also build the software architecture accordingly.

The requirements are divided into technical requirements and business requirements.

Technical requirements

When discussing technical requirements, we focus on how we need to design our software for different extension use cases. These use cases include:

  • Functional extensibility
    • It should be possible to extend the feature with additional features.
    • Ex: Extend the enterprise search by a suggestion feature
  • Functional modifiability
    • You can rewrite the feature in certain areas to modify the functionality.
    • Ex: Implementing tax calculation for America via tax providers
  • Functional differentiation
    • The feature should be able to be extended in such a way that certain parts of the software are liable to pay costs.
    • Ex: With the XXX software version, you should be able to unlock another feature.
  • Functional exchange market
    • The feature is to be replaced entirely by an external solution
    • Ex: An external newsletter system should be connected

Business requirements

When discussing business requirements, we examine how the above technical requirements are applied across different business cases. These business cases include:

  • Marketplace extensions
    • We should build the software so everyone can easily provide new features in certain areas.
    • Ex: There should be a plugin to integrate a CMS Page publishing system
  • Adaptive technologies
    • We must build certain technical areas so flexibly that we can use different technologies for this area.
    • Ex: Our listings should be able to be read via Elasticsearch for large systems.
  • Environment specifications
    • We must program features so that they can resist different loads depending on the setup.
    • Ex: Assets should be able to be loaded via CDN, as there are several App Servers.

Approaches

Business cases are realized with the following conceptual approaches.

Patterns

All the above requirements and approaches are based on different design patterns within our architecture. To realize the extensibility, we use the following patterns, which allow the third-party developer to extend our software:

  • Decoration
  • Factory
  • Visitor
  • Mediator
  • Adapter

Decoration

With the Decoration pattern, we can replace or extend certain areas of Shopware completely. We often use this pattern for our Store API routes to provide more functionality in the Store API. Another use case is the functional replacement market case, where we can completely replace features with other technologies or external libraries.

An example Store API route is the CategoryRoute. For this route, there is an Abstract class to which we type behind a Concrete implementation and a Cache decorator

Factory

The factory pattern is often used when we need to interpret user input and validate or enrich it before passing it to the application. One use case for the factory pattern is Functional extensibility, which allows third-party developers to add new factories that support other user inputs.

A good example is the line item factory registry. This registry is used when an item is added to the shopping cart via the store API. The corresponding handler is responsible for the instantiation of the line item and enriches it with necessary data.

Visitor

The visitor pattern is often used when we process some objects within our application. This pattern is often used to fit the Functional extensibility and Functional modifiability requirements. In theory, after or before the core visitors are executed, the third-party visitors are executed, and they can visit the objects and manipulate or extend the processed data, either before or after, to influence the result.

A good example of the visitor pattern is the cart processor. The processor calls all line item processors, such as the product cart process, to modify the provided cart object and transport the line items from the previous cart to the calculated cart.

Mediator

We often use this pattern to achieve functional extensibility and functional modifiability to manipulate or extend data using additional data sources. The best-known example of this pattern in our application is Events. We use events to create different entry points for developers to trigger specific processes.

The best-known example is the checkout.order.placed event. This event is dispatched as soon as an order is created in the system. However, over time, it has been shown that it is best practice not to pass objects or entities around in events, but only a corresponding primary key, so that the connected listeners can determine the data for themselves. Furthermore, possible asynchronous processing of the underlying processes is easier to realize this way. An optimized variant of this event would not contain the private OrderEntity $order; but only the primary key for the order private string $orderId;.

Hooks

Hooks are another good example of the observer pattern. Hooks are entry points for apps where the so-called App scripts are enabled. Since apps do not have the permission to execute code on the server directly, hooks are a way to execute more complex business logic within the request without having to address the own app server via HTTP. Hooks are the equivalent of events.

One of the best-known hooks is the product page loaded hook. This hook allows apps to load additional data on the product detail page. The hook is instantiated and dispatched at the controller level. Each app script registered to the hook is executed.

Adapter

The adapter pattern is perfectly suited to a Functional exchange market. We often realize this by allowing the user to configure and select a corresponding adapter. These adapters are usually registered inside a registry, and third-party developers can easily add new adapters via events or via tagged services.

A good example is the captcha implementation. The store owner can configure a captcha type, and we then use the corresponding adapter in the code for the configured captcha.

Was this page helpful?
UnsatisfiedSatisfied
Be the first to vote!
0.0 / 5  (0 votes)