前言
高效,是一个很难定出标准的事情,在今天这个浮躁的HTML行业里,很难被客观的定义。多数时候,只要制作人员能在项目规定的时间内完成制作需求,并交付程序开发相关的程序应用,这个HTML前端工程师就算是一个合格的工作人员。而所谓高效,通过此环节所能看到的客观指标就是,提前多少时间量完成任务。
然而,事实又是哪般呢?任务的细节开始变化了,客户要求增加,设计不断地挑战人类(其实是前端工程师)的思维极限,整件事情就完全被打乱了。工程师会开始埋怨,客户怎么那么多要求,设计怎么不按规范做没得选择,客户确认了。加班开始了,不断的增加Hack,不断的对既有样式进行大量的覆盖、增加权重控制。任务恍恍惚惚的貌似进行下去了。
现实是残酷,新的考验又开始。样式细节和设计偏离很大,以前做的页面完全错位了,脚本错误不断,乱码,为什么页面竟然有个空白的行(BOM头)。这些都不是最挑战人类可承受能力的极限的,最最刺激的就是什么?修复这个问题你竟然要那么长的时间?这不是一个显然易见的问题吗?你们是不是在用CSS?
重构
最近公司的一个项目,其实已经完成了任务的70%吧,这个70%是表面上做出来的页面的完成度。但是我发现在某一天以后,这个任务居然进度极端异常的缓慢。我感到诧异,因为已经允许不套入Wordpress制作皮肤,而直接制作一个只包含丰富JS特效的静态站点。
进一步深入了解,发现两个前端工程师,竟然在SVN上分了两个目录在进行这个项目,而且被告知最正式的版本,是测试服务器上的。
然后我尝试了解,他们是如何进行分工合作的,虽然两人没有明确彼此进行指责,但是,彼此推诿有时候是比指责更严厉的态度。从他们对彼此的推诿,我发现,他们将各自擅长的领域(一个擅长制作页面,一个擅长整理JS)作为他们彼此对立的一个矛盾点。具体的表现如,页面的CSS制作出来以后,JS为了写特效,又把页面推翻了,制作自己引入了一些js,可是又没有和大家做一个介绍和说明。我意识到,他们之间缺乏必要的沟通,也缺乏基本的信任,也许对于中国人(看国足和乒乓球的差异)对于团队之间的信任,总是做的十分保守、有限。
我获取了代码,审视了他们的工作成果,我才真正的发现,问题已经远不止于缺乏沟通和信任的问题了,而是浮躁。大家都急于将这个任务尽快的完成,于是采用的做法就是CSS和HTML,又一个页面做一个页面的样式,JS有一个特效做一个特效。正如前言所言,诚然,这就是一个很显然的高效做法。可是这里带来了很多问题:
1、一个页面一套CSS(一套相应的id和class命名),这种做法将来的维护成本会很高,因为他忽略了整个网站可被重用,代表这个网站的通用性特征,如果要对某个特征进行修改,可能需要对同一个位置的样式进行多次重复的修改。
2、问题1往往会引伸出该问题,就是,在检查制作结果的时候,往往那些在一个页面制作达到要求的地方,为什么在第二个相似的设计结构的页面会有差异?而且甚至存在这种差异第三种、第四种版本。这个问题,如果站在设计的角度,会是一个十分严重的问题。
3、每个页面即兴的写一堆脚本,东一块西一块的,也许今天我为了项目的进度,可以认为这个特效是完成了的。但是他日真的套入到程序中,可能会让程序员碰个一鼻子灰,因为程序员也许有耐心看你的代码,但我多数时候愿意认为,他们不懂,就算他们懂,也没有义务去帮你做些什么。结果往往是,比如A君负责写JS,为此工作了3天,完成了,可是在程序开发的时候,发现不对劲,又要求A君来进行配合工作,开发进行了5天,A君陪了5天。为什么A君要在之后的5天内还要继续参与呢?那么就是他前面的3天工作没有完成了。当然,现实中,我们多数不会这样去看待这个问题,而是尽量让A君还是在后面的5天去参与进去,也不会有人去追究他前面3天究竟都做了哪些不合理的事情。而后由于后面5天人员参与数量增加,我们会希望压缩项目的开发时间云云。
重构,即时重构,就以现在既有的这些代码,其实我已经很早就放下心中的目标:一个完美代码构成的网站,我需要他们每个人都明白,怎么样能让自己更加高效准确的工作。
抽象
对于前端制作,提抽象,可能有些过分,然而我这么多年来的经验告诉自己,只有剥离了表面现象,才能洞察需求的实际。
我就不谈那些有的没有的空把式了,对于页面制作和特效定制,一个最行之有效的抽象方式就是:不要急于动手实现,而是多看设计图,找出:
1、排除设计元素差异(颜色、icon),找出页面结构之间的共同特性,其中需要着重注意以下几个特点:
* PSD是怎么做辅助线的,PSD辅助线是帮助你理解设计意图的最佳切入点,有些设计会认真的做栅格辅助线,这种PSD基本上一上手,HTML要怎么写,已经很明确。
*实际内容外宽度 <-> 内部常见布局分布(左右比例,布局模式是左中右,还是上下通栏)
*正文内容默认字体,h1 - h6的字体
*全局a标签默认样式,字体,颜色,hover style等
*form元素的样式风格
2、排除设计细节的差异(文字大小、margin、padding、height、line-height等),找出可被重用的模块(Box)模型,而这种模型,往往是以一个如下基础模型为基础的:
这种模型从功能上区分,往往有以下几种:
*列表块,列表头为标题块,列表为内容块
*正文块,正文标题为标题块,正文为内容块
*列表块还可以细分,列表内容中每一个:内容标题为标题块,描述内容为内容块(摘要等)
这种模型,可以通过以下的特征来做出区分:
*所在的页面,比如用于首页每个栏目的最新内容的列表,还是某个栏目首页的内容列表等
*出现在页面的位置,比如Ajax弹出层,DropDown Menu,侧边栏,正文栏等
*用于什么用途、表现侧重点是什么,比如博客列表页,会提供内容摘要,便于用户选择阅读,而门户型网站内容列表,会仅仅显示标题,因为信息量大,相册的列表页,总是会做得更加sexy,便于能吸引用户的眼球等。
*和页面其他部位的关联,这个需要因应各个的设计的不同,就不具体举例了。
3、排除实现的复杂度,找出特效展现的共同特性,并尽可能的想象其实现的一些细节。这部分工作是尤其重要的,因为他决定了一个页面的工作重点所在,通过对这部分重点的细节想象,你会发现如下问题:
*现在有什么,还缺什么?
*合理程度,这是用户体验基础,不合理的体验,是不会被认可使用的
*用户如何操作的,页面的元素如何变化,既能做到惊叹,而又在用户的可理解可被认知范围内,而后最大程度的缓冲系统与用户之间的惊诧点
*合理性,合理性,合理性
当你确信,在找到上述3个问题的答案后,并且做出足够的思考与预估后,我们可以开始动手制作了。
什么优先?什么其次?
优先要做的,永远都是通用性、共用性方面的东西,他会伴随在你整个制作过程中。当然,大多数公司,这种通用性存在共识,基础的CSS、基础的JS Framework。然而,对于项目和任务本身来说,你需要做更多这个项目自身的共用性的工作。其实说白了,就是上面的三个问题。
1、问题一所对应的
*body 字体,颜色,背景色,背景图,a标签的通用样式
*页面布局模式,常用宽度定义等
*h1 - h6的样式控制
*input、select样式
2、问题二所对应的
*制作多个和设计元素、设计细节无关的通用性的box模型(甚至不包括宽度的细节),仅仅描述一个模型的骨架性特征。
3、问题三对应的
*为需要实现特效的部位做足够的兼容性准备。
问题1,往往不存在太多的问题,可是大家看看自己写过的CSS,有多少句在页面里定义了字体、字体大小、颜色的,这些部分的代码也都是可以被再次抽象,而再减少对设计细节进行描述的。
问题2,是从根本上提高CSS编码质量的一条解决之道。初步了解CSS特性的人,往往会患上重度描述的症状,他们寄望于通过编写大量、甚至是成瘾性的定义样式特性,为求实现设计。确实,这种Hash结构让我们了解到了描述的快感。然而,正式因为这种重度描述,令CSS文件的修改,成为一个令人头疼的所在,密密麻麻的样式声明,不断重复又重复的特性描述,整个样式被定义的面目全非。
局部特征描述法,是一个很好的治疗的模式,通过对仅有的若干个特征进行描述,而后进行组合使用,能让我们的HTML和CSS获得解放(代码量),同时带来更多的灵活性(我不再需要对权重过度紧张等)。
比如,一个box,相关的box_title,box_content,仅仅描述其结构(如内部关联程度,如padding,margin等),宽度使用相关的样式,如具体的w500(width: 500px),或其使用用途的特征描述,如news_box(定义了具体的某几个样式)。
这种定义方式,不会破坏box、box_title、box_content相关的结构性样式特质,而通过基于news_box再次写入到box_title和box_content的样式,可以基于原来的样式的基础上,进行重用,对于专属news_box的样式,我们可以在这里重写。
而后,也许我们还有pic_box,还有blog_box,还有很多很多,我们都不需要再对box的结构进行调整,而仅仅只要对每个box的本身的特征进行局部描述。
这已经有点类型面向对象开发的方式,但是我不同意把一个标签的多个class认为是一次多重继承,他顶多只能算是一种混入(Mix in),比如Scala中的trait。
局部描述还有更多实际使用中的案例,并且,他的技巧和好处远不止于此,这里就不再累赘的进行描述了。
问题3,其实要强调的重点,是为开发JS特效预留更加宽松和自由的切入接口。JS特效的问题,会在另外的一篇日志去讲,这里就不再做过多的描述了。
现状
重构并不是要搞他个刀光剑影、暗无天日,而在于重新树立一些正确的观念苗头。我并不预想着,事实上你也不可能期待,这样一次重构,就能把每件事情做的真的和想象中那样完美无缺。
预料之外的,是人对于工作的激情和热诚。这些是无法从言谈中获取得到的,而对于写代码的人来说,也许代码最能说明问题。