From advertising management system, to the examination and approval system, design of ERP system, tax management system, the raise information management platform, research and development process management system, make the front over the years I have developed a lot of such a system, now everyone seems to like to call them in the backend system, or B end system, I think they are typical complex front-end system, This article hopes to summarize the difficulties in developing these systems and the key points to pay attention to when solving them through my experience.
This article mainly focuses on functional scenarios and models, rather than technical selection. The technical solution is helpful to solve the problem, but does not change the essence of the problem. For example, compared with jQuery, Redux requires no less requests, but it simplifies the conversion of data to view and the binding of events.
So what is a complex front-end system? What are the difficulties in development?
Visually interacting, we can see that systems with the following typical elements are often more complex. Forms, pop-ups, tabs, pages, load more, tables, etc. So why do these elements complicate the system? Let’s take a look at each one:
The form
From the beginning of traditional websites, forms are the difficulty of the system. They are complicated because users need to enter data through them, and they also involve the form validation that we are all familiar with. Problem after using the tools such as Redux, get a degree of simplification, the problem of model also becomes clearer, the form of each project is a status value, with the user’s input binding, and may also have associated logic between each form items, even the associated data request, such as the user to select the value of the project, You need to request data for related subprojects. There’s also the familiar input suggestion, which offers options for retrieving data in real time based on user input. Form validation adds error-related state to each form item, including whether there are errors and error messages. Based on forms more complex interactions have cooperate popup window form, form nested form and so on, is the main model for a form item need to choose or new information, such as the form of address, and address items can be added, this involves the communication between modules, after completion of the new information need to update the data in the form according to the new information.
TAB
Very common elements, mainly listening for click events to switch between modules, the complexity is that each module may have its own initialization logic, and modules may have relationships, or in some cases need to reset the module state when switching.
Pagination, load more
It is also a common element that updates and adds data inside the module, receives user click events and requests corresponding data.
form
The complexity of the presentation table is not high, usually there is only an initial request, after the data is loaded directly render. Complex tables have two directions:
- Internal operation type, common for example, for each piece of data delete button, or even click the delete button after the need for confirmation popup or confirmation floating layer, which requires more state control. And sometimes there might be an edit button that updates the form by popping up or switching the table rows to an input field, and that’s when the form is rolled in.
- External actions, such as common checkboxes and external action buttons, operate on selected rows, and common filters on tables.
- In addition to these two directions, there are some difficulties with purely front-end presentation features, such as tables that don’t fit on a screen and sometimes need to follow the table header when scrolling, but these difficulties are not the focus of this article.
summary
Through the analysis of these typical elements above, I summarize the reasons for these elements to increase the system complexity in two aspects, one is to increase the number of modules, the other is to increase the complexity of modules. The complexity inside the module involves user events, data requests and data states, which are interrelated. For example, user events often change the system data states and trigger data requests, and the data returned by data requests are generally part of the data states.
The module
This is a relatively independent function block. Technically, it is usually represented as the corresponding part of a substore of Redux, which usually has its own states and may need to make some requests to get some initial data. General module’s lifecycle is request to do data initialization, respond to user events change the internal state, also may be some data request, sometimes may need to reset the status or the renewed initialization data request to refresh their own data, at the end of the life cycle may also need to clean up their own state data.
Communication between modules
The increase of system complexity after the increase of modules is not linear, which may be geometrically increased due to the interaction between modules, and the communication method between modules is also a key concern of the front end. A very important problem solved by Flux model is the chaotic communication mode between modules. Under the one-way Flux data flow model, common communication modes between modules are simplified into the following two.
- By the Action. Because the main states of the system in the Flux system are all in the Redux state, as long as the corresponding state is changed through Action, the corresponding module will receive the change, and the influence of these changes can be directly reflected in the view, or the corresponding module can monitor the change of properties. Make side effect responses where appropriate.
- Father and son corresponded. The parent module can let the child module get the latest data state by passing the attribute value, and the child module can notify the parent module of its state change at any time by passing the attribute function.
The timing of the communication between modules in general at the end of the initial and module, the module relationship such as brother step, step on it during the at the end of our information is stored and open the next step, or a parent-child relationship such as we mentioned above in the module module new address fill in the address when the new address, new address module after the new address information back.
If there is frequent communication between modules, it is likely that they can be grouped under the same large module, such as the table mentioned above and its external action and filter buttons.
Reuse of common logic between modules
For example, multiple modules may need the same logic to verify the operator’s permissions and give a hint when the permissions are limited. For example, multiple modules need to make the components perform certain logic according to the mouse movement position. At present, HOC and React Hooks are the main solutions to reuse problems. Although reuse cannot reduce the complexity of the module itself, it can reduce the workload when we develop multiple same functions.
User events
This includes common events triggered by input boxes and buttons, such as onChange, onClick and onScroll, etc. They are undoubtedly the core of the whole front-end system, because they represent the user’s operation, and the user’s operation is the entrance of the system operation, adding the entrance naturally increases the complexity.
Data request
Ten years ago Gmail showed us what Ajax could do in the browser, kicking off a decade of great front-end development. So why is it special? What are the core functions of our WEB applications up to now? In fact, it is still the data communication capability and local refresh with it anytime and anywhere, which is why the WEB Application has a name called RIA – Rich Internet Application, and the level and density of data request is also an important factor of module complexity. Of course, there are not only Ajax data requests, but also WebSocket and SSE, which make the logic of data requests more complicated.
In some cases, our module cannot obtain all the required data only through one request. For example, trivial interface or complex data source, it needs to assemble data. For example, after requesting list information, it needs to request detailed association information of each item. So if you have GraphQL to solve under-fetching and over-fetching problems, and the server provides data, modifying the server is an important way to solve any fetching problem. Of course, if the server side is not easy to change, many times the front end has to solve the problem itself.
Redux Saga and Redux Observable are designed to handle complex event and data request logic, which in Redux’s case means actions and Side effects.
Redux Saga can be used to simply describe competing requests (Race), non-blocking requests (Fork), waiting for All requests to complete (All), and so on. You can control the sequence of actions including data requests. For example, in a typical Login and Logout process, you can Logout only after you Login. The subscription model can also be implemented within the Action layer through Put and Take. For example, in the first Saga, the execution process of the sequence of actions before and after a data request is defined, and in the second Saga, the process of the data request itself is defined, for example, to fetch data from multiple places for assembly. The first Saga publishes the data request action by putting, and the second Saga responds by subscribing to the action by taking every.
Redux Observable and the RxJS behind it have more powerful event control capabilities, such as easily listening for Triple Click events, and defining multiple event trigger relationships. For example, multiple events must happen before the whole event can be triggered. Any subsequent occurrence triggers the whole event.
The complexity of events and data requests, or Action and Side effects, depends not only on the number, but also on the timing and logic between them.
state
The concept of state in the modern framework is the core of one-way data flow. It is found in tools like React and Redux. I believe you can understand that the more states a system needs, the more complex the system will be.
conclusion
With all that said, you might be thinking, what’s the use of all this stuff? In my opinion, the above model basically abstracts the framework we need to solve the problem. When we receive the requirements of a new system or a new functional requirement, we can first think about which modules there are, whether there is communication between modules, when they need to communicate, and whether there is common code between multiple modules. For each module, you need to think about whether the module needs to initialize and reset data, what user events are inside the module, the logic and timing of retrieving data, and what states the module needs to record. Did these thinking after we for the complexity of the system have a general understanding, for evaluating workload and make scheduling plan is of help, more important is if you don’t want to early these important details we may be found later in the development of them, they may even have been neglected thus cause online Bug, Module resetting and timing logic for data requests are common and often overlooked issues.
In addition, we can present some typical functional scenarios based on the model, and then compare the pros and cons of implementing functionality with different technical frameworks, so that we can compare specific code rather than argue about it out of thin air.
In the end, I hope these thoughts can inspire others and welcome your criticism.