控制器和视图之间的耦合
对我来说,良好的 MVC 实现的试金石是交换视图是否容易。由于懒惰,我一直做得很糟糕,但现在我想把它做好。这是 C++ 语言,但如果我相信这种炒作,它应该同样适用于非桌面应用程序。
下面是一个示例:应用程序控制器必须在后台检查某个 URL 是否存在。它可以连接到“URL available”事件(使用 Boost Signals),如下所示:
BackgroundUrlCheckerThread(Controller & controller)
{
// ...
signalUrlAvailable.connect(
boost::bind(&Controller::urlAvailable,&controller,_1))
}
那么 Controller::urlAvailable
是什么样子的?
这是一种可能性:
void
Controller::urlAvailable(Url url)
{
if(!view->askUser("URL available, wanna download it?"))
return;
else
// Download the url in a new thread, repeat
}
对我来说,这似乎是视图和控制器的粗耦合。这种耦合使得在使用网络时无法实现视图(协程除外)。
另一种可能性:
void
Controller::urlAvailable(Url url)
{
urlAvailableSignal(url); // Now, any view interested can do what it wants
}
我偏向后者,但看起来如果我这样做,将会有:
- 400 亿个这样的信号。对于一个不平凡的应用程序来说,应用程序控制器可能会变得巨大
- 给定视图意外忽略某些信号的可能性非常大(API 可以在链接时通知您,但信号/槽是运行时)
那么您建议删除什么耦合并降低复杂性?提前致谢。
The litmus test for me for a good MVC implementation is how easy it is to swap out the view. I've always done this really badly due to being lazy but now I want to do it right. This is in C++ but it should apply equally to non-desktop applications, if I am to believe the hype.
Here is one example: the application controller has to check some URL for existence in the background. It may connect to the "URL available" event (using Boost Signals) as follows:
BackgroundUrlCheckerThread(Controller & controller)
{
// ...
signalUrlAvailable.connect(
boost::bind(&Controller::urlAvailable,&controller,_1))
}
So what does Controller::urlAvailable
look like?
Here is one possibility:
void
Controller::urlAvailable(Url url)
{
if(!view->askUser("URL available, wanna download it?"))
return;
else
// Download the url in a new thread, repeat
}
This, to me, seems like a gross coupling of the view and the controller. Such a coupling makes it impossible to implement the view when using the web (coroutines aside.)
Another possibility:
void
Controller::urlAvailable(Url url)
{
urlAvailableSignal(url); // Now, any view interested can do what it wants
}
I'm partial to the latter but it appears that if I do this there will be:
- 40 billion such signals. The application controller can get huge for a non-trivial application
- A very real possibility that a given view accidentally ignores some signals (APIs can inform you at link-time, but signals/slots are run-time)
So what do you suggest to remove coupling and also keep complexity down? Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可能会因为这样说而招致批评,但我不同意这种说法。这在纸面上看起来不错,但现实世界的示例表明,良好的 UI 是响应式和交互式的,这通常需要将视图和控制器交织在一起。尝试编写一个完全通用的控制器来处理不可预见的理论视图会给控制器和视图增加大量的代码和复杂性。根据我的经验,互连的视图/控制器效果更好 - 我将其视为“M(VC)”。
我想说,良好的 MVC 实现的试金石是如何轻松地将另一个视图/控制器对“添加”到模型中。模型的更改是否从一个视图/控制器(例如桌面操作员)传播到另一视图/控制器(例如Web 远程用户)。该模型是否足够通用以支持不同的视图/控制器范例(例如桌面 GUI、命令行、计划/批量输入、基于 Web 的 UI、Web 服务等)?
这并不是说控制器代码不能共享(例如,从公共基础派生),但您必须在控制器应处理的内容(模型的外部操作)和应处理的内容之间找到正确的界限。被视为模型行为的一部分(模型的内部转换)。查看代码同上。
我想阅读““控制器”中的内容”下的一些答案“MVC” 也会对此有所帮助。
I'll probably draw fire for saying this, but I don't agree with this statement. This looks good on paper, but real-world examples show that a good UI is responsive and interactive, which often times necessitates intertwining the view and controller. Trying to code a completely generic controller to handle unforeseen theoretical views adds a ton of code and complexity to both the controller(s) and the views. Interlinked views/controller worked better in my experience - I think of it as "M(VC)".
I would say litmus test for a good MVC implementation is how easily you can "add" another view/controller pair to a model. Are the changes to the model from one view/controller (e.g. desktop operator) propagated out to the other view/controller (e.g. web remote user). Is the model generic enough to support different view/controller paradigms (e.g. desktop GUI, command-line, scheduled/batched input, web-based UI, web service, etc.)?
This isn't to say that controller code can't be shared (e.g. derive from a common base), but you do have to find the right line between what should be handled by the controller (external manipulation of the model) and what should be considered part of the behavior of the model (internal transitions of the model). Ditto for view code.
I think reading some of the answers under "What goes into the “Controller” in “MVC” would also help with this.
您可以使用“m”模型使它们解耦,并使用(在概念上)类似命令的模式和侦听器模式来降低复杂性。
所以你的控制器可能看起来像这样:
注意:我不是 C++ 程序员,所以请原谅我错误的语法。
MVC 的整体思想是使用 M(odel) 将 C(ontrol) 与 V(iew) 解耦。该示例极其简化。更实用的一种是对不同种类的相似信号使用不同的模型。
希望这有帮助。
You keep them decoupling using the 'm' - Model and use (in concept) command-liked pattern and listener pattern to keep the complexity down.
So your controller may looks like this:
NOTE: I am not C++ programmer so forgive me for wrong grammar.
The whole idea of MVC is to use M(odel) to decoupling C(ontrol) from V(iew). The example is an extremely simplified. The more practical one is to use different model for different kind of similar signal.
Hope this helps.