Pro M and Pro V and Nemoj Pro C
The news from a number of pleasantly unexpected awakened all sorts of memories, sweet and not so good. And from it I got on this article , and at once I didn’t want to be nostalgic, and from the height of the past seven years, I wanted to follow such a weighty ellipsis after it.
Dephi was a completely brilliant decision. Well, you know, like the Beatles, like a graphical computer interface with a mouse, like an internal combustion engine. The ingenious solution that came into our lives so widely that they no longer believe that it was once there, and drawing windows, checkboxes and buttons in Windows could be a real pain.
Brilliant, absolutely, part of Delphi was VCL - the very same set of checkboxes and buttons for Windows windows, which suddenly became so easy and simple to drag on each other, and create beautiful and unusual Windows applications.
And like any decent UI, this one worked, of course, according to the event model. OnClick in the button object described everything that the button does, OnChange when typing in the text field, everything is just like adults. But further - further, unfortunately, there was still nothing.
None of what we know now, I mean. MVC, for example - Delphi, consider, consisted of one V, then everything remained at the mercy of the developer. Directly from OnClick to pull the request into the database? Yes please. In OnChange, open any file and try to write to it, and if the file was not in place it quietly crashes with something like Memory Access Violation - at every step (however, this has nothing to do with Delphi as a platform).
And it must be said that for many years this suited everyone perfectly, but it still suits some of them to this day. The benefits of a slim and beautiful UI component library are immediately visible; the benefits of all controllers and models become obvious not in the first year of development, and not in the first hundred kilobytes of source code.
And even if it has become - it is easy to forget about it, there is a mind trap, like those optical and sound illusions about which they argue furiously on the Internet. So let me try to throw a small bridge from Delphi to the modern understanding of the UI and we can figure out what happens.
So, the key idea: we separate the presentation from the data, the widget is separate, all work with the information in it is separate. How separate? For example, the button still has an inscription, and sometimes an icon. In the text field, this inscription can be driven in by the user, and sometimes the text field has another inscription explaining to the user what it is driving. The general rule: the widget deals with the display, the minimum (SIC!) Of the logic that can be present in it should be associated only with the display and nothing else. For example, if a button is not ready to stretch along with an inscription on it - the label should either be cut off (for example, show ellipsis and the full version in ToolTip), or give an error when trying to set a value greater than it fits (really the idea is so so
The text entry field can eject carriage translations from the text if it is single-line, but it is not necessary to require, for example, that only numbers should be entered into it - this is not his job. As well as in the handler for pressing the button, no checks are needed, no redraw calls, the button handler must pull the external code, which is already responsible for the logic of the UI and the entire application.
And if you live in the beautiful new reactive world, looking from top to bottom at all this OOP-event fuss, then the principle still remains the same: pressing the button changes the state, adding the appropriate Action to it, and then some code, no code associated with elements of the UI, look at this Action, and draw the appropriate conclusions, and change the state so that there is something to display on the UI back.
That is, regardless of the environment, the platform and the paradigm, the visual elements themselves carry a minimum of functionality and zero logic in themselves. Receive information in the most general form, so if you have a TextBox, it is also Input, it is the text field, it takes exactly the string, and gives the string. And the task of turning a line into a number, whose name or something even more cunningly is no longer for the widget.
Well, then the Controller, or Presenter, processes the result and gives the result. Call him as you are accustomed, but do not pop into him any visual elements.
What is the profit? I list in order from the most obvious to the most, in my opinion, essential.
Firstly, reusability. Quite a lot of time is spent on it to understand that the field for entering a postal address, for entering a surname, and for entering a sum is, in fact, the same field. The same widget, with the same set of features, comes down to jerking a text input event or updating a state. And only the logic of working with text inside it may differ. An example of “how not to” from life: make a field for entering a sum of money (up to two decimal places), and then fiddle with it for a long time, reworking it so that you can sometimes enter the same amount in the same field (up to 4 decimal places) . Break in the process all the places where the amount is entered in the application, and rush to repair them in the middle of the night. This is despite the fact that according to the logic of their work, they had differences in the third decimal place.
Secondly: testability. You can test and UI. Almost any UI. But it will be expensive, in terms of time and resources spent on developing tests and executing tests, and they are unlikely to be launched at every reassembly, but when tests crash on the release, it will be force majeure. But UI-components are the most risky in terms of breakdowns, they break, as a rule, most often, most obviously, and most painfully. But the code from the widgets themselves torn off, really cover unit tests (unit tests). And unit tests are much cheaper - and it is easier to write, and you can run literally after any changes, and always be sure that nothing is broken.
And third, the most important, in my opinion. Drawing a piece of UI together with logic in one piece is extremely difficult to defeat laziness and ponder deeper into how it works. To work out scenarios other than ideally positive, when the user entered exactly what was expected of him, did exactly what was needed, and got exactly what he wanted. That, sacramentally programmer "all works for me".
Separation of the visual part and the logical part makes one wonder, first of all, on how the visual part works: what comes into it, what comes out of it, what happens if it is not exactly what was expected or entered. And writing logic separately from the control forces writing it according to cases, that is, according to possible usage scenarios in a particular place of a particular application, including processing errors that occur exactly here, and helping the user in the difficulties he is experiencing here. Well, yes, not always, or rather not in everything, the solution in general is better than the solution sharpened for a particular case.
Summarizing. You can write on Delph, or an application for iOS, torment the long-suffering web some-there-0, or rivet some microcontroller game on Python, if your code has outgrown the formula “one form, one request, one result” - I tell you I strongly recommend to decisively separate the widgets from any logic of their work, and then there is a chance that there will be fewer flies in your cutlets. And in spite of the initial perfect non-obviousness of the advantages of such a decision, the further you work with it, the more these advantages will appear to you.