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