【51CTO独家特稿】设计模式再“高级”一点,便是所谓的“框架”了。
从事Web开发,一般都会接触到MVC框架这个概念。
M:也就是Model,直接跟网站数据库相关。
V:也就是View,是网页的模版,跟显示数据相关。
C:则是Controller,相当于网站的业务逻辑。
MVC也不仅仅是应用于网站开发,它的概念实际上植根于桌面软件,并且在手机软件开发上也有应用。
MVC本身是一个设计模式,是一个被验证过的,可以用来很好归纳、管理代码的软件开发方式。
基于这样的设计模式,提供了很多相关的类库实现,则“设计模式”升级为“框架”。
MVC的任何一个方面,扩展出去讲,都可以讲上几天几夜。
今天只讲V。
传统的ASP / PHP网站开发,V是很混乱的。
默认只有一种文件,html与业务逻辑代码混杂在同一个文件;相当难以维护。
ASP.NET相对于asp做出了很大改进,提出了code-behine的概念:默认将html的模版代码,以及c#或者vb.net的逻辑代码切分到两个不同的文件。
这样的方式算是有很大进步。
微软平台上做开发是比较苦逼的,微软掌控了整个开发平台的前进速度。
asp跟PHP在开始的时候,是相似的技术。有类似的便利,以及类似的麻烦。
微软推出了.net,推广了code-behind的模式;然后,所有的微软程序员都超着微软指定的这个方向去迈进。
asp被抛弃了,自从ASP.NET诞生之后,就不再有任何改进。
而PHP,在开源世界中,则不断的得到各式各样的改进。
各种模版引擎层出不穷;不仅可以实现code-behind这样简单的模版、业务代码分割;很多还直接引入了MVC的概念;实现了三层的分割。
而ASP.NET,则长期止步于web form的code-behind,在开源世界中的MVC方案大放光彩若干年后,才推出 ASP.NET MVC。
模版技术,最初的目的就是要把业务代码,也就是说,把获得数据的代码跟html分割。
在模版实现上,因此涌现了不少不同的设计哲学。
Python的Django框架中的模版,是一种典型。
它彻底的禁止程序员在模版中嵌入任何代码;模版中,只可以出现html;以及一些跟业务逻辑无关的控制标签,如:
- {% If XXXX %} foo {% else %} bar {% end %}
条件XXXX,必须是一个数据值,不可以是一个复杂表达式、不可以包涵函数调用等等。
模版中,也不可以声明任何新的变量,下面的做法是被禁止的:
- {% set i = 0 %}
- {% foreach item in items %}
- {% i += 1%}
- <div>
- {{ item }}
- {% if i mod 2 == 0 %}
- <hr />
- {% end %}
- </div>
- {% next %}
Django的模版,从技术上彻底禁止程序员添加任何逻辑,强迫程序员必须在controller中去写各种逻辑,以确保模版内容的纯洁干净。
所以Django的模版,一般都非常简单,有很好的移植性,并且可以让网页设计人员直接编辑。
ASP.NET则是另一种典型;虽然有了code-behind,但是它没有对前端代码,以及后端代码做任何限制。
在前端aspx页面中,可以嵌入任意的逻辑代码,而code-behind的code,为空白;这种伪“code-behind”的方式,跟原来的asp没啥区别。
ASP.NET从框架本身,并不阻止程序员去做这样的事情,实际上,它还标榜它这样的特性:方便原有的asp项目直接升级到.NET的平台上。
也有另外一种奇葩的做法,前端aspx页面保持空白,然后在code-behind的code中去拼接所有的html。这样的方式,ASP.NET框架本身也不禁止。
只要ASP.NET程序员喜欢,没有什么不可以的。
ASP.NET把对模版使用方式的选择权留给了程序员,如果程序员自律,他们可以按Django模版那样的方式去使用模版,并拥有Django一样的优点;如果程序员自律?!
在某些可以通过嵌入代码去快速处理的场景,ASP.NET的模版也保留了程序员去hack的能力。
还有一些模版技术,则是折衷的(如tornado的模版):允许嵌入单行代码,如声明变量,调用函数等等;但是不允许整块、整块的业务代码出现模版中。
上述三种模版设计哲学,各有它们的道理,以及应用场景。
需要根据具体的业务、应用场景,才能说其中哪种比较合适。
开发人员的能力也是直接相关的,如果团队中,普遍不自律;缺乏将业务、模版代码分割、以提高代码可维护性的意识,那么Django的做法是最好的,它直接禁止去滥用模版,强迫他们去使用更好的开发风格;即便在某些场景下会更麻烦。
武断的认为任何一种模版设计哲学是“最佳”的想法是极其肤浅的。
各种成熟的模版技术,一般也都会有包括以下特性:
1. 嵌入
也就是说,编写各种可以复用的小模版块,然后供多个不同地方调用;比方说,用户头像(甚至名片)的显示。
具体页面不需要重复编写这些重复的模块。
并且,这些模块需要调整时,只需要修改一个地方,便可以在所有地方生效。
2. 继承
能够编写一些基础模版,定义常见的页面结构。
具体页面继承这些基础模版,便不需要重复编写那些结构代码。
同样的,当页面结构需要调整时,也是修改一处,所有生效。
3. i18n
网页模版的国际化支持是一个模版引擎是否成熟的表现。
如果没有,当网站需要同时提供多种不同语言支持的时候,会很麻烦。
成熟的模版,都会提供内置的支持。
因为网页模版实现实在是太多了,大家功能也都差不多,那么性能,也就成为了相当重要的比较指标。
有的模版,能够“编译“,渲染起来快些。
一般可以简单认为,功能越多的模版,性能会约低。有的模版,甚至将i18n的支持变成可配置的,不需要的时候就可以关闭,以提高性能。
也有的模版认为,写 {% %} <%%> {{}} 这样的符号太麻烦了,可以直接忽略,它可以自动聪明的识别 html,以及模版控制代码。简单的说,就是以极其华丽的方式,去方面程序员少打几个字符。
还有的模版,在实现嵌入功能的时候,还可以选择所依赖的的css / js文件。
比方说,要显示用户的名片,需要引入 namecard.css;那么,可以在 namecard的模块文件中指定这个依赖,然后模版渲染的时候,自动把这个css的引用,放在html的头部。
直接在模块文件中写 namecard.css 的引用是很傻的,因为模块可以在模版中引用多次。重复引用同一个css文件是没有道理的。
种种模版功能细节,实际上,都是可以在没有模版支持的框架中去实现。
想想PHP,它本来是非常简单的,默认只能够在同一个文件中混杂逻辑与代码。
但一旦程序员有了追求,它也可以有模版实现。
模版不支持 i18n,程序员一般也是有办法在现有模版实现中添加相应的支持的。
并不复杂,关键是看程序员的态度;看程序员是否有把事情做得更好、更优雅的态度。
一般情况下,程序员选择去实现更多的模版功能的时候,必须先看看别人是怎么做的。比方说,如果完全不知道什么是gettext就去自行实现模版的 i18n 功能,是非常2B的。
绝大多数情况下,程序员面临的问题,都不是自己独有的,一定是别人已经解决过的问题。
是否有足够的见识,有足够的知识广度,了解别人的解决同样问题的做法是程序员能力的表现。
是否有快速的搜索出类似的解决方案,也是能力的表现。
1. PHP的Smarty 模版的设计哲学是什么?
2. Perl的Mason 模版的设计哲学是什么?
3. 什么是gettext?
4. 前端Javascript实现的模版中,目前最成熟的是哪个引擎?
男主角:Wuvist(新浪微博),真名翁伟,自称胖程序员一个,幸好已婚。学习.NET
本文作者:Wuvist
女主角:Katze,Wuvist的老婆,女程序员,
51CTO系列: