The circular relationship between the "controller" and "gui"

I am writing a complex GUI in Java with many components on multiple screens working on top and interacting with a common part of the logic and model. Obviously, there are some circular dependencies between "gui" and "controller / logic": user actions in the GUI are redirected to the controller, which performs some task, and then should reflect these changes in all graphical interfaces. Something can happen in the background, which makes the controller push updates for graphical interfaces. Etc.

Now, here is my question. The listener or observer function is great for pushing updates to the GUI. Is it possible that my GUI directly depended on a specific controller class? Why, why not? There is (and always will be) only one such controller. There are about a dozen controller calls that the GUI needs to query the status and perform actions. I am not in love with the idea of โ€‹โ€‹several trivial callback interfaces that will always have only one implementation, as well as one giant callback interface for all kinds of actions.

+6
source share
3 answers

Is it possible for my GUI to depend on a particular controller class directly? Why / why not?

Not. Because loose communication is fundamental to good design. Depends on abstractions. Depending on the implementation, it is not possible to replace one implementation with another without recompiling the dependent one. The close connection of any two classes impedes future flexibility.

Yes: This is a solution. If a loose coupling definitely has no future benefit and is too expensive to justify, take it away.

But really try not to do this. The presence of a GUI depends on the controller - this is the right design decision. But it always depends on abstractions, not on realizations. Come on ... you knew that. I mean, well, if no one ever wants to turn off the controller, then you didn't get anything using the interface. In addition to calm, knowing that you wrote more accurate, less related code. And it may be easier to test.

As for the choice of how the communication between the graphical interface and the controller occurs, this happens. You can use events, but connecting them is drag and drop, and they will not cross application boundaries. But using events, you can feel that you have the loosest connection. The GUI and the controller never need to refer (abstractions) to each other, except for the initial posting of events. It may seem enjoyable. Or you could use method calls against interfaces, which might feel like a slightly tougher connection, but that is practically not the case. No matter how you do it, X needs to know about Y to communicate.

The circular dependencies between the graphical interface and the controller are in order (according to the abstractions!). There are many variations of the MVC pattern. Every time I use it, I shape it for my needs / mood. However, I try to avoid circular dependencies. I prefer to limit dependencies in one direction. Or not at all!

For example, in my current project, the controllers are aware of the views, but the views have absolutely no idea about the output of the controllers. Controllers report view events and pass data back through one state object to which the view is bound. A state class is the only thing that a view depends on. And the only thing the controller knows about the view is the interface and the type of state object. And these things are defined in the external module, so the view module can be completely removed, and the controller will still compile, and vice versa. This is a very loose clutch. Almost none at all (both sides depend on the third module).

Some people do it differently.

Reasons to Avoid Specific Dependencies

  • itโ€™s difficult to change one implementation option for another - it depends, you probably need to change it or at least recompile it
  • harder to maintain - cannot change components independently
  • more difficult to test in isolation - you need to modify and recompile dependent on swap in a mock implementation of the dependency
+6
source

I totally agree with @Charles when he says that:

A loose coupling is fundamental to good design.

the reasons are clear, and he has already explained them. I would just like to share with you a template that is slightly different from MVC, where the view and controller are the same object. It was called Model-Delegate and was used by Swing. A related article describes this deeply.

+1
source

I am not an expert in everything MVC / MVP, but here is what I do most of the time.

For simple applications where automation and testing the user interface is not a problem, I go with a graphical interface depending on the specific controller (My view actually creates an instance of the controller). Nevertheless, I am convinced that the GUI implements some presentation interface, which the controller accepts as a parameter in its constructor. Thus, I do not need to use any event or behavior similar to an observer: the controller has access to the view interface, and the view contains the controller as its member. The problem with this approach in my opinion is that it is not very friendly. Although some may argue that Model View Presenter (MVP) can be based on this approach, I donโ€™t like the fact that the controller cannot exist without instantiating the GUI. Even if you pass the controller as a parameter to the GUI object in its constructor, I tend to consider it more like a hack. Another problem with this approach is that the GUI is not really passive . I like that the logic in my interface is handled by the controller, and not vice versa. But this may just be a personal choice.

For more advanced applications, where testing becomes a big problem, I make sure that the GUI does not even know about the controller, since the controller is the one that creates the GUI object (directly or via dependency injection). Something in the line of the control controller . This approach helps a lot in testing, because I can actually make fun of the entire user interface by creating a fake GUI implementation or even reusing my controller with a different view implementation. In this case, the user interface can actually raise events that the controller will process, but only the controller will change the base model or make changes to the presentation if necessary (as opposed to presenting โ€œpullingโ€ this data from the controller to update itself).

Only my 2 cents ...

0
source

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


All Articles