Translation of Martin Fowler material. The article discusses the general approach to the UI architecture and provides detailed descriptions of design patterns such as MVC, MVP, Presentation Model, Forms and Controls, Humble View, Passive View. Article cleans the brain well. In order not to miss a single nuance, I decided to do the translation.
Generally speaking, squatted for a long time, I wanted to do everything at once and quickly. Finger to the sky. Sometimes
I was crushed by
radiculitis by the Milestone project and I set aside the transfer to indebtedness. Or something else interfered. In short, I didn’t master everything at once and, so that the good would not be lost, I decided to post the translation in paragraphs. Now translated half, half remained.
I am not a professional translator and could have misunderstood something (and even made marks in brackets in some places), but in any case you have the opportunity to read the article in the
original . I hope that the translation of such an interesting article will help someone to improve their skills and broaden their horizons.
GUI Architectures
Graphical user interfaces have become a familiar part of the software development landscape, for both users and developers. If you look at them from a design point of view, they represent a special set of system design problems — problems that have different but similar solutions.
')
My interest is to identify common and useful template solutions that can be used by programmers when developing rich (rich-client) clients. I have seen various architectures, both in the implementation of design inspections, and in more “permanent” style. There are useful solutions in these architectures, but describing them is not an easy task. Take, for example, Model-View-Controller. This decision is often perceived as a template, but I do not see much use in seeing it as a template, if only because the ideas contained in it are different in nature. Different people read about MVC in different sources and perceive its ideas differently, but they call these ideas the same way - “MVC”. This leads to confusion and misunderstanding of MVC, as if people were learning about it through a “broken phone”.
In this paper, I want to give a number of interesting architectural solutions and describe my vision of their most interesting properties. I hope that I will explain everything in a clear style.
In some ways, you can take this work as a tour of the history of various UI programming solutions over the course of several years. However, I must warn you. Understanding architectures is not a simple matter, especially when many of them change or die. Tracing some of the ideas is even more difficult, because different people see in them their own, different from what others see. In particular, I did not conduct a deep and thorough analysis of the architectures that I will describe. What I have done can be described as general descriptions of system designs. If I missed something, it means that I just don’t know about it. Therefore, do not take my descriptions as a guide. Moreover, I specifically leave some things simplified if they are insignificant. Remember that my main task is to describe the solutions to the problem, and not the history of these solutions.
(However, I contradict myself a little - in terms of having access to the working version of Smalltalk-80 so that I can study MVC. Again, I cannot say that this study was thorough, but it allowed me to understand some aspects of the solution that other descriptions could not explain - which, in turn, pushes me away from the intention to present my description of other architectures as the only true one. wrong or something missed, then I would like to know about it I also think that a more thorough analysis of what I will talk about will serve as a good subject for study in universities.)
Forms and Controls (Forms and Controls)
(Fowler very zealously uses the notion of control, which can be left as “control” or translated as “control”. Alas, in Russian there is no word “control” (even though it is commonly used in slang), and do not torture your eyes, then I will call the controls simply "elements." - approx. transl.)I will begin this study with an architecture that is simple and familiar to most developers. It does not have a general designation, so for the purposes of the general rules of this work, I will call it “Forms and Elements”. This architecture is well known primarily because it was provided by client-server application development environments such as Visual Basic, Delphi, Powerbuilder. Despite the fact that it is rejected by such steep architectural solutions as I do, they still continue to use it everywhere.
In order to understand it (and understand other architectural solutions), I will use a common example for all. In New England, where I live, there is a government program for tracking the amount of ice cream in the air. If the concentration is too low, it means that we eat too little ice cream, which, in turn, represents a big risk to our economy and public order. (I like to use examples no more real than you find in other books like this one).
In order to keep track of our ice cream, in all the states of New England, the government has built special tracking stations. Using a complex atmospheric model, the department assigns a target (target) value for each station. After that, the staff goes to the station to assess the concentration of ice cream. The UI below allows them to select a station and enter the date of the measurement (date) and the actual value (actual) of the concentration. The system calculates the variance between the target and the actual value. Moreover, if the actual value is less than 90% of the target, the deviation is highlighted in red, and if greater than 105%, then green.
Figure 1: UI, which I will use as an exampleTwo important details can be distinguished from this view. A form is application-specific, but it uses controls (controls) that are common to other forms. Most GUI development environments have a set of common elements that can be used when developing applications. We have the ability to create our own elements (and this is a good idea), however, application forms and reusable elements are still different from each other. In other words, created elements can be used in many different forms.
The form has two main responsibilities:
- Screen layout: the form determines the location of elements on the screen, combining them into a hierarchical structure.
- Form logic (Form logic): the form defines the behavior that can not be programmed in the elements
Most GUI development environments provide a developer with the means to define a screen layout, for example, a graphical editor that allows you to drag and drop elements onto a form. This, in principle, is enough to create a layout and easily adjust the arrangement of elements on the form (although this method is not always the best - we will return to this later.)
The elements represent the data - in our case, this reading. The data is very likely to come from somewhere else. For our case, suppose that from the SQL database, since it is the main data source for the development environments mentioned. In most cases, the application has three copies of the data used:
- The first copy is the database itself. This copy displays the data records in the actual data store - DB, so I will call them (data) record state . Usually, using various mechanisms, several people can access the recording status at once.
- The second copy is stored in the application's memory as a Record Set . Most development environments provide easy ways to get a set of entries. The data in them is relevant for one specific session between the application and the database, so I will call the record set the session state . The essential characteristic of the session state is that it creates a temporary local copy of the data with which the user works until he saves or commits a commit to the database — while the session state is merged with the record state. I do not want to analyze in detail the ways to make the union: I already did this in [P of EAA].
- The third copy is stored in the GUI components themselves. Strictly speaking, this is the data that the user sees on the screen, so I will call them the screen state . It is very important how the UI synchronizes between session state and screen state.
Synchronizing screen status and session state is a very important task. The tool that can solve it is
Data Binding . The idea of ​​data binding is that a change that occurs in the data of an item or record data in a record set immediately spreads on each other. That is, if I enter the current concentration on the screen, the “text field” element updates the value in the column for the corresponding data record in the record set.
Implementing data binding is a rather complicated exercise because you need to avoid such cycles, for example, where changing an element changes the data set, which updates the element, which back updates the data set, which updates the element again ... flow of usage helps to avoid such cycles - we load data from the session state to the screen state only when the screen is opened, then any screen change is propagated back to the session state. Updating the session state when the screen opens is unusual and unnecessary. As a result, the data binding may not be completely in both directions - it may be limited to initial data loading and processing screen changes to the session state.
Data binding, generally speaking, implements most of the functionality of a client-server application. If I change the value of the actual concentration, the value in the column will be updated. Even selecting another station will cause a change in the selected record in the record set, which in turn will force other elements to update.
Basically, the described behavior has already been implemented by the developers of application frameworks, who have provided and provided the means to quickly and easily meet the basic needs of programmers. In particular, one of the ways is to explicitly set some characteristics of controls, which are usually called "properties". The element reads the string name of the dataset column, which was specified by the developer through a simple property editor and binds to it.
Using data binding, with the necessary parameterization, can help you implement almost all the functionality of the application. However, data binding cannot implement ALL of functionality - almost always there is logic in the application that does not fall under the parameterization options. In our case, the deviation calculation is an example of what cannot be implemented through data binding - because such functionality is application-specific and is implemented in the form itself.
In order to implement it, the form must know when the user has finished entering the value of the actual concentration, and this, in turn, means that the control should trigger some form behavior. Such logic implies inversion of control (Inversion of Control).
(In the original "This is a bit more a bit more than a little bit more than a little bit.)There are various methods for solving this problem. Typically, client-server application development environments have an event presentation system. Each control has a list of events that it can trigger. Any external object has the ability to tell an element that it is interested in an event. In this case, when an element event occurs, the element will transfer control to such an object. Essentially, this description is just a reformulation of the
Observer template, where the form follows the element. The application framework allows the form developer to write code in a method that will be executed after an event occurs. The way in which the connection between this method and the event occurs depends on the specific platform and is not important in this case. It is important that such a mechanism exists and it works.
When the form has control, she can do everything she needs. It can perform some actions, change the controls, and, based on data binding, make the changes made back to the session state.
Such a mechanism is also needed because data binding is not always available. There are a lot of window controls in the world and not all of them support snapping. If there is no binding, then the form must deal with the synchronization of data between states. In particular, it can pull the data from the data set itself and put it into the controls. When you want to save the data back, it can do it in the same way by the event of pressing the "Save" button.
Let's take a look at how the current concentration value will be edited when data binding is available. The form stores references to controls. Each element will have its own link, but I am only interested in text fields for the actual value, the deviation value and the target value.
Fig. 2: Class diagram for forms and elementsA text field announces an event when its text has changed. At the initialization stage, the form collects itself and subscribes to the event, binds its method to it - here,
actual_textChanged
.
Figure 3: Text flow chart.When the user changes the actual concentration value, the text field triggers its event and, using the special magic of the application framework, executes the form method
actual_textChanged
. This method gets the actual and target value from the form elements, performs calculations and sets the deviations in the difference text box. It also calculates what color to highlight the resulting value and highlights it.
Now we can summarize:
- Programmers develop forms that, with their functionality, depend on the specifics of the application, but use controls common to all forms.
- A form describes the location of its controls.
- The form follows the events of the controls and processes them.
- Simple data changes are synchronized using data binding.
- Difficult changes are made in methods - event handlers.
The next part is
here .