📜 ⬆️ ⬇️

Mobile platform. ReactNative Hybrid Application Architecture

Probably, you have already heard about mobile development on ReactNative in the Unified Frontal System (EFS) of Sberbank. We have already written why we use the ReactNative technology itself in our developments, and also told us how not to be afraid to do it.



Today, we will take a bird's-eye view on building mobile application architecture using ReactNative, Objective-C, Typhoon, VIP, SOA, TypeScript, React and Redux.

About architecture and its premises


Let's start from afar and first formulate the main tasks that the architecture solves, when it is necessary and expedient, and what requirements it must meet.

When work occurs in a startup where 6 people are sitting in the same room, communication is built on a short leg, a single product is created around which the entire team is concentrated, then usually the developers in the first iterations (until the product understanding is aligned) do not care much about the solution architecture. flexibility, cost of change, reliability, scalability and much more.
')
Usually in such groups and companies, decisions are made quickly and are built by enumerating various hypotheses and experiments.

The cost of changes is quite small, and the speed is quite high. At the same time, integrated productivity remains small, but this is not required in companies of this scale.

The question of formalized rules and approaches to the design and construction of complex automated systems usually appears in large companies with a large number of individual systems requiring integration, as well as a large number of developers distributed among different teams.

Each of us associatively understands what the term "architecture" means. However, besides the definition itself, the architecture must solve certain tasks and fulfill the requirements imposed on it.

The requirements that are imposed on the architecture may be different, but in most cases there is a fairly general list of characteristics that simultaneously fits most systems:


and etc.

One of the main tasks of the architecture is to meet the requirements. Also, do not forget that technical requirements are born from the requirements of the business: a good architecture should quickly find and fix problems, quickly update the system, ensure trouble-free process, quickly deliver new products and features to the user, and much more.

Task: "Building a city"


Let's solve the architectural problem:

Required to design and build a city. The city is Sberbank.

image

The city has houses in which people live and various organizations / institutions in which people buy goods or receive services. People are Sberbank clients.

The houses in which people live and the establishments they visit are the interfaces from Sberbank, which they use.

The houses have gas, electricity, water, which are delivered and delivered to the client, in the shops - food, clothing, household appliances - all these are services / products of Sberbank that people use.


Water, gas, electricity, as well as food and other goods are somehow delivered to people in homes and shops - and this is done thanks to the powerful back-end infrastructure that is hidden from the client (water-power stations, hydroelectric power plants, nuclear power plants, factories, storage facilities and etc.)

And now to the requirements of the architecture of the city:


We are architects with you - specialists who build this city and solve all the problems and problems that arise. The task is not easy, but extremely interesting.

Her decision cannot be fully covered by one article, so first let's talk about how we build houses in practice!

How we build houses or 3 levels of architecture


So. We need to build houses. Build quickly, but the quality of the houses should be top notch. Homes should be modern and comfortable (i.e. meet UX requirements). We must ensure the possibility of a quick withdrawal of new services even in old houses.

At home, as we said, these are the EFS interfaces. Interfaces are channel-specific, for example, there are mobile and web-interfaces, a contact center, branches, ATMs, etc.

One of the key tasks of the ESF program is to create the ability to quickly output services to all channels (omnichannel output), to ensure recognition and a single visual style of interfaces for interaction with the client.

We will devote this article to building mobile interfaces, and also prepared some interesting steps for the future for dessert.

Let's go back to our comparison with urban planning and architecture.

So, classic houses are similar in their structures and appearance and are divided into certain classes (patterns): panel house, brick, high-rise building, cottage, summer house, etc.

In addition, houses have similar structures or typical elements inside themselves, for example: a wall, a window, a door, a roof, a lightning rod, etc.

Each of these structures is built from atomic elements - building materials: brick, board, nail, glass.

As a result, we get 3 main levels:


In our world of mobile PL (Presentation Layer) architecture, there are also 3 levels:


Components are building materials.


Our mobile interfaces are built from atomic (indivisible) entities, which we call components.

Some of our basic rules when designing components:


Examples of the simplest visual components for building screen forms are buttons, input text boxes, radio buttons, check boxes, switches, etc.


Each component is a full-featured, complete module that does not depend on others. To implement modules on native Objective-C code, we use the VIP architecture (View, Interactor, Presenter).

We took VIPER-architecture as a basis, which is well-designed for creating separate modules and their further re-use. We removed the Router, because transitions between modules are carried out at the level of the application code, i.e. TypeScript.

It turned out that the application developer, using the methodologies of the React approach, can develop a mobile application, importing our components and even unaware of how they work at the native level.

Let's look at a small example of how the whole chain works based on the TextInput component.

TextInput is a simple component designed to enter text into it.

The component is visual, so to display it on the screen, you need to insert a JSX tag in the render () method of the parent component.

Currently, the component has 14 properties:
Property
Type of
Description
maxLength
number
Maximum number of characters
value
string
The value displayed in the field. It can be used both to set the initial value and for subsequent control over the content.
label
string
The specified text will be displayed as a caption over the input field.
placeholder
string
Placeholder, displayed in Input, if no value is given.
disabled
bool
This attribute disables the element and does not allow the user to edit it.
keyboardType
UFSLibrary.KeyboardType
Keyboard type from the KeyboardType dictionary.
onChange
function
Called every time a user changes a value in a field.
underlined
bool
Sets the horizontal line below the component. By default, the property value is set to true.
onFocus
function
Called every time the field becomes active.
onBlur
function
Called every time the field goes out of active state.
hasError
bool
Sets the component to an error state (the title and underlining are colored red).
errorText
string
The message displayed in the error state of the component.
hasWarning
bool
Specifies a warning state for the component, provided that hasError = false (the title and underlining are colored yellow).
warningText
string
The message displayed in the alert state of the component.

Our attention needs to be concentrated on two: text and onChange. These properties are important for the demonstration of one of the basic principles adopted in React and, accordingly, in the Mobile Library: the component does not store states, i.e. is stateless.

To our team, the term did not seem to accurately describe the actual state of affairs, and we added another important term: the component does not store values, i.e. is valueless .

In other words, if we enter text in the TextInput component, the text property will not change. For correct behavior, we need to save the return value of newText from the onChange callback in the Redux-store and reassign it to the text property of the TextInput component. Read the previous phrase again, and then look at the picture below, which demonstrates it.


.TS - TypeScript component interface
RN - ReactNative
VM - View Manager (class for working ReactNative)
A - Typhoon Assembly, which is used to assemble a native VIP module
P - Presenter
I - Interactor
V - View

Viewless components or services


Components for building interface forms are not the only components. To implement full-fledged mobile applications, and not just flattened screens, we need to be able to work with the network, databases, files, notifications, etc.

To do this, there is a special type of components, called Viewless - components that do not have View, i.e. visual part and display capabilities.

An example of a component of this type is Log.

The Log component provides a convenient API to the application developer to work with logging: the ability to record events in a log file in a specific format, as well as further uploading to the server by a command.

When building Viewless components, we follow the standard principles of a mobile SOA architecture: i.e. create a number of service classes and a number of core classes. Classes-services can use core-classes, but cannot use classes-services. By the way, the same service classes can be used by integrators of VIP modules of visual components.

Below is a diagram of how the chain of calls hiding inside the Log component at the native level looks like.


.TS - TypeScript component interface
RN - ReactNative
B - Bridge (class for work ReactNative, inherits protocol RCTBridgeProtocol)
A - Typhoon Assembly, used to assemble a native Viewless module.
S - class service
C - core class

We talked about two fundamentally different types of components that we have: visual and non-visual (component services). It's time to talk about how the components are organized and where they are stored.

The place where the components live is the component library


Components do not live in chaos - there is a centralized repository that unites them, provides access to them and ensures their integrated performance. And this repository is a library of components.

The component library is a native compiled framework that is statically included in the final application. As mentioned earlier, each library component available for use has a TypeScript interface.

The library is located in the Nexus corporate repository and is connected to the project as an npm package. To make life easier for JavaScript developers who didn’t have (and most importantly shouldn’t) experience with native Objective-C code, Xcode and many others, we implemented a number of scripts that automatically link the framework in the post-phase npm install and configure. xcodeproj and collect the basic binding for the implementation of the application code.

A library is not only a set of visual and non-visual components, but also a set of auxiliary files containing a common part (base classes, decorators, helper classes, macros).

The library has a division into 3 levels, which we call PL (Presentation Layer), BL (Bridge Level), SL (Service Layer).

PL are full-featured VIP modules, i.e. components for building interfaces.

BL is an intermediate layer that serves as an adapter for using components from the Application Level in TypeScript. This level includes application interfaces (.tsx), classes required for the execution of ReactNative (ViewManager, ShadowView, etc.)

SL is an SOA layer consisting of service classes and core classes. Services can be used from the application level, for this there are Viewless components that through the BL provide access to native calls within the service classes. Also services can be used by VIP-modules at the native level through their interactors.

The diagram shows the interaction of all three levels with each other:


Of the unfamiliar letters on the diagram, only W is present. W is the Wireframe, the class connecting the VIP modules at the native level. The topic is quite interesting and large, so be sure to tell about it next time.

You can talk endlessly about the library of components and we will certainly do this more than once - leave questions in the comments that look interesting first of all or seem incomprehensible.

We assume that we have building materials and even an excellent ordered warehouse, in which it is always clear where everything lies and it is impossible to get lost. Now let's go to the level above and talk about building houses and highlighting their common parts.

Learning to build applications


Having a library of ready-made components, you can easily assemble mobile applications that implement typical business tasks. Mobile applications can now be assembled by developers with competences in TypeScript, and the library “protects” them from the nuances of developing for mobile devices.

All projects use the same components, which allows interfaces to look recognizable in different applications. If a defect is found inside the components, all applications will receive updates, when the appearance changes, all applications will receive a new component appearance.

We have provided application developers and designers with a set of LEGO cubes from which to build interface forms and applications.

But we, of course, thought this was not enough and we wanted to reuse even more.

Currently, applications that use the library are applications for internal bank employees (tellers, field specialists, collectors, financial advisors, etc.). Each employee has a mobile workplace (MRM) in which he works. Those. MRM is a set of some implemented functionalities that solve a number of tasks of a specific employee role.

The example shows the possible tasks that an employee in an MRM can solve and the processes he faces.


The number of roles of employees within Sberbank exceeds all possible ideas of humanity about the concepts of extremity, therefore, looking widely, we noticed that most of the roles have intersections in a series of tasks and activities.


Those. we see that there are whole chains or sections that must be present in all MRM, regardless of the role of the employee. In our understanding, these are the very common constructions from which the final house is quickly built (in our case MRM).

As we said earlier, the final application is developed on the TypeScript stack, React + Redux, therefore the part cut out from the application is developed on the same stack.

It turns out that the general sections inside the MRM is a part of the code written in TypeScript that uses our library of mobile components.

Fine! It remains to arrange this part of the code in the form of something finished, give it a name and draw a diagram. The name appeared very quickly, as it has long existed in the world of JavaScript - JS Bundle.

A new layer appears - reusable JS Bundle, which is also stored in the Nexus corporate repository. The application developer of the final MPM application in package.json specifies the dependencies on the JS Bundle and includes them in its final code at compile time.

This approach allows you to reuse the JS Bundle, but introduces one major disadvantage for the business: due to the static inclusion of the JS Bundle, the number of MRMs that are designed to work for various employee roles is growing.

It turns out the following reuse scheme:


In addition, each JS Bundle (orange color) necessarily uses the Component Library (yellow color) in its implementation.

What's next?


We do not stop. We always understand that we can do better, therefore we strive to simultaneously make both an innovative technical system and a convenient tool for solving business problems.

In the near future we will be engaged in two monstrous tasks:

  1. Cross-platform library (mobile and web) components;
  2. Dynamic mobile workplace.

About the last task I want to add a few thoughts. In essence, the task should solve the problem of a multitude of mobile applications assembled by roles.

The idea is simple - the mobile application is one and all the required functionality is dynamically loaded depending on the role.

The task is feasible precisely because of the use of hybrid technology ReactNative. Right now in the release build JavaScriptCore interprets the input js files located in the local NSBundle.

Our idea is to manage the sources of the files for interpretation. In other words, we want to develop our own framework that allows us to determine the necessary dependencies by user role, download them, cache, update and roll back. Code name - Start Manager (CM).

The tasks to be implemented in this new system are much broader. In addition to managing dependencies and actually assembling MPM on the fly, the SM must solve SSO tasks between all JS Bundles, use a single API, “deliver” reference requests for MPM, and much more.

We are waiting for you!


So! Our plans are ambitious and ambitious, and the scope of work is great. The team of the ESF Mobile Platform needs help in the form of cool mobile specialists from various fields.

A new team is being created right now to embody the architecture of the future and we need:


Join our team!

In order to do this, send your resume to our email addresses and a couple of suggestions on how you would like to help the ESF Mobile Platform:

Rtishchev Evgeny ESRtishev.SBT@sberbank.ru
Ostrovskaya Anastasia ASOstrovskaya.SBT@sberbank.ru

Source: https://habr.com/ru/post/325210/


All Articles