📜 ⬆️ ⬇️

Ways to transfer control between software objects

Program objects are ordinary classes from OOP. By the interaction of software objects, I will imply the transfer of control from one class to another.
This can be done in two ways. Further I will call them: objective and event . The names are taken from the object-event paradigm, implying the presence of objects that trigger and handle some events. But in my case, the meaning is different. Also, in order not to be confused, let us call the first class, from which control is transferred by the manager , the second class, which takes control, respectively, by the executor .

Since I am used to working with the C # language and the .NET Framework, I will use them in the examples and explanations. At once it is worth saying that in C # the event mechanism is implemented through delegates - pointers to a method with a pre-specified interface. For the same purpose, suitable pattern Command or Observer. Despite the differences in implementation, they are equal in meaning. Both perform the same task — they notify an event of an unknown subscriber or subscribers.
I will consider a situation when only one of the objects knows about the other. There are still options - both know about each other (strong connectedness of classes), or no one knows about anyone (universality, the use of the Facade pattern, etc.).

Description

Object method means that one class (performer) provides some method to the outside through its interface. The second (manager), having a link to the copy of the artist, can call this method. When this happens, the transfer of control from the first object to the second. Here is an example in C # (I think that they understand C # ++, they will also understand):

//
class Worker {
public void doWork() {
//....
}
}

//
class Boss {
Worker worker1 = new Worker();
Worker worker2 = new Worker();

public void startProject() {
worker1.doWork();
worker2.doWork();
}
}

As you can see, the Worker class knows nothing about who made it work, who it belongs to. On the other hand, Boss knows perfectly well what kind of workers he has in subordination, how many of them and what kind of work they can do. Summarizing: the class manager (Boss) knows the interface of the executing class (Worker), but not vice versa. The manager must know the number of performers.
image
')
The event-based method of transferring control works a little differently. One class through its interface announces that it can initiate some events. The other class, knowing this, can subscribe to these events and process them if they occur.

//
class Worker {
public Worker(Boss boss) {
boss.projectStarted += new EventHandler(doWork);
}

private void doWork(object sender, EventArgs e) {
//....
}
}

//
class Boss {
public event EventHandler projectStarted;

public void startProject() {
if (projectStarted != null)
projectStarted.Invoke(this, new EventArgs());
}
}


Now the Boss class knows nothing about who will execute its commands, it simply announces the “projectStarted” event. Those who want to do their work (class Worker), definitely know who they work for. A specific instance of Worker will only perform its work with a team of a specific instance of Boss. In contrast to the object approach, the performer knows the manager's interface, and the manager does not know anything about the executors and their number.
image

Application


The problem of applying the appropriate approach arose in the implementation of Model-View-Controller. Control from the controller is passed to the view and I needed to decide who I should know about: Controller about View or View about Controller?
First, let's look at how it is implemented in others. Let's take some UI Control from the WinForms library (forgive me, adherents of other UI frameworks), for example, Button.
The first thing that comes to mind when we think about buttons is the Click () event. In the overwhelming majority of cases, we use them to process clicks. In the event approach, events are initiated by the manager. So, the button from WinForms, when it needs to transfer control, is the manager. Now let's take a look at its methods, for example, the Title property. It is responsible for the inscription that we see on the button while the application is running. The button provides methods for working with yourself through its interface and, therefore, plays the role of a performer. How so, the button and the performer and manager? Why not? In addition, the button is even called accordingly - UI Control. On the one hand, it is UI, i.e. performer, on the other hand, she contol, i.e. controller controller
When designing a button class, we have one problem - we don’t know where the button can transfer control and from where it can get control. But the behavior must be implemented. Let me formulate an obvious conclusion, which nevertheless allows a better understanding of the nature of the system design. Transferring control to the unknown, we use the event mechanism, getting control from the unknown, we use the object mechanism.
Picture for better perception:
image

But this is obvious only for “obscurity”. And what to do if we design both parts and we do not have uncertainty? You have to think of an unknown. But which approach to choose? I came to the conclusion that any. It all depends on where we start to design the design, which is primary for us.
Let's return to the conversation about View and Controller. For example, we write a system for displaying statistical information on the screen in the form of graphs. It is the task of drawing beautiful graphs that is primary - i.e. primary performer. Further, we imagine that the statistics itself is not important for us (although, in fact, this may be completely wrong) and imagine that control is transferred from the unknown. Therefore, we apply an object approach — for the View, we describe methods for drawing graphs, pass a link to the View to the Controller, and make method calls from the controller in the right places.
Another situation - the statistics (the manager) is important for us, and how it will be presented is already a second time. Now for us, the unknown is how the statistics will be displayed. We apply event approach. We describe events and we initiate them in the right places. Now it does not matter for us who will process them and how. The module of drawing graphs in this case itself subscribes to the necessary events.
In the first case, it is more convenient to call graphics for different types of information, for example, not only statistics, but also operational data. Those. the use of different controllers for the same presentation is not difficult. In the second one, on the contrary, we can draw our statistics (and at the same time) both in the form of beautiful graphs, and in the form of a cloud of values ​​and in any other ways. In other words, it’s easy to set up multiple views for a single controller.

What for?


Somehow I implemented the interaction of different parts of the application. At that moment I had not thought so deeply about this topic and did the simplest thing that I then thought of, and then the simplest one more time. As a result, the design was mixed. The Controller and View knew about each other - somewhere the controller called view methods, somewhere View subscribed to events. It is from this that I would like to caution. Because it leads to mutual knowledge of objects about each other, and as a result:
  1. The difficulty in own understanding of the system;
  2. The difficulty of modifying classes;
  3. The difficulty in explaining the device system to a stranger.

Since the system being developed at this stage is quite simple, the first problem does not yet arise. The second one also did not make itself felt. But this does not mean that they will not be in the future. But with the arrival of a new person in the team, the third one has even brought difficulties. Because of this, I had to structure my knowledge and describe everything in uniform terms.
You can read about these and other patterns in the book “Object-Oriented Design Techniques. Design Patterns ”by E. Gamma, R. Helm, R. Johnson, J. Vlissides. For UML, see the book “UML. User Guide ”Grady Butch, James Rumbaugh, Aivar Jacobson.

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


All Articles