文档章节

在WEB开发中更好的使用MVC和模块化

豆浆Melon
 豆浆Melon
发布于 2014/06/05 23:11
字数 1636
阅读 311
收藏 0
点赞 0
评论 0

前些时间,有个朋友跟我说: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;
    }
}


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


© 著作权归作者所有

共有 人打赏支持
豆浆Melon

豆浆Melon

粉丝 67
博文 8
码字总数 18465
作品 1
广州
程序员
Asp.net Core介绍

ASP.NET Core is a significant redesign of ASP.NET. This topic introduces the new concepts in ASP.NET Core and explains how they help you develop modern web apps. Asp.net Core是重......

sshpp
2017/07/20
0
0
ASP.NET 5系列教程 (一):领读新特性

近期微软发布了ASP.NET 5.0,本次发布的新特性需求源于大量用户的反馈和需求,例如灵活的跨平台运行时和自主部署能力使ASP.NET应用不再受限于IIS、Cloud-ready环境配置降低了云端部署的门槛,...

葡萄城控件技术团队
2014/11/26
0
0
如何选择一款最适合你的 PHP 框架?

PHP 是世界上最流行的编程语言之一,广泛用于主要的项目中。例如,Facebook 就是利用 PHP 来创建和维护他们的内部系统;WordPress 内部基于 PHP, 作为报答它为超过26%的网站提供了技术支持。...

两味真火
2016/12/26
6K
67
ASP.NET Core: 全新的ASP.NET !

背景 最新版本的 ASP.NET 叫做 ASP.NET Core (也被称为 ASP.NET 5) 它颠覆了过去的 ASP.NET。 什么是 ASP.NET Core? ASP.NET Core 1.0 是一个开源跨平台的开发框架,用于构建基于云的现代 We...

葡萄城控件技术团队
2016/07/08
142
0
这些最热门的 PHP 框架,哪一款是你的菜?

原文出处:opensource 译文出处:开源中国—两味真火 PHP 是世界上最流行的编程语言之一,广泛用于主要的项目中。例如,Facebook 就是利用 PHP 来创建和维护他们的内部系统;WordPress 内部基...

opensource
2016/12/27
0
0
转发-基于ASP.NET MVC 4/5 Razor的模块化/插件式架构实现

基于ASP.NET MVC 4/5 Razor的模块化/插件式架构实现 概述   在日常开发中, 我们经常谈起模块化/插件化架构,这样可既可以提高开效率,又可以实现良好的扩展性,尤其对于产品化的系统有更好...

tinwai
2013/12/22
0
0
[Struts 2系列] Struts 2发展历程

MVC思想概述: 如今见到的大部分应用都是基于B/S(浏览器/服务器)架构的,其中服务器就是Web服务器。可见,Web应用是目前广泛使用的应用模式,而Struts 2是一个具有很好的使用价值的Web MVC框架...

LSantorini
2016/01/19
95
0
J2EE应用服务器--JFox

JFox 是一个开源的J2EE应用服务器,致力于提供轻量级的Java EE支撑环境,从3.0开始,JFox提供了一个支持模块化的MVC框架,以简化EJB以及Web应用的开发! 具有简单、轻量、高效、完善等特点。 ...

匿名
2009/01/10
1K
1
Javascript MVC 架构之旅

本文摘自smashingmagazine的Journey Through The JavaScript MVC Jungle部分内容,因为个人对于框架的应用总结和特点比较感兴趣,这里翻译了部分的内容,希望对于大家有帮助,如果你觉得不过...

gbin1
2012/09/11
1K
0
最好的8个Java RESTful框架

过去的每一year,涌现出越来越多的Java框架。就像JavaScript,每个人都认为他们知道一个好的框架的功能应该是怎么样的。连我的老祖母现在也使用 一个我从来没有听说过而且可能永远不会使用的...

李景枫
2016/05/03
8.6K
27

没有更多内容

加载失败,请刷新页面

加载更多

下一页

mysql 主从复制中遇到的错误!

。。。。。

万建宁
8分钟前
0
0
DUBBO 详细介绍

摘要: 主要核心部件: Remoting: 网络通信框架,实现了 sync-over-async 和 request-response 消息机制. RPC: 一个远程过程调用的抽象,支持负载均衡、容灾和集群功能 Registry: 服务目录框架...

明理萝
18分钟前
0
1
4 个快速的 Python 编译器 for 2018

简评:Python 和其他的解释型语言一样经常被吐槽性能不行,所以开发人员为了提升性能创建了不少编译器,本文则选取其中的四个做了基准测试。 Python 其实是一种相当快的语言,但它并不像编译...

极光推送
21分钟前
0
0
spring boot注册多个MQ服务器的问题

关于注册到多个MQ源的文章已经有很多了,这里记录一下声明queue的坑; 如果使用注册bean的方式声明queue,会导致声明的queue同时被注册到所有的MQ源上; //如果使用下面的声明方式,que...

placeholder
22分钟前
0
0
Java面试基础篇——第九篇:BIO,NIO,AIO的区别

现在IO模型主要分三类:BIO(同步阻塞IO),NIO(同步非阻塞IO),AIO()。 先来看看BIO。 1. BIO 服务端接受到请求后,要指派或新建一个线程去处理客户端的IO请求,直到收到断开连接的指令。这么做...

developlee的潇洒人生
27分钟前
0
0
@RequestMapping @ResponseBody 和 @RequestBody 用法与区别

1.@RequestMapping 国际惯例先介绍什么是@RequestMapping,@RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为...

特拉仔
29分钟前
1
0
基于 HTML5 结合互联网+ 的 3D 隧道

前言 目前,物资采购和人力成本是隧道业发展的两大瓶颈。比如依靠民间借贷,融资成本很高;采购价格不透明,没有增值税发票;还有项目管控和供应链管理的问题。成本在不断上升,利润在不断下...

xhload3d
31分钟前
0
0
济南小程序热度分析

原文链接:http://www.jnqianle.cn/company/2072.html

tianma3798
32分钟前
1
0
大数据软件

beats 采集 kafka spark hive es grafana zeppelin

ArlenXu
34分钟前
0
0
Mac item2常用快捷键

标签 新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 command + 左右方向键 切换全屏:command + enter 查找:command + f 分屏 水平分屏:command + d 垂直分屏:c...

说回答
38分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部