Behavior Driven Development
At Apriko, we strive for a high degree of automation of customer processes, a fast market launch, and continuous improvement of our software. To ensure this in a demanding domain and complex software architecture, precise planning and consistent implementation from the outset are essential.
Automatic generation of the graphic user interface (UI)
A central design principle of Apriko’s software architecture is to automatically generate as much boilerplate code as possible or to derive logic. This allows the development team to focus more on the “what” and less on the “how” (the time-consuming detail work).
The design process
For example: In the design process, a Person entity is defined that contains various characteristics such as first and last name. Each of these characteristics can also be subject to validation rules – for example, first and last name are mandatory fields. The “what” refers to the external perspective of the application, i.e. to the modelling of entities and the definition of business rules. Declarative approaches offer many advantages, especially as they reduce complexity. Internal mechanisms are implemented faster and are immediately visible without the need to analyse large amounts of code first.
Problems with manual boilerplate management
Typically, the “how” is implemented manually. While this provides flexibility, it quickly leads to vertical expansion across all layers of the software architecture. The main problem is to ensure consistency. Similar problems must be addressed with similar solution approaches to ensure stylistic and functional completeness and consistency. If changes are made afterwards, there is a risk that important adjustments are missed, which can lead to bugs and software regressions.
Inference
Further logic is automatically derived from the centrally defined entities, characteristics, actions, and business rules. On the one hand, backwards in deeper layers by automatically generating the database structure and migrating it if necessary. On the other hand, forwards in higher layers, e.g. by generating infrastructure components and web service interfaces (API/REST).
These declarations, i.e. layout definitions, are transferred to the UI/frontend. A specially developed UI engine processes these to generate the graphic user interface.
As this architecture requires strong standardisation, many requirements need to be unified to achieve the full potential. However, the robustness of the architecture lies in allowing deviations from the standard in order to implement specific business logic in a targeted manner without creating inconsistencies.
Front-end engine
Layout definitions
Each service provides its declarations in the form of JSON files as layout definitions for the front-end UI engine. These layout definitions contain all entities, features, actions, and business rules in a structured form. On this basis, the frontend can represent the majority of use cases without the need for additional programming. This enables a largely independent and self-sufficient frontend that is only loosely coupled with the backend.
Generating views
Different views can be generated dynamically from the layout definitions. The basic structure of a view, e.g. a form, is explicitly implemented. On the other hand, the content – i.e. the type of action, the fields, and the entity types – is determined dynamically based on the context and configured from the layout definitions. For example, the form view receives the instruction to “create a person” and automatically generates the necessary fields including validation rules and business logic in order to be able to send a finished request to the backend.
Event-based approach
The individual views and their components not only obtain their information from the layout definitions but must also take into account the current data status. In a dynamic system, components must react to events, for example, a change of a field value, and display these changes in real time. This is implemented by a mix of model-view-controller (MVC) patterns and a virtual database in the frontend. This virtual database acts as a model in the sense of the MVC principle and synchronises changes and generates corresponding events. The model also corresponds to a cache for queries to the backend.
Model Messages
The standardised exchange of changes (create, update, delete) to data takes place via so-called model messages. These are exchanged both between the system units (services) and with the frontend. Model messages show changes to entities as well as changes to relationships between entities or data shared between entities. This semantic knowledge, together with the layout definitions, enables the dynamics of the frontend and contributes to the decoupling from the backend.
Model Service
Due to the dispersed nature of the application, in which different services manage different data, it is not possible for an individual service to perform a complete query of all the data. A Model service has been developed so that the frontend can still efficiently receive data from several services in a single query. It processes the model messages and creates an aggregated view of the data of all the services. The Model service thus acts as the preliminary stage of a data warehouse and enables comprehensive queries – including graph-based ones – on this hierarchical data structure.
Localisation
Another central component of the front-end engine is localisation, which includes the translation and formatting of the content.
Since Apriko is multilingual, texts and data must be available in a generic, untranslated form or provided by the backend. The actual translation only takes place in the last step of generating the interface.
Conclusion
The decoupling of backend and frontend and the declarative approach in backend development enable a better focus on the implementation of business logic. At the same time, the creation of unnecessary boilerplate code as well as its erosion is minimised, and consistency is increased through all layers of the software architecture.