Spryker is a commerce operating system for business-to-business(b2b) and business-to-consumer(b2c) companies. With Spryker, you can implement awesome customer interfaces while still maintaining a modular architectural implementation. This article is aimed at highlighting a few of the important concepts of the framework.
When reading through the documentation of Spryker, you will come across this phrase a lot, “Modular architecture”, What does that mean? It means every part of the shop is composed of separate independent components, each module is responsible for performing just one task while also working as a functional whole. In effect, if you are not comfortable with any of the modules, you can always remove them and add yours.
Since Spryker is built with the modular architecture in mind, it means, every functional act performed by a user while shopping online, happens within individual modules. A typical example is the discount section of the Spryker shop,
Discount is an individual module, why? because it is a functional process of any online shop. Building with modularity in mind implies that, as a developer, you can get rid of the discount module and implement yours from scratch, or better, extend the existing implementation and add more features for your shop.
Building with modularity in mind also ensures that there are no redundant functionalities in your store, you can see all the modules and know exactly the job of individual modules.
A reoccurring theme with most commerce framework is that as years go by, it is always difficult to upgrade your shop to the latest and most stable libraries/components available, thereby leading to having stale technologies in your code, having to patch your way through and of course, having issues with scaling when trying to accommodate your shops growth. This is not the case with Spryker, why? you guessed right, “the modular architectural concept”.
The modular architectural approach gives room for a release pattern called “Atomic release process”, this pattern ensures that individual modules have their own semantic versioning. For example, you can choose to upgrade to the latest version of the checkout module while being rest assured that your shop will function as expected.
Separation of concerns
In Spryker, the frontend and backend of the shop are entirely separated and can be linked together, just like legos. Separating the functionality of our shop to frontend and backend makes it easy for the shop to have a blazing fast response time, why? Because the frontend uses Elasticsearch for performing search, key-value storage(e.g, Redis) as a data-source for localized content while the backend uses a direct connection to a relational database.
Separating the frontend from the backend also makes it hard to perform a cyber attack against your shop, why? exactly, you guessed right, “Your frontend application does not communicate with your database”. That being said, you still need to protect your shop against SQL injections.
The Zed layer is responsible for handling all backend related logic, including database interaction.
According to the dictionary, facade means a “deceptive outward appearance”. In software development, facades literally mean just that. The Facade design pattern hides complex code blocks, by providing a simple interface that allows working with a singular class instead of calling multiple methods in different classes.
In essence, Facades can be likened to some of the duties a librarian performs, you ask for a method, and it directs you to where the method is located. Facades provide a simpler and convenient interface, especially when working with a large codebase like Spryker.
In Spryker, you will find facades in the Business layer of individual modules in the Zed layer. Within a module, the facade is the entry point for the zed business layer. Think of it as the API for your module.
The business layer is responsible for the entire business logic of your module. Meaning, initiating interaction with your database and interaction with your models. Your model can handle logics ranging from simple cart price calculation to interaction with a third party API. The business layer has a direct communication link to the persistence layer. This layer also contains a facade, which acts as the entry point to the module.
Picture it this way, let us assume we have a task to fetch all todo items from a to-do list. We will need to make a call to a database, get the response and return it back to the user. The logic of this happens within the Zed layer.
A request will be sent to the Facade class in the Business layer of a module, the facade sees the request and proceeds to call a “Factory”. As the name suggests, a factory is simply a place where you create classes. The factory sees the request, instantiates a business model and forwards the request to that model. Why do this, you may ask. Well, the business model is where the logic of a module actually resides. Assuming I want to retrieve the todo list, and also filter the list by order of priority, that logic needs to be done inside the business model.
When the business model gets the request to fetch all todo items in order of priority, it passes the request to the query container interface of the Persistence layer. The business layer initiates the call to your persistence layer, which in turn communicate directly with the database.
The persistence layer is responsible for the database structure within a module and all interactions with the database. Any module that connects to a database will always have a Persistence layer.
Spryker uses Propel as its object-relational mapping tool(ORM), and in Propel, database structures are always written in XML. Propel allows you access your database using a set of objects, providing a simple API for storing and retrieving data.
Using our todo list example, the persistence layer gets a call from the business layer requesting to fetch all todo items from the database. Assume we have our database schema laid out, the business layer will call our “Query Container Interface”, the query container interface is a delegator to the “Query Container”, so, it will proceed to call the requested method from the query container.
The job of the query container is to hold all available queries within a module, but, it does not interact with the database. Just as how a factory is known to be a place where goods are manufactured and assembled, here in the persistence layer, the Factory’s job is to create a new instance of the ORM class.
Once a new instance of the ORM class is created, you can run all Propel commands within the factory. The factory must always return an entity back to the calling method, which in our case, is always the query container.
Now that we have our response, the query container returns the response back to the business layer. When an update is to occur on an entity, the business layer sends the update to the persistent layer through the query interface, which in turn, will persist the entity into the database.
An entity is a single row from the database
The communication layer is one of the entry points into your system. Console commands are also another entry point into the system.
In spryker, plugins can be likened to extensions and you will always find them in the communication layer. Plugins are used as a communication tool between modules. Since modules in Spryker are responsible for handling just one task, there are times where resources need to be shared between modules, this is where plugins come to play.
Transfer objects are used to transfer data across multiple modules and it is also used to transfer data between the frontend and the backend. Transfer objects are written in an XML format inside the shared layer.
Since the transfer objects are used by both the frontend application and the backend application, they need a converging point. In Spryker, this point is called the shared layer. Individual modules can have one or more transfer objects.
The Glue API is a RESTful API that allows you to integrate your shop with other applications ranging from IoT applications to mobile applications, other web stores and bots. The possibilities are endless.
In Spryker, methods that perform repetitive task across multiple modules are to be written as services. Using the modular approach, each service must have its own module. In Object-oriented programming, this pattern is known as the “Helper methods”.
Publishing and Synchronization
The frontend layer of a Spryker shop does not communicate with the database, rather, it communicates with the key-value storage, in our case, Redis. The client shop also makes use of Elasticsearch as a data source for its search engine. The search engine also does not communicate with the database. Now, this poses a set of questions, what happens when a change occurs in the database? Are there times when the data served on your client shop is totally different from what you have in your database?
To answer these questions, Spryker came up with Publishing and Synchronization. In P&S, for every change that occurs in the database, there are listeners patiently waiting for changes to occur in the database. Once there is a change, the listeners will kick in an event, this event will proceed to update your Redis and Elasticsearch in the background. Of course, there are times when the listeners will fail, or an event will fail, when this happens, you can always trigger synchronization manually.
This article has covered some of the technical concepts within Spryker. With this, you can enjoy working with one of the best SOLID and OOP principled commerce framework ever created.
From a Certified Spryker Developer ✌🏻