MVC架构的职责划分原则
最近负责一个项目,用了 Yii Framework 的 MVC 框架,刚开始自以为结构很稳健。
但是随着对业务逻辑理解的深入,才开始意识到问题的严重。
我错误地理解了 MVC 中的 Controller,想当然地根据以往的经验,把所有的业务逻辑都放在 Controller 的 action 中去实现。
于是,每一个 Controller 的代码都上千行,越来越臃肿。
最后,我下定决心重构代码,起源是一个对外开放 API 接口的需求。
按照现在的架构,代码基本无法复用,我需要把很多功能再重复写一遍,这实在是无法接受。
面向对象编程不仅仅是课本上的名词啊!
真正开始实践才发现,要有面向对象意识,有全局观,是多么难得的一件事情。
MVC设计原则
1、到底什么是 MVC
模型-视图-控制器(MVC)是一种设计框架(设计模式)。
MVC 的目标是将业务逻辑从用户界面的考虑中分离。
这样,开发者就可以更容易地改变每一部分而不会影响其他。
在 MVC 中,Model 代表数据和业务规则;View 包含了用户界面元素,例如文本,表单等;Controller 则管理模型和视图中的通信。
MVC 在各种编程语言中均有实现,例如 J2EE 应用开发中,
View 可能由 jsp 实现;Controller 是一个 servlet,现在一般用 Struts 实现;Model 则是由一个实体 Bean 来实现。
2、我遇到了什么问题
Yii Framework 是一个流行的 PHP 框架,它借鉴了 Ruby on Rails 的 ActiveRecord(AR) 概念。
数据库中的每一个 table 都可以用 AR 类来方便地进行增删改查操作。
它把 AR 当做 Model,并推荐放在一个名为 models 的目录下面。
于是,我在自动生成表对应的 AR 之后,便望文生义想当然地认为已经拥有了 Model 层。
其实,AR只不过是 DAO (数据访问层),并不是 Model 层。
我们的业务几乎全放在了 Controller 里:对用户提交上来的表单进行各种逻辑判断,进行计算,实例化 AR 对数据进行存储……
因为一个 Controller 中会有多个 action,每个 action 都有这样的业务处理。
最后,我发现我的 Controller 代码已经超过了 1000 行。
突然有一天,leader 说,我们这个系统要开放 API 给现有的旧系统调用,要给第三方接口。
第三方只是要给定一个参数,本系统给出个结果值而已,这其中的业务处理它是不关心的。
坏就坏在这里,Controller 已经实现了那些业务,但它是接受表单提交的,怎样能够也接受 SOAP 的 xml 文档呢?
Controller 和套套一样,应该越薄越好。
它的职责应该只是接受用户的输入,然后立刻转发给别的类来处理。
这样 Controller 只负责提供不同的接口,我们才能算是将业务逻辑分离出去,而分离出去的业务也很容易进行重用。
分离出来的这部分业务由谁来处理呢?答案应该是 Model。
3、View的职责
View部分比较明确,就是负责显示。
一切与显示界面无关的东西,都不应该出现在view里面。
因此,View 中一般不应该出现复杂的判断语句,以及复杂的运算过程。
可以有简单的循环语句、格式化语句。比如,博客首页的文字列表就是一种循环。
对于PHP的Web应用而言,HTML是View中的主要内容。
View应该从不调用Model的写方法。
也就是说,View只从Model中读取数据,但不改写Model。
所以我们说,View和Model是老死不相往来的。
而且,View中不直接访问$_GET和$_POST,应该由Controller传递给View。
此外,View一般没有任何准备数据处理的内容,如查询数据库等。
这些一般是放在Controller里面,并以变量的形式传给视图。
也就是说,视图里面要用到的数据,就是一个变量。
4、Model的职责
对于Model而言,最主要就是保存和输出信息。
比如,Post类必然有一个用于保存博客文章标题的title属性,必然有一个删除的操作,这都是Model的内容。
数据、行为、方法是Model的主要内容。
实际工作中,Model是MVC中代码量最大。
Model是逻辑最复杂的地方,因为应用的业务逻辑也要在这里表示。
注意将Model与Controller区分开。
Model是处理业务方面的逻辑,Controller只是简单的协调Model和View之间的关系。
只要是与业务有关的,就该放在Model里面。
数据校验、public常量和变量,都应该放在model层,
也就是说,有可能被重复使用的属性或方法,都应该放在model层,一次定义,到处使用。
Model不应该访问request、session以及其他环境数据,这些应该由Controller注入。
好的设计,应该是胖Model,瘦Controller。
5、Controller的职责
对于Controller,主要是响应用户请求,决定使用什么视图,需要准备什么数据用来显示。
因此,对于request的访问代码,应该放在Controller里面,比如$_GET、$_POST等。
Controller应该仅限于获取用户请求数据,不应该对数据有任何操作或预处理,这应该放在 Model 里面。
对于数据的写操作,要调用Model类的方法完成。
对于用户请求的响应,要调用视图渲染。
此外,一般不要有HTML代码等其他表现层的东西,这应该是属于View的内容。
6、启示
Yii Framework 的官方文档中有这么一段:
In a well-designed MVC application, controllers are often very thin, containing probably only a few dozen lines of code; while models are very fat, containing most of the code responsible for representing and manipulating the data.
简言之,Rich Model is Better。
以上是MVC架构的职责划分原则的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

文章讨论了PHP 5.3中引入的PHP中的晚期静态结合(LSB),从而允许静态方法的运行时分辨率调用以获得更灵活的继承。 LSB的实用应用和潜在的触摸

使用PHP的cURL库发送JSON数据在PHP开发中,经常需要与外部API进行交互,其中一种常见的方式是使用cURL库发送POST�...

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

会话劫持可以通过以下步骤实现:1.获取会话ID,2.使用会话ID,3.保持会话活跃。在PHP中防范会话劫持的方法包括:1.使用session_regenerate_id()函数重新生成会话ID,2.通过数据库存储会话数据,3.确保所有会话数据通过HTTPS传输。
