Continuing the
comprehension of the smallest infinite sets in the application architecture through dependency games, firsthand.
More tape!
I have a friend, his profession is connected with electrical installation. When he was younger and more cynical, he liked to poison bikes about electricians who worked on non-powered networks. The end was always entertaining, but sad for the main character. Component architecture is the same: somewhere you do not isolate one functional from another, it will “shock” both you and the one who will be after you. The difference is that insulation in IT is still more costly pleasure than in electrics.
In the previous
article, we already made the first engineering estimates of the amount of functionality of the new solution for Sberbank - the Unified Frontal System. We focused on quantitative estimates of the functional scope, on the methods of its production and development. It's time to talk about its connectedness and ways to isolate the functional.
')
First of all, we isolated from each other the system, application and integration functional. In fact, these are different "electrical circuits", with different "voltages" and mode of operation. It turned out the metamodel of admissible dependencies, as in the figure below:

Naturally, on the Sberbank scale, the application functionality is predominant. Therefore, let's talk about it separately.
The analogue of the "nonlinear electrical circuit" for the front-line banking system is the front-end scenario of customer service. Just like chains, frontal scenarios can be branched and include many subprocesses. The natural desire of every architect who has already worked on the “non-powered networks” is the desire to granulate the processes as much as possible so that any changes lead to less regression.
The analogue of the “linear electric circuit” for the Unified Frontal System is any state-less logic caused by frontal scenarios. Unlike the scenarios themselves, it has its own life cycle. In Sberbank, it is subordinated to the general program of replacing the legacy functionality with solutions based on its own promising back-up and middle-office banking automation platform.
Continuing the analogy, we wrapped individual electrical circuits with insulating tape and introduced the concept of a “module” - a group of applied functional that is strongly connected inside and weakly connected with another functional. Once implemented in code, it is a regular jar file and a pom artifact.
Although we tried to limit ourselves to a small unified number of rules for granulating the application functionality, we still needed a lot of electrical tape. On the server side, the target number of modules is> = 10
4 . Here are the rules:
- separation of state-less and state-full logic into different modules;
- separation of logic over entities of different domains according to different modules;
- putting in separate modules of any public API;
- separation into different modules of product-specific and channel-specific logic;
- allocation of modules for dependency concentration.
The result is approximately the following meta-model of modular concentration of an applied functional isolated from each other:

Granulation limits are determined by the stability of the API module (service API and API call a separate subprocess) when:
- changes in the requirements of the regulator and the customer's idea of ​​the target functionality for automation;
- changing the system or integration functionality to which the ESF delegates state-less logic;
- changing the sequence of state-full processing chains.
The size of a separate module is 20-50 java-classes.
So far, only 5% of modules have changed less than once a quarter, and this trend will continue in the future. This means that in order to comply with architectural safety precautions, you must add electrical tape directly to the modules themselves. It is good that such patterns as bridges, adapters and facades have already come up with us. All this became a natural electrical tape inside the modules themselves.
The general typical architecture for the most common application modules is shown in the figure below. Naturally, the emphasis is not on what is happening there, but on how it is isolated from each other.

By the nature of the granulation of the functional, from the point of view of the executing thread, the architecture of individual modules most closely matches the layered architecture. From the point of view of the final application, which includes a whole group of applied modules, depending on the dependencies, process driven architecture.
Granulation and abundance of insulation, in addition to the above advantages, has the following:
- all forms of interaction are well divided into typical, and for their participants, you can use either abstractions or marker interfaces;
- several independent development teams can edit the same module for several months, and it miraculously keeps working;
- bridges, adapters, and facades are good places for concentrating the “crutches” that appear at a particular stage of the “immaturity” or “over-maturity” of the code;
- easy top-level control of architectural violations. Just look at the pom-file and check the actual dependencies with the project;
- since the system functionality is always lacking, its early prototypes are easy to isolate at the level of individual application modules, and the resulting redundancy does not “spread out”, “poisoning the code”.
Among the significant drawbacks:
- high labor intensity of maintaining high granularity. Actually, bridges, adapters, facades, and a huge amount of code for re-placing one data structure into another require implementation;
- it is necessary to have advanced version control and impact analysis in order not to immerse the entire solution in jar hell;
- End-to-end cross-module code changes require synchronous switching from branch to branch for a related group of modules, and pull requests should be taken into account with inter-module dependencies.
Micro-monolithic dualism
Among the well-known laboratory works in physics for first-year students there are experiments with photons that simultaneously behave as particles (corpuscles) and as a wave. These experiments are used to illustrate the properties of wave-particle duality, incomprehensible at the household level. The Sberbank Unified Frontal System has very similar behavior.
The EFS has two requirements, each of which is in itself harmless:
- “Corpuscular requirement”: a change in any applied functional should assume a minimal regression of the adjacent, including similar functionality in other channels. The whole of the EFS should never fall through a continuous regression. In addition, the “corpuscle” of the ESF is inevitable due to the large number of teams that develop independently applied functionality.
- Wave Requirement: the change in customer service logic should be carried out immediately across all service channels. This is just the main idea, reflected in the name of the “Unified Frontal System”, to minimize the channel-specific costs for the output of the product in each channel.
In general, both requirements are contradictory and make you think about "interference and diffraction" in architecture. The first requirement is well implemented in microservice architecture, the second - in monolithic.
Problem solving - dependency management. We must have dependencies of the same kind, reinforced with minimum guarantee of regress and transparent, in terms of the requirements of introducing products across all channels. And vice versa, to have a group of dependencies “transparent”, in terms of volumes of regression, and reinforced concrete - for changing products.
The first group of dependencies that meet these requirements can be created based on the practice of Domain-driven design and a general understanding of the automated banking field. If we draw analogies with nuclear physics, it suffices to single out elementary stable
particles domains, the interactions between them are prohibited. Each application module must belong to a particular domain.
Below is an illustrative map of the domains we used. None of the modules related to a particular domain should be directly dependent on the module of another domain, if it is not at the top of the dependency chain.
Individual domains have their own hierarchical structure. For them, you can select separate subdomains, between which direct dependencies will also be prohibited.

The second group of "wave-particle" dependencies can be created by dividing the functional into cross-channel and channel-specific. The functional of the first group will be the product functional, and the functional of the second will be auxiliary. Then, by isolating the product functionality from the channel-specific method of constructing presentation logic, user authorization, customer identification, etc., you can build the circuit shown in the figure below.

Note:
- if the requirements of the regulator regarding the special procedures for interaction with the customer through the channel change, the code changes will take effect for all products of the channel;
- if the understanding of the business with respect to the product itself changes, all changes become available to all channels.
In our experience, for the last cited scheme to work, it is important to observe the following requirements:
- a developed systemic cross-channel functionality is required for the abstraction of the client service application scenario from a specific way of interacting with the client;
- we need a strict business architecture that classifies the final functionality and unifies interaction with the consumer.
Now you, dear reader, have everything for an independent understanding of the Schrödinger equation. ;)
If you love - let go
So what do we do with the number of modules? Let me remind you, in the target form of modules> = 10
4 . Moreover, the customer has the expectation that all the functionality can be replaced entirely at least once a quarter.
Despite the fact that there are less than two dozen basic design patterns for a typical application functional, for each automated operation it is necessary to do the following:
- modular decomposition of the functional;
- module layout by application;
- designing business entities and APIs;
- fixing inside modular dependencies and isolation.
Pulls on several architectural solutions. Everything is complicated by the fact that the pledged requirements for code reuse require knowledge of the content of the application modules.
Practice has shown that one architect, designing the component structure of an application functional, is able to remember the content of ~ 100 modules. So, we only need ~ 100 architects to manage all the application functionality. But this is already such a number of specialists, in which the architects themselves will not know each other. So, the problem has no administrative solution.
Fortunately, earlier Gabriel GarcĂa Márquez proposed a “counter-administrative" solution to the problem, which was included in the section heading. Now we are “releasing” the direct design of the architecture of the application functionality, since it is impossible to keep it on target scales.
We are going to know nothing about each module and proceed only to the control:
- the quality of designed new modules, comparing their quantitative characteristics with typical values ​​of statistically successful solutions;
- the nature of the changes in the code through reverse engineering;
- and provide content to automate the search for modules for reuse.
It is important here that reducing the IT architecture to large numbers (in particular, to a large number of typical components) is a solution that is good because it allows you to work out a common solution on a sufficiently large number of particular cases.
Chronicle of events:
- it all started with 20 application modules;
- when the modules became 50, an estimate of the target number of application modules was obtained and a preliminary metamodel of dependencies was constructed;
- 100 modules were enough to stabilize the modular component architecture and raise the question of automating the “production” of applied modules;
- 300 modules became enough to quantitatively reveal the “golden section” of ideal and acceptable in quality applied modules.
Now we have a number of projects working on an interim solution that allows us to carry out the internal design of the applied modules according to the functional configuration, the tool for which we described in the last
publication . The architect manually solves only one task - “lays out” the functionality for generation by different application modules, positions the modules in the final hierarchy by dependencies.
Perhaps, these new methods of forming applied architecture will even be called somehow rational. For example, Statistic driven application architecture. How do you? ;)
Technically, we are ready for full automation of the applied design process. And it is important that, unlike Gabriel Garcia Marquez, we know what reverse engineering is, which allows us to keep our favorite application architecture “on a leash” and control the manual development of automatically generated code. But it seems that this is already something from Darya Dontsova.
In conclusion, I note the following. There is a widespread opinion that only descendants will truly appreciate any creator (GarcĂa Márquez and Dontsova). In IT, and especially in the ESF, this is not the case. We are ready to consider new ideas and technological solutions. Join our
technology promotion "Promotion" !