谈对象 MVC 和 多端
什么是对象?
我是单身狗,我没有对象;我是C程序猿,我没有对象;我是程序猿,我只会new一个对象。
言归正传,想想从一个电商网站上买一个东西,“进入首页,搜索商品,选型购买,登录下单,支付完成”,这里面有多少个对象。在我的理解中,对象是一个物,无论是一个真实的物还是一个虚拟的物,但不会是一个动作。比如“登录”是一个动作而不是一个物,所以“登录”不应该是一个对象(类定义),而应该是用户对象里面的一个方法。所以上面那一句的流程中,明显涉及的对象有:商品、用户、购物车、订单,隐含的对象有:页面控制器。
但是,随着业务的复杂,有些动作又会衍生出一个对象,比如当“登录”接入多种第三方OAuth登录时,就会多出一个“OAuth”控制器;“搜索”功能需要比较强大时,必然要加入一个“搜索引擎”控制器。有些对象可能又需要从中拆分出对象,比如“商品”对象可能会需要拆分出“属性参数”对象等等。这个问题似乎很复杂,但也并非无迹可循,我的经验是:从最直接的名词开始规划类和对象,动词和名词内部的名词根据发展需要再进行扩充。
对象规划与职能划分
什么叫职能划分,就是一个对象做它自身的事情。说起来似乎是一个很基本的原则,但是很遗憾,我看过的不少开源PHP项目都没有这个理念。在谈这个问题之前,我想先谈谈嵌入式C语言中的对象。
有研究过C语言和单片机的会知道,C语言里面一个C文件加上相对应的H文件就相当于一个类,是不是感觉和JAVA很像,一个文件就是一个类。当然这个不仅限于这两三门语言,应该是绝大部分语言所共同遵循的规则。在单片机程序开发中,一个硬件模块应该对应一个C和H文件,如一个温度传感器就应该有一个类似于 Temp.c和Temp.h的文件,里面的应该有的方法就是 初始化传感器 和 读取温度。在这个C文件(类)里面,所拥有的函数应该只和这个模块的功能(温度)相关,你可以添加类似于以字符串、符点数、整数返回等等的读取温度方法,但不能加上例如 “符点数转字符串” , “显示温度” 这样的方法。为什么呢?“符点数转字符串”虽然是这里面的一个必须方法,但它是一个通用方法,大部分其它地方都可能会用到,如果是自己实现的话那应该放到一个公共函数文件(如 pubfunc.c)里面去。当然C库里面已经有实现好了的就不要重复造轮子了。“显示温度”看似是一个跟温度非常相关的功能,但是它跟温度传感器并没有关联。你可能会用黑白屏显示、也可能会用彩色屏显示、也可能会用语音播报,这种情况就不能把显示温度放在Temp.c里面,而是应该在业务C文件里把数据读出来运算处理,最后把数据传到对应的显示设备的C文件中去展示。
说到这里,大家可能已经隐约感觉到分层这个理念了,分层稍后再提,先看回网站中应该怎么对象划分。PHP中有函数和方法两种不同的function,函数是应该是公共的,就像前面提到的pubfunc.c一样,还有一些类也是公共的,比如分页类、加密类等,这些文件里面不应该与项目的业务逻辑有耦合关系,应该拿出来给另外一个项目也是通用的。而另一方面的项目功能模块呢,应该是职责明确的,比如用户控制器就应该有读写用户信息、登录注册等等,而不应该有订单数量这种东西。
为什么要MVC和怎么MVC
MVC即是模型-视图-控制器的意思,但实践中,我发现这种统一的MVC说法并不能适应到程序编程的各行各业。毕竟编程有 嵌入式开发、电脑软件开发、手机APP开发、网站开发、游戏开发等等,对应不同的场景应该会有略有不同的具体实现。在此我仅对我自己所使用的网站MVC模式作出介绍,有不当之处恳请提出。
如下图所示,浏览器发出的请求分成两大类,一类是页面请求(红色箭头+蓝色箭头),一类是AJAX纯数据请求(绿色箭头+蓝色箭头),服务器上的代码资源也分为两类,一个是PHP框架的(青底黑框表示),一个是自主开发的(白底蓝框表示)。
1、浏览器发出到服务器,框架通过URL路由分发请求到控制器里,当中可能会做了URL优化什么的。
2、页面请求(根据URL判断)全部转发到页面控制器中(暂时只有IndexController一个),然后调用逻辑控制器;AJAX请求则直接分发到对应的逻辑控制器,逻辑控制器通过一定的策略判断需要AJAX返回还是函数return(如可选参数)。
3、比较简单的逻辑直接在逻辑控制器中处理,直接使用“表模型”访问数据库,我这里说的“表模型”是指没有定义Model类,但是使用对象的方式去操作数据库,通常以表为操作单位,相当于ThinkPHP框架中的M()方法。
4、 对于比较复杂的逻辑,可以进一步封装在一个Model模型中,Thinkphp中称为“虚拟模型”,是指这个模型不一定会有对应的数据表,当然也可能有对 应的表。对于到达何种复杂度就封装到Model中,我经验不足暂无法下定论,因为现在为止我的项目还没有使用“虚拟模型”,也就是说我把MVC三层中把C 层拆分出了两层,而M层至今留空。至于为何这样做,稍后再分析。
5、到这里已经到达了数据库了,取回数据顺着蓝色箭头反方向返回,数据再次 来到了逻辑控制器。如果是AJAX数据请求,则直接echo输出数据或者操作结果,或者用TP内置的ajaxReturn()方法,两者有数据 header的区别,至此AJAX请求就处理结束了,剩下就交给前端JS去处理了。如果是页面请求,则把数据返回给页面控制器,注意这里是函数 return而不是打印输出。
6、页面控制器收集好各个调用到的逻辑控制器返回的数据,利用框架内置的模板引擎或者Smarty引擎,将数据赋值到页面文件中,最后渲染页面输出。
多用户端(模块)和继承
前文再续就书接上一回,上回讲到 我的项目中M层一直为空的。为什么呢?网站这一种程序,通常都会有多端的情况,就是会有 PC端、WAP端、管理端、APP端等等,这个在Thinkphp3.2中称为“模块”。我目前项目中就有 Home(PC端)、Mobile(移动端)、Admin(管理端) 三大模块了。那三大模块就写三份程序吗?显然不应该这样,因为它们之间绝大部分的逻辑是相同的,应该使用继承,而我们的项目中 Home 模块功能最基础、Mobile次之,Admin则是权限最高的模块,大部分写/修改操作只允许在Admin模块中有。所以我项目现有的结构是 Home模块中的类是基类,Mobile继承Home,Admin也继承Home,以后如果感觉有必要的话,也可能会使用一个Common模块,Home、Mobile、Admin都继承于Common。
然后这样的关键就来了,既然有那么多的模块,那么多的类,那么多的模型,如果要新增一个功能那应该写在哪里呢?我们的决定是,很长一段时间内都暂不使用Model类,避免大量继承过来并没有新增功能的“空Model”而导致找查找代码浪费时间;对于新增的功能,如果是一类全新的功能,比如折扣功能,则在几个模块中都新建一个逻辑控制器文件,继承方式同前文所提。新的方法如果可能在PC和移动端都用到的话,就写在Home的控制器里面,如果只有移动端用到的话就写在Mobile的控制器里面,如果是后台管理方面的功能则写在Admin的控制器里面。
实践证明,这样一个决策是可行的,直到现在Mobile模块里面还有半数的控制器是空的(即与PC一致没有新增功能),如果是加上了Model层的话,目测各个类里面的方法会写得很分散,各种继承错综复杂,那些方法要到各个模块下的控制器、模型各种到处找。
我是PHP程序猿,我只有一半对象(PHP的吉祥物是一只象,即半对象,而且PHP可以用或完全不用对象来写程序)
谈对象 MVC 和 多端的更多相关文章
- SignalR Self Host+MVC等多端消息推送服务(3)
一.概述 最近项目确实太忙,而且身体也有点不舒服,慢性咽炎犯了,昨晚睡觉时喘不过气来,一直没休息好,也没什么时间写博客,今天朋友问我什么时候能出web端的消息发送的文章时,我还在忙着改项目的事,趁着中 ...
- [备忘]Asp.net MVC 将服务端Model传递的对象转为客户端javascript对象
<script type="text/javascript"> var jsObject = @Html.Raw(Json.Encode(Model.Objects)) ...
- 浅谈Spring MVC知识
关于MVC框架,我相信大家都不陌生,都会说也就是模型-视图-控制器这三层的框架结构,如果你参加面试的时候考官会问:“MVC框架是什么?你说一说.”其实我们都知道这个问题还需要问的,只要你是一个开发人员 ...
- 浅谈对MVC的理解
1.MVC设计模式理解 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界 ...
- ASP.NET MVC在服务端把异步上传的图片裁剪成不同尺寸分别保存,并设置上传目录的尺寸限制
我曾经试过使用JSAjaxFileUploader插件来把文件.照片以异步的方式上传,就像"MVC文件图片ajax上传轻量级解决方案,使用客户端JSAjaxFileUploader插件01- ...
- 浅谈.net MVC
大学毕业对MVC的概念还不是很清晰,总觉得MVC是和三层一样的,是同一级别的架构.其实不然,三层架构是:BLL(业务逻辑层),DAL(数据库访问层),UI(页面显示层),而MVC仅仅是属于三层架构UI ...
- 关于JavaScript对象,你所不知道的事(一)- 先谈对象
这篇博文的主要目的是为了填坑,很久之前我发表了一篇名为关于JavaScript对象中的一切(一) - 对象属性的文章,想要谈一谈JavaScript对象,可那时只是贴了一张关于这个主题的思维导图,今天 ...
- 我要谈对象之——JavaScript面向对象(1)
任何语言里都有面向对象,除了个别的.今天,我要说的是javascript中面向对象. 什么是面向对象? 计算机中的一切算法和逻辑都是源于生活中的,对象,这个抽象的概念并不是男同胞理解的妹子哈,对象,无 ...
- 扯谈spring mvc之WebApplicationContext的继承关系
spring mvc里的root/child WebApplicationContext的继承关系 在传统的spring mvc程序里会有两个WebApplicationContext,一个是pare ...
随机推荐
- Java 利用 ByteArrayOutputStream 和 ByteArrayInputStream 避免重复读取配置文件
最近参与了github上的一个开源项目 Mycat,是一个mysql的分库分表的中间件.发现其中读取配置文件的代码,存在频繁多次重复打开,读取,关闭的问题,代码写的很初级,稍微看过一些框架源码的人,是 ...
- W3School-CSS 文本实例
CSS 文本实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 CSS 内边距 (paddi ...
- python基础(六)循环
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 循环用于重复执行一些程序块.从上一讲的选择结构,我们已经看到了如何用缩进来表示程序 ...
- js有关时间日期的操作
var myDate = new Date();var date_string = myDate.getFullYear()+""+((myDate.getMonth()+1)&l ...
- Android Native 程序逆向入门(一)—— Native 程序的启动流程
八月的太阳晒得黄黄的,谁说这世界不是黄金?小雀儿在树荫里打盹,孩子们在草地里打滚.八月的太阳晒得黄黄的,谁说这世界不是黄金?金黄的树林,金黄的草地,小雀们合奏着欢畅的清音:金黄的茅舍,金黄的麦屯,金黄 ...
- Redhat使用CentOS的Yum 网络源
Redhat 的更新包只对注册的用户生效,所以我们自己手动更改成CentOS 的更新包,CentOS几乎和redhat是一样的. 1.首先查看redhat 7.0系统本身所安装的那些yum 软件包:[ ...
- ZBrush中怎样对遮罩进行反选
通过对ZBrush的学习,我们知道了如何手动创建遮罩,手动创建遮罩相对来说是最简单有效的方法,在某些特定的使用场合会起到事半功倍的效果.创建遮罩我们可以结合Ctrl键在物体保持编辑的状态下来执行,您可 ...
- 第9章 用内核对象进行线程同步(3)_信号量(semaphore)、互斥对象(mutex)
9.5 信号量内核对象(Semaphore) (1)信号量的组成 ①计数器:该内核对象被使用的次数 ②最大资源数量:标识信号量可以控制的最大资源数量(带符号的32位) ③当前资源数量:标识当前可用资源 ...
- IT菜鸟的3(for循环+分支语句)
第三天学的东西感觉已经不是很容易能想通了,感觉头懵懵的,难道这就是是文科生的障碍吗,我不相信,坚持!相信自己一定会做好! 1:for循环!(1)循环四要素:初始条件,循环条件,循环体,状态改变for( ...
- jmeter 函数助手里的P,property的使用
1.函数助手里的 p及property的使用 ${__P(init,2)} , ${__property(init,start,200)} 可以自行定义变量名称,及变量的默认值 P 变量名为init, ...