profile for Macon_Cao at Stack Overflow, Q&A for professional and enthusiast programmers

前端开发的思考--看起来简单,做起来难

今天和网上的朋友聊到了前端开发,这位朋友真是一位大师级人物,聊聊几句话,几乎就概括了整个前端的开发工作。

我整理了一下,前端的开发工作大致包含3点:

1. 前后端的数据交互

2. DOM操作

3. 模块化设计

 

/* 因此,我也兴趣大发,想借此写点什么。首先声明一下,下面的口水话较多,仅当是一次技术闲聊,多有不严谨之处,还望大家多多指教。*/

 

这3点将我们前端杂乱无章的开发工作梳理了一遍,至少让我们的思路得到片刻清晰,是的至少是片刻清晰。让紧绷的神经得到片刻放松。

 

我个人从事开发工作有15年时间,其中大概有5年左右的Web前端经验。 至少到目前为止,还没有一个项目能够给我上面3点的那种轻松的感觉。这就像我们看房子的样板间,家具摆放得赏心悦目,但当我们真的住进去之后,才发现各种问题。

 

的确,软件开发的实际情况从来都没有过看起来如此简单过。现在就让我们进入这个样板间转转。

 

前后端的数据交互

我们至少可以通过以下库来实现前后端的数据交互

  1. AngularJs的http
  2. JQuery的ajax
  3. axios
  4. WebSocket

 对于AngularJs的http,如果你用AngularJs进行开发,一般都使用http模块。据我了解,大多数类似于angularjs的重量级js框架,都会有其自身的前后端数据交互模块。

 

对于后面3种,它们一个比一个专。

 

JQuery的ajax是通过JQuery这个轻量级的Js框架发布的。JQuery作为Js世界的老大哥,很多现有的其它js框架都会跟jQuery兼容 。而JQuery又有着很强的DOM操作能力。因此,当JQuery作为项目前端架构的一部分时,通常也会使用到JQuery的ajax来实现前后端通信。

 

axios则只专注于http的数据通信,它可以在nodejs和浏览器环境下运行。支持Promise对象。我之所以在这里提到axios,是因为我曾经使用过它,个人感觉api设计得不错。但事实上,在npmjs的网站上,类似的库还有很多。

 

DOM操作

这方面的技术,个人认为,鼻祖就是JQuery。以前我也试过ExtJs,Dojo,里面也有类似的DOM操作库。

 

DOM操作的目的是展现数据。关于数据展现,最初就是简单的表单和列表,后来随着web应用的日渐繁荣和需求的日益复杂,出现了WYSIWYG编辑器和类似于JQueryUI, Bootstrap的各种库。最终,这些UI库隐藏了DOM操作的细节,只暴露出API给开发人员调用,使得开发人员只用正确配置和调用接口,就可以实现很酷的界面效果。

 

目前,就我个人的观点,最好用的UI库是Boostrap,它不仅提供了目前常用的Js插件,还提供了一套页面布局的标准。这些都和DOM的操作紧密相关。

 

当然,EasyUI也是一个很强大的Js库,提供了丰富报表和界面插件。限于个人的见识,我相信还有不少类似于EasyUI的Js库。在这些Js库的帮助下,可以完成我们日常需要的各种复杂界面。

 

我个人认为,DOM的操作可以分为3个层次:

  1. 能够使用Js库来完成DOM的操作
  2. 能够解决Js库的冲突,Js库的样式问题和Js库的浏览器兼容性问题
  3. 能够自己写Js库来完成DOM的操作

 

模块化设计

 我对Js的模块化设计最初是从Js的闭包开始的,然后接触到了requireJs,然后是AngularJs。

 

最初的模块化设计仅仅是为了管理日趋庞大的代码,随着requireJs的出现,又出现了模块加载的能力。个人认为,无论模块化的技术怎么发展,模块化设计都离不开业务分析的结果,模块化设计是技术与业务的结合,业务分析在这个阶段必不可少。

 

如果你的项目已经使用了angularJs这样的重型框架,那么它已经为你提供了模块化设计的技术支持。如果你想自己去构建项目的模块,那还是推荐使用requireJs或者seaJs。

 

因此,从技术层面上来说,模块化设计依赖于各种Js框架/库提供的技术支持,了解并掌握类似于AngularJs, requireJs的模块定义就可以了。而从业务层面上看,则可以参考Eric Evan 的Domain Driven Design这本书。

 

个人认为,模块化的设计核心价值是让系统得到有序构建,其衡量标准是让模块之间的依赖尽量简单,其实现的方式是让模块功能范围与业务的相关范围得到最大程度的匹配。因此,模块化设计的切入点就是对先对业务模型进行设计。

 

-------------------------------------

 

目前来说,这三个方面基本阐述完毕,看上去也比较单纯。这里借用一位我们的祖先老子的一句话:道生一,一生二,二生三,三生万物。貌似什么事情,过了3就会变得复杂起来。

 

下面给出一个例子,来展示这3个方面扭在一起时的情况。

以TypeScript的Angularjs 2项目为例。

假设我们定义了serviceA用于前后端数据交互。

定义了componentA用于数据展示,即dom的操作。

定义了一个module,用于存放serviceA和componentA,用于模块化设计。

 

个人认为,用于前后端数据交互的service定义,在javascript的动态语言环境下,不过就是一个管道,甚至不用去考虑传输的数据结构是怎么样的,只用关心如何正确传入参数和正确获取输出。而真正要关心的是获取的数据如何正确绑定/显示到界面上,界面上的参数如何正确绑定到service要传入的参数上面。这时,我们会想到component的定义,或者是在界面上,会展示/编辑什么数据。从理论上讲,后台传到前台的数据应该直接绑定到界面上就结束了,数据没有理由增加或减少。唯一需要做的是在前台定义个model来绑定到界面设置的参数上,最后在查询时,将这个model传给service,但有时,这一步都可以被省略。

 

到目前为止,我们都还是理论上的推导,但在实际开发中,这些仅仅是保留在大脑里还未付诸实施的想法。当我们开始动手编码的时候,我们会遇到各种各样的问题。

  1. 子数据的处理
  2. 数据选项的展示
  3. 数据验证
  4. 根据数据A推导出数据B的数据展示

子数据的处理需求一般来至于业务的逐渐完善。当我们完成蓝图的第一个版本设计的时候,我们构建的数据模型是抽象的。抽象意味着任何一个点在实施的时候,都有可能再向更深的逻辑层次展开。

 

因此,随着业务的逐渐完善,这种抽象到更深层次的展开就不可避免。

这种情况带来的干扰是数据处理出现了分支。出现了分支,就会有分支展开和分支回归操作。这种展开和回归的操作具体到代码中,它几乎会同时影响到我们上面提到的3个方面。

 

在前后台的数据交互方面, 会影响到定义的model的结构,会添加新的结构来映射子数据。

 

在DOM的操作方面,会定义出新的区域来展示和操作子数据,而这个动作无疑会引入新的,和业务关系不大的胶水代码,而最终贡献了代码的复杂性。

 

在模块化设计方面,你需要决定是否设计出新的component来存储相关的代码,如果你决定是否定的,那么就要修改处理主干数据的component,如果你决定是肯定的,那么整个系统的结构就会受到一定程度的影响。

 

数据选项的展示无论是在“先天的”设计阶段还是在“后天的”开发阶段都会影响到开发的三个方面。

 

数据选项和数据字典不同在于,它是根据当前的上下文,动态生成的。它涉及到事件的联动处理,DOM的动态更新以及默认选项的处理。我曾经遇到过的复杂情况,事件的联动超过了4级。而这些联动处理都是胶水代码,不易于维护。

 

数据验证是一种技术挑战。数据验证的方式有:

  1. 前端的数据验证
  2. 后端的数据验证

实时的数据验证对技术要求比较高,它要求对用户的每一次键盘敲击进行数据验证,AngularJs 2的ValidatorDirective可以助我们一臂之力。对于简单的验证逻辑,我们可以直接将其放在自定义的Directive里面,对于复杂的业务逻辑,可以放在Service里面。虽然,我们已经有了清晰的思路来处理验证代码,但是对于这些验证的配置,需要不少的时间,当然也会贡献出不少代码。

 

保存数据时的数据验证发生在数据完成编辑后,将数据持久化之前的这个窗口中。随着现今类似于Angularjs前台框架的应用,很多时候,数据验证也被放在了前台。但是,按照传统的分布式系统的设计方式,数据验证会被放在后台,这样有利于业务逻辑在更大层面上的复用。

 

前端的数据验证优势在于速度快,后端的数据验证优势在于对数据的处理能力强。因此,通常情况下,我们要同时使用前后台的数据验证方式,来一起解决问题。注意,这里还有一颗地雷,就是前后台的验证逻辑同步问题。

 

但不管是前端的数据验证还是后端的数据验证,最终都需要将验证的逻辑体现在DOM上面。这使得前后端的数据交互和DOM的数据展示再一次拧在了一起。这里再一次考验架构师的真实能力,但无论怎么设计,代码的复杂性因此而再次增加。

 

根据数据A推导出数据B的数据显示通常是开发后期追加的业务需求。个人认为它是对代码结构冲击最大的方式。它在处理上创建的分支首先会影响到已经稳定的结构。由于得响应某个事件来加载数据,因此,还必须为此添加额外的胶水代码。而这段胶水代码,会影响到前后台的数据交互,会影响到DOM的数据展示和操作响应,最终可能到处都被糊上了。

 

上面这些问题仅仅是从应用的业务逻辑实现来看的,还有无数的日日夜夜处理的浏览器兼容问题,特别是使用了类似于Bootstrap这样的CSS框架后还遇到的浏览器兼容问题,这里我就不多说了。

 

以上就是个人的一些想法,写到这里,我发现这里既是结束,又是开始。既然都已经知道了这些问题的模式,那么就有对应的解决模式,容我再想想,有时间接着侃吧。

 

上面写了这么多,都没有一行代码,如需代码,请前往 https://github.com/cao5zy/restful_angularjs

 

口水话较多,限于个人的经验,漏洞百出,还望大家多多指教。

 

posted on 2017-12-15 10:49  无所畏惧,有所期待  阅读(1835)  评论(0编辑  收藏  举报