博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在WEB开发中更好的使用MVC和模块化
阅读量:6220 次
发布时间:2019-06-21

本文共 4491 字,大约阅读时间需要 14 分钟。

hot3.png

前些时间,有个朋友跟我说:MVC把程序都限制得太死了,我无法在里面使用其它设计模式。这让我注意起来,MVC这种结构只有三层,看起来无论在C或者M都无法满足灵活和细化的程序设计。

然而很多人都不知道MVC只是一个框架模式,从宏观上控制框架大体的运作流程。那么回到刚才的问题,如果纠结于MVC本身,肯定不能从更细的粒度去思考具体业务逻辑的设计实现。

更严重的是:这样大大的降低了程序的可重用性

所以我们需要把这些代码从MVC中分离出来,举一个例子:

class Controller {        public function regist() {        $username = strtolower( trim( $_POST['username'] ) );        $password = trim( $_POST['password'] );        $email = $_POST['email'];        if( ! preg_match( '/^[a-zA-Z]/', $username ) ) {            exit( '帐号只能由英文字母组成' );        }        if( strlen( $password ) < 5 ) {            exit( '密码长度最少为5个字符' );        }        if( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {            exit( '请填写正确的邮箱' );        }        // 调用模型        $memberModel = new modelMember();        $uid = $memberModel->insert( array(            'username' => $username,            'password' => sha1( $password ),            'email' => $email,        ) );        if( $uid > 0 ) {            echo '注册成功';        } else {            echo '注册失败';        }        exit;    }}

这是一个控制器,里面regist是一个注册新用户的方法,看上去没什么问题,整体流程也走得通。但试想一下:有一天,BOSS需要你在手机页面或者本地应用中添加相同的注册功能,使用的是原来的用户体系,但是接口要求返回的视图(数据)不一样,因为本地应用可能需要一个JSON或者是XML,这时候该怎么办?

你可能会在原来的regist方法里加一个表示类型的参数'type'加以区分,或者把regist方法里的代码拷贝一份到新的控制器,再改一下视图输出(现实中看过很多这么干的)。但这样造成了不同业务逻辑的混乱和代码的重复,而且这只是举了一个方法,一般情况下会有更多,login、logout等等。所以它们不是好的解决方案。

稍微注意一下代码分离的人,这些问题都很容易解决:将regist和其它方法封装到一个独立的类里,由控制器调用:

class Controller {        public function regist() {        $uid = Member::regist( trim( $_POST['username'] ), trim( $_POST['password'] ), $_POST['email'] );        switch( $uid ) {            case -1:                $result = '帐号只能由英文字母组成';                break;            case -2:                $result = '密码长度最少为5个字符';                break;            case -3:                $result = '请填写正确的邮箱';                break;            case 0:                $result = '系统异常';                break;            default:                $result = '注册成功';                break;        }        echo $result;        exit;    }}// 会员接口class Member {        /**     * 注册一个新用户     *      * @param string $username     * @param string $password     * @param string $email     * @return int $uid -1 帐号只能由英文字母组成; -2 密码长度最少为5个字符; -3 请填写正确的邮箱; 0 系统异常; <= 1 新用户ID     */    static public function regist( $username, $password, $email ) {        if( ! preg_match( '/^[a-zA-Z]/', $username ) ) {            -1;        }        if( strlen( $password ) < 5 ) {            -2;        }        if( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {            -3;        }        // 调用模型        $memberModel = new modelMember();        $uid = $memberModel->insert( array(            'username' => strtolower( $username ),            'password' => sha1( $password ),            'email' => $email,        ) );        return $uid;    }        static public function login() {        //...    }        static public function logout() {        //...    }}

OK,现在regist和其它方法都分离了出来,并整合到Member类中。现在你可以在任何控制器里使用,输出不同的数据视图,也可以 思考如何去使用设计模式并重构它,根本不需要顾及到MVC,甚至以后迁移到其它架构中也很容易。

操作起来也很简单,只要封装一下。遗憾的是我见过国内大部分MVC架构的程序都是把逻辑直接写到控制器方法里的,最起码的接口封装都没有,二次开发起来很困难。

再看市面上部分MVC框架,它们只能在控制器里使用db(数据库)或者模型,我觉得也是不合理的,那样大大限制了程序的可分离性。

模块化

由刚才的问题想到模块化,目前国内的WEB系统大部分开始走模块化路线,而模块化一般只限于把不同的MVC归类,放到一个文件夹里,我觉得这样很形式,最多只起到代码层面分离的作用,没有一点重用性可言。稍微好的模块化也应该与MVC分离,并提供一系列接口。

下面是我目前开发的一个小项目的模块目录结构

这里有三个模块,Admin-管理员、Content-内容、Member-用户。每个模块都使用MVC实现,并都有一个Lib文件夹,Lib文件夹存放当前模块的通用接口,就像之前说的Member类一样,控制器去调用它们。你注意到最下方有一个ModuleApi,它是一个工厂类,负责生产每个模块下的接口实例。

现在有一个需求,Admin模块要使用到Member模块的用户体系。注册一个管理员实际是注册一个Member用户,并将其放到管理员组里,然而'注册'这个逻辑在Member模块中早已经实现。

为了不重复编码相同的代码,ModuleApi的作用就显得很重要,在Admin模块中通过ModuleApi,取得Member模块中包含注册方法的对象实例(这里是Member/Lib/UserAccess)并调用:

// admin模块中的控制器class AdminController {        public function regist() {        // 取得member模块的注册接口        $userAccess = ModuleApi::member( 'userAccess' );        $uid = $userAccess->regist( trim( $_POST['username'] ), trim( $_POST['password'] ), $_POST['email'] );        switch( $uid ) {            case -1:                $result = '帐号只能由英文字母组成';                break;            case -2:                $result = '密码长度最少为5个字符';                break;            case -3:                $result = '请填写正确的邮箱';                break;            case 0:                $result = '系统异常';                break;            default:                $result = '注册成功';                break;        }        echo $result;        exit;    }}

基本就是这样,其实只要养成封装的习惯,很多问题很容易解决,甚至不会发生。

转载于:https://my.oschina.net/melonol/blog/274017

你可能感兴趣的文章
js fuction函数内return一个内部函数详解
查看>>
ti processor sdk linux am335x evm /bin/setup-tftp.sh hacking
查看>>
Apache+tomcat的整合
查看>>
本人编写的近乎全部《仙境传说》(RO)服务器工具下载 包含源代码
查看>>
MySQL中的空间扩展
查看>>
医疗保健研究报告-生物大数据的时代(附下载)
查看>>
17.3. SNMP 命令
查看>>
快看Sample代码,速学Swift语言(1)-语法速览
查看>>
算法之【牛顿迭代法】
查看>>
Golang入门教程(二)Ubuntu16.04下安装golang(实例:Golang 定时任务管理器)
查看>>
Maven - 项目结构
查看>>
大话系统之权限控制
查看>>
如何在CRM系统中集成ActiveReports最终报表设计器
查看>>
10.2.0.4 11.1.0.7UNDO可能异常增大的BUG
查看>>
大学里的几件趣事(一)
查看>>
C#流水号生成汇总(四)
查看>>
Linux 内存使用方法详细解析
查看>>
工程师文化,是一种内心的欲望与恐惧的表达。对创造的欲望,对世界的恐惧。因为欲望而创造,因为恐惧而改造。创造世界,改造世界。(转)...
查看>>
直击游戏行业音视频应用——12月2日livevideostack Meet成都沙龙
查看>>
[20170703]ora-12516 ora-12514 rac.txt
查看>>