MVC设计 - 控制器数量应该是多少?

3

概述

我正在构建一个简单的Web应用程序,由画布和画布上的元素组成。

画布支持以下操作:加载、保存

元素支持以下操作:移动、调整大小

Web页面上的JavaScript为每个操作发送一条消息到服务器,服务器会发送相应的响应。

我的设计

enter image description here

注:Canvas对象和Element对象之间的箭头表示Canvas对象包含一系列Element对象。我没有正确的符号来表示这个图表。

示例工作流程

  1. 在画布上移动元素,生成一个element_moved消息。
  2. 前端控制器管理会话并将消息传递给具有正确画布对象的画布控制器。
  3. 画布控制器检查消息并发现它是针对画布上的元素的,然后将其传递给元素控制器。
  4. 元素控制器解析消息并直接更新相应的元素对象。

问题

这种控制器的分层排列在MVC设计中是否很常见,还是我完全没有理解重点?我已经搜索了几个小时,但没有找到任何讨论MVC设计更深入的网站,只是简单地返回一个页面视图。

我的设计背后的动机是,客户端需要与之交互的每个对象都有一个控制器,因此,如果界面发生更改(以支持新方法),则相应的控制器可以更新而不影响设计的其他部分。


这是一个非常好的问题。我认为你可能会从我的答案中得到一些东西。 - Anthony Rutledge
2个回答

1
你的情况涉及到在客户端JavaScript中为MVC组织问题时的基本问题。

第一个基本问题

1) 整个“页面”是否应该使用一个单块的Controller,其中该Controller的成员方法是处理单个Model和单个View的事件处理程序/起始点?

用正则表达式来说……

Controller{1}

Model{1}

View{1}

由于只有一个 Controller,因此在其方法必须作为输入方案的事件处理程序/侦听器时,不存在歧义Controller.moveCircle()

扮演一分钟的笨蛋,如果只有一个 Model,那么您可以简单地前往一个地方创建所有需要的数据/状态处理方法。 对吗?(hehehe) ;-) Model.calculatePosition(), Model.calculatePrice()

在最基本的客户端/Web场景中,如果只有一个 View,可能会认为只需将所有呈现逻辑放在那里即可完成工作:View.repositionCircle(x, y), View.repositionTriangle(x, y)

讨论1

为什么像这样的单片式 ControllerModelView 方案在将来可能会有问题?

我能够轻松地将个别屏幕元素及其行为转移到其他“页面”上而不带任何麻烦或额外负担吗

耦合度和内聚度

考虑耦合性。一个单块控制器是否与访问屏幕目标松散或紧密耦合?

考虑内聚性。一个单块控制器是否强烈或弱化地组合与访问单个目标相关的行为/方法?

Controller.moveCircleUp()Controller.moveTriangleUp()处理访问一个屏幕目标还是两个目标?

在这种情况下,关于单块控制器的这些广泛问题也适用于单块模型和视图。一个模型最可能由多个对象组成,用于执行和处理各种事物的数据/状态,因此通常不会引起混淆。

但是,如果它也是一个单块,则必须处理所有屏幕目标的数据/状态。即使在这样的模型中使用多个对象属性和多个方法,也可能变得混乱。

可重用性和可维护性

我在这里写的内容对于代码的可重复使用性和可维护性来说并不好。即使你不是SOLID专家,很容易理解为什么庞然大物往往会违反单一职责原则。你不应该在同一个地方更改关于圆形的内容以及更改三角形的内容。
为什么?可以这样想。你的船翻后,你和另一个船员一起漂浮在海上。你宁愿与他或她脱离关系,这样如果他失去意识,他或她也不会拖垮你。相反,你希望独立自主地游泳。
如果你们紧贴在一起,你们可能会互相碰撞或造成其他错误,如果每个人都是单独漂浮者,这种错误就不会发生。
换句话说,独立操作并相互协作比黏在一起试图完成相同任务更好。这不仅仅是当事情顺利时。这是在事情出错或者独立更可取的时候。例如,当一个人能够抓住直升机上悬挂的绳梯,而另一个人正在被鲨鱼啃咬时。
你希望能够在不同的屏幕或应用程序中重复使用应用程序元素。这就是为什么松散耦合和强内聚对面向对象编程和编程一般都是基本的原因。

(**注意:View并不仅限于HTML,即使这是最常见的结果。其他可能性包括SVG、XML、画布图形、图像格式……任何适合情况的东西。)

第二个基本问题



2)屏幕上的每个精心制作的可操作对象/元素/目标是否应该有自己的ControllerModelView

用正则表达式说……
Controller+ (one or more)

Model+      (one or more)

View+       (one or more)

讨论2

您是否想在其他页面/屏幕上使用屏幕目标/元素并带有它们的特定行为

在第一个场景中,ControllerModelView之间存在1:1:1的关系。它们是单片式的。有一个屏幕/网页。在这种设置中,您无法将一个圆形放在另一页/屏幕上而不带来三角形的逻辑!

如果目标是使代码在另一个上下文中可重用,则答案是每个形状都需要具有自包含的MVC安排。每个目标都将拥有其自己的ControllerModelView

实际上,这意味着您指定的每个屏幕元素都将知道如何接受事件输入、处理它并显示输出。某种程度上,我们回到了听起来相当基本的东西。


最后的想法

如果一个人接受以上内容为真,则形状就是活着的。 :-) 它们不依赖于上下文。操作它们不应该依赖于某个全面的JavaScript FrontController,事件处理霸主首先被触发,只是将工作委托给目标个体的Controller方法。

PHP MVC

在进入所需的Controller子类之前,服务器端PHP使用FrontController方案,因为如果您有一个应用程序的单个入口点(/index.php),则必须将HTTP请求(/contact/send)转换(路由)为Controller的实例,并从该控制器调用所需的方法:ContactController->send()

性能

这里的真正问题是在将所有JavaScript下载和加载到用户代理后,应用程序的性能如何。

回答?你拥有的元素越多,使用的内存就越多。如果每个屏幕元素至少有三(3)个文件用于其 ControllerModelView,那么十个元素可能意味着最少三十个(要下载的文件)。

当然,其他配置也是可能的,但这就是工具派上用场的地方,可以将所有内容合并和压缩。在 JavaScript 中,我宁愿每个文件开发一个对象。

希望这可以帮到你!


1
通常在MVC中,您不会有一个控制器调用另一个控制器。您指定的元素控制器实际上只是更新画布模型的业务逻辑的一部分。如果您的用例要求您独立于画布更新元素,则将有一个单独的元素控制器,调用业务逻辑以更新元素。
祝好, Ryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接