全国咨询/投诉热线:400-618-4000

前端培训之浅谈框架模式(MVC MVP MVVM)(一)

更新时间:2016年12月06日11时50分 来源:传智播客web前端培训学院 浏览次数:

前言:框架模式不是一门写代码的学问,而是一门管理与组织代码的学问。其本质是一种软件开发的模型。与设计模式不同,设计模式是在解决一类问题时总结抽象出的公共方法(工厂模式,适配器模式,单例模式,观察者模式 。。。 。。。),他们与某种具体的技术栈无关。一种框架模式往往使用了多种设计模式,切不要把他们的关系搞混。
更多信息可以看看这本《Developing Backbone Application》

一代目: 脚本式设计(无架构设计):


下面这样的代码,就是无任何设计模式的产物:
JavaScript

1
2
3
4
5
6
7
8
9
const a = document.createElement("a");
a.innerHTML = "www.google.com";
a.href = "//www.google.com";
a.style.position = "absolute";
a.style.top = 100;
a.onclick = function(){
    console.log("google");
}
 document.body.appendChild(a);
 
嗯嗯~先别吐槽,因为这种编码方式还是有他的优点的。
短短的几行代码,包含了创建,样式,绑定,插入。 balabala。。。。。
这种搞法虽有不少缺点,但麻雀虽小五脏俱全,所有功能一应俱全。早些年由于UI程序还处在一个懵懂期, 逻辑不算太复杂,代码量也不会太多。这样的搞法似乎也没有什么问题。 毕竟到达A B两点最短的距离就是直线,上述代码可以说是实现某功能的最短路径。 典型的例子就是 ASM (虽然汇编语言不是用来写UI的),他们共有的缺点是 :入口单一 功能简单 不可维护
让我们修改一下上面的逻辑:
JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function doCss(a) {
    a.style.position = "absolute";
    a.style.top = 100;
}
function doEvent(a) {
    a.onclick = function(){
        alert("google");
    }
}
function doAttribute(a){
    a.innerHTML = "www.google.com";
    a.href = "//www.google.com";
}
const a = document.createElement("a");
doCss(a);
doEvent(a);
doAttribute(a)
document.body.appendChild(a);
 
这里我们将一个功能拆分成了3个部分,即外观 事件 和属性。
函数将他们重新分离成一个个独立的逻辑块,这样一定程度上达到了分离复用的目的,比如你想修改外观,就去doCss函数里去找。。。
就像有钱人追求更多的财富,权贵追求更多权利一样。
人类总在思考同一个问题, 我们能不能做得更好。。
直到有一天。。。

二代目: 代码文件分离(CodeBehind):


对asp。net尤其是webForm,winForm模式熟悉的同学,肯定对aspx 和 aspx。cs 这2种文件非常了解。
    
aspx是视图文件,而对应的。cs文件是他的相关逻辑处理文件 事件驱动模式下,框架帮我们完成了基本的事件类型,我们要做的是在事件下完成相关业务逻辑。
在前端中,也可以找到二代目大人的影分身。。
JavaScript

1
2
3
4
5
6
7
8
<html>
<head>
    <link href="style.css" rel="stylesheet" />
</head>
<body>
    <script src="bundle.js" ></script>
</body>
</html>
 
各文件各司其职,编写的时候分离,在运行的时候合并。这样进一步降低了功能之间的耦合度。 视图看起来非常”清爽”,对应的逻辑也被分离成一个个文件, 交由相应的开发人员处理。
如果你涉猎的技术范围很广,你会发现其实二代目大人已经出现在诸多成熟的技术栈中。。。。
但是,没过多久伊甸园欢乐的笑声被下面这个需求打破。。。

为了实现他,在这里我只写伪代码了:

1
2
3
4
5
6
7
8
9
10
11
`购买苹果按钮`绑定事件如下:
1.int 苹果数变量 + 1;
2.显示苹果数控件的值 = 苹果数变量;
 
`购买梨按钮`绑定事件如下:
1.int 梨数变量 + 1;
2.显示梨数控件的值 = 梨数变量;
 
...`吃苹果`
 
...`吃梨`
 
这里比较困难的是 第2步
就是如果显示苹果数的控件是另一个程序员开发的黑盒, 如何修改其值?
于是程序员A 去找 程序员B 寻求是否存在对应的 get/set 方法。
程序员B说, “有” 字还没落地, 开发买梨的程序员C 又踹门进来了,问了同样的问题, 后来才知道 开发吃苹果功能的程序员D正在路上。。。
于是程序员B 不得不把接口的详细信息写到 wiki中, 于是 程序员CDEFGHIJKMLN 都看了wiki 懂了。
完成这件事 程序员B 写wiki 花了 10分钟, 程序员CDEFGHIJKMLN 看wiki每人花 1分钟,一共团队成本 20分钟。
于是 wiki中这个 get/set 接口函数出现在了每一个被绑定的函数里。一共4个button 出现4次
ps: 这个get/set接口本质上就是一个view刷新接口
事情仍在在酝酿:
产品大爷发话了,要改成下面这样:

多了一个求和。
于是伪代码变成了这样:

1
2
3
4
5
`购买苹果按钮`绑定事件如下:
1.int 苹果数变量 + 1;
2.int 总和变量 = 苹果数变量 + 梨数变量;
2.显示苹果数控件的值 = 苹果数变量;
3.显示总和控件的值 = 总和变量;

这次 程序员B为了人身安全,提前把 get/set 接口发布到了 wiki上。。
于是 总和控件的值 = 总和变量 这行代码出现了 4次。
产品存在的意义,就是将程序狗虐到极致:
于是需求改成了这样:

只是删了一行。
于是 4个函数中所有相关代码都被删除。。。 共影响 4行代码。。
段子讲完了,其核心问题在于,按照事件进行的业务模块划分,有时候是不合理的,事件是用户行为的入口,但不是程序逻辑的入口。 一个button的click就可能横跨N个领域, 需要N个人来进行协作, 这部分逻辑到最后还是会耦合在一起,通过各种函数封装进行解耦,无疑是扬汤止沸,而我们需要的是釜底抽薪
(第一节结束)

本文版权归传智播客web前端开发学院所有,欢迎转载,转载请注明作者出处,谢谢!
作者:传智播客web前端培训学院;
首发:http://www.itcast.cn/web/

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

uids

北京校区

    14天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    8天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    0天免费试学

    基础班入门课程限时免费

    申请试学名额

    12天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    10天免费试学

    基础班入门课程限时免费

    申请试学名额