维基百科这样描述单一职责原则:
单一职责原则指出每个对象都应该有单一职责,并且该职责应该完全由类封装。它的所有服务都应与该责任密切相关。
MVC 中对控制器的传统使用似乎导致程序员违反了这一原则。拿一个简单的留言簿控制器并查看。控制器可能有两种方法/动作:1) Index() 和 2) Submit()。Index() 显示表单。Submit() 处理它。这两种方法是否代表两种不同的职责?如果是这样,单一职责如何发挥作用?
维基百科这样描述单一职责原则:
单一职责原则指出每个对象都应该有单一职责,并且该职责应该完全由类封装。它的所有服务都应与该责任密切相关。
MVC 中对控制器的传统使用似乎导致程序员违反了这一原则。拿一个简单的留言簿控制器并查看。控制器可能有两种方法/动作:1) Index() 和 2) Submit()。Index() 显示表单。Submit() 处理它。这两种方法是否代表两种不同的职责?如果是这样,单一职责如何发挥作用?
是的,它确实。
如果您想遵循 SRP,您可以将 Controller 分解为 Dispatcher 和 Actions;Dispatcher 将控制分派给它的动作,并且在编译时(C++ 模板)或运行时(Java XML 等),您将组合 Dispatchers 和 Actions。
为什么我们不经常看到这种情况?因为控制器通常是“ad hoc”实现,叶级的具体类没有被泛化并且不应该被子类化。在这里,该类更多地用于方便地对代码进行分组,这些操作几乎可以肯定是非公共的(可能是私有的,可能是受保护的),“仅仅是”内部实现细节。
如何决定派发到哪个动作、可能动作的数量和多样性的选择很高,并且调度和动作是紧密耦合的。所以在实践中,将代码放在一个地方通常更容易。
不,它没有。
MVC 模式或其变体没有任何内在的东西会导致违反单一职责原则。控制器的实现是否违反 SRP 取决于封装的行为是否有多个改变的理由(就像任何其他类一样),而不是因为对模式的任何预设规定使用。
您提出的示例是基于数据应用程序的基本表单的子集,其中控制器仅为给定模型提供 CRUD 操作。CRUD 操作本质上是相当有凝聚力的,所以这通常不构成违反 SRP。当方法代表跨域的不同行为交互时,单个控制器上的多个方法开始变得可疑。
也就是说,即使有人认为 CRUD 代表四个独立的非内聚关注点,MVC 模式也没有固有的东西会迫使您在同一个控制器中促进这些操作中的每一个。
有关 MVC 模式的一些历史以及对其在 Web 开发中的应用的一些讨论,请查看交互式应用程序架构模式。