写在前面
从面向过程的角度来看前端工程,就是各个过程,以及过程之间的衔接:
(面向过程视角下的)前端工程 = 过程 + 过程间的衔接
其中,过程旨在解决效率问题,而过程间衔接关注更多的是体验问题,前端工作流相关的所有工程设施都可以按这个标准来划分,要么是过程,要么是衔接
反过来从问题角度看,体验问题能够通过衔接来缓解,比如打通上下游工具/平台、写个批处理工具、搭个管理平台,效率问题则必须通过更优、更快的过程来解决,比如协作模式升级、构建速度优化
但面向过程的划分也存在一些问题,例如:
一些相似的过程横跨多个生产环节:打包工具跨开发、构建阶段,调试套件跨开发、测试阶段,迭代管理跨全流程
过程之间需要大量的衔接:一些工具需要配合使用,如脚手架与公共库、编辑器与构建工具、调试套件
过程边界不清晰,缺少层次结构:很容易产生一大堆拉拉扯扯的零散工具/平台,如性能日志导出工具、性能分析诊断工具、性能监控平台、性能数据可视化平台
既然如此,不妨换个视角观察,从面向对象的角度来看
一.前端工程中的 OO 概念
对象
对象,是对前端应用生产活动中各个实体的抽象,其中一些对象是主体(比如充当不同角色的人),另一些是客体(比如工具、平台等各种具体事物)
对象之间通过一系列交互行为来完成前端应用的开发和交付:
产品经理:从现实生活中的问题发现用户需求,并将用户需求转化成产品需求
设计师:根据产品需求设计 UI 效果和交互操作流程,以设计稿的形式输出
后端工程师:根据产品需求设计数据模型,实现数据读写,约定前后端数据协议
前端工程师:根据产品需求还原设计稿,并根据前后端数据协议实现交互功能,产出前端应用程序
测试工程师:对前端应用程序进行充分测试,保证产品需求得到了一致满足
运维工程师:将质量可靠的前端应用程序部署到生产环境
运营专员:将已上线的前端应用程序推广给用户
与面向过程的视角不同,这里更关心的是对象和对象间的交互行为,以前端开发工作为例:
面向过程视角:现在处于开发阶段,我要通过模块拆分、编码、调试等步骤来完成开发任务,接着项目进入下一阶段
面向对象视角:我是前端工程师,我需要产品经理、设计师、后端工程师提供的产品需求、设计稿和数据协议,产出前端应用程序给到测试工程师
也就是说:
(面向对象视角下的)前端工程 = 对象 + 对象间的关系及交互
其中,对象的数量关系到体验,对象数量越多,主体需要关注的东西越多,体验越差,对象依赖关系的复杂度决定了效率,对象关系越复杂,交互越多越繁琐,效率越低
接口
接口,是在前端应用生产过程中的一些抽象产物,不直接体现在最终交付物中,例如:
协议/约定
规范
这些抽象产物定义了对象间通信的消息格式,让人与人、工具与工具、工具与人都能够紧密协作
抽象类
抽象类,也是前端应用生产过程中的一些抽象产物,定义了不同对象之间的关联和交互方式,例如:
研发模式
技术方案
流程标准
工具链
与接口不同,这些“抽象类”能够约束多个对象之间的联动关系,而接口要约束的是两个对象之间的一次交互行为
二.面向对象的前端工程设计
审视前端生产活动
先将视角爬升到白云之上足够高的地方,再看前端生产活动:
现实问题(用户需求) -> 前端生产活动 -> (解决方案)前端应用程序
P.S.前端生产活动,指的是前端项目从需求到发布上线的整个生命周期
即,通过前端应用程序解决现实问题,中间的生产活动就是前端工程所关注的领域
如果把前端工程看作一个系统,其运作原理大致是这样:
一些人,通过一些交互,生成一些中间产物,最终交付前端应用程序
输入用户需求,输出前端应用程序,前端工程一直以来所要解决的问题无非两个:
效率:减少一些人、减少一些交互、规范化一些中间产物
体验:简化一些交互、减少一些中间产物
P.S.当然,质量是前提条件,就像CAP 中的 P,实属没得选。所以伤及质量的效率、体验提升不在讨论范围内
建模前端工程
首先,识别出系统中的所有主体对象:
项目经理
产品经理
设计师
前端工程师
后端工程师
测试工程师
运维工程师
运营专员
那么顶层应该是前端生产平台,定义了研发模式和流程标准,让这些角色能够协同工作:
-----------------------------------------------------
| 前端生产平台 |
-----------------------------------------------------
| 项目中心 | 研发中心 | 发布中心 | 监控中心 | 运营中心 |
-----------------------------------------------------
第二层是 5 大中心,承载前端应用程序在生命周期不同阶段的生产活动,关键类如下:
项目中心:项目、迭代及其相关资源类(需求文档、设计稿、数据协议)
研发中心:脚手架、物料池、IDE、构建工具、调试器、测试套件等类
发布中心:部署服务类
监控中心:应用数据报表、报警服务类
运营中心:用户数据报表、配置后台类
其中,以源码编辑为中心的研发工作台已经成为趋势,前端工作流相关的工具、平台与定制化端 IDE/云 IDE提供的开发环境充分融合,集中解决过程间衔接的体验问题
另一方面,传统的前端研发模式也正在发生变革,例如:
工具化/自动化设计还原:设计师直接产出可用的前端代码,而不再输出设计稿,减少了反复确认视觉效果的低效交互
基于标准组件的低代码开发模式:将中间产物规范化,脱离全套开发工具(脚手架、IDE、构建工具等)也能产出前端应用程序,同样减少了一些对象间的交互,效率有所提升
整个前端工程系统都是为了更快捷地交付前端应用程序,从这个角度来看,研发模式上的这些变革也是顺理成章的
三.抽象、封装、继承与多态
抽象
抽象的目的是增加灵活性和通用性(抵抗变化),前端工程中有 3 种常见的抽象:
从诸多同类客体对象抽象出通用模型:跨容器框架(如Rax)、跨引擎接口(如React Native JSI)、标准容器
从中间产物抽象出标准协议:跨端组件、通用 API
从对象交互活动中抽象出规范流程:研发模式、技术方案(如Lottie)
其中,抽象层的作用分为两种:
把变化的部分圈起来:抽象层以下能够灵活变化,抽象层之上对这些变化没有感知
将不变的部分固化:流程固定不变,但流程中的某些环节可替换,就像模版方法模式
封装
封装的目的是信息隐藏,就像一个柜台窗口,隔开了后厨与前厅,用来区分实现者和使用者
在前端工程中按关注点 的是平台维护者和用户,例如:
IDE:是对前端开发相关的整套工具环境的封装,包括脚手架、编辑器、调试器、依赖管理工具、构建工具等在内
构建工具:是对本地开发、测试/正式部署等环节所需的资源处理步骤的封装,包括源码编译、资源优化、源码/产物静态检查等步骤
发布服务:是对正式、测试环境下的部署、灰度发布、回滚等功能的封装,让测试工程师、产品经理无需专业的运维知识也能完成前端应用的部署和发布
封装能够有效减少顶层对象数量,将内部的依赖隐藏起来,主体对象需要关注的对象更少,不必了解内部具体交互细节也能轻松完成一些复杂工作
继承
继承的目的是复用现有对象的属性或行为,前端工程中常见的复用形式有:
工具包:将相对完整的工程能力打包成 CLI/GUI 工具或 IDE 插件包,可集成到其它工程体系中
SDK:将工程能力中可复用的部分抽离出来,允许在此基础上二次开发和扩展
其中,IDE 插件包是一种相对新的复用形式,比定制 IDE 和 GUI 客户端的成本更低,也不失为一种好的选择
多态
多态的目的是扩展,从前端工程上看,多态体现在:
面向角色的定制:比如产品经理、前端工程师对应的系统主页不同
面向场景的横向拓展:比如小程序、Web、移动端、PC 中后台等等,一个流程环节在不同场景对应各自的实现
因此,不同的角色能够在一套系统中完成各自的工作,同样的研发模式能够产出不同类型的前端应用程序
四.总结
从面向对象的角度来看,前端工程是对象和对象间的关系及交互行为:
一些人,通过一些交互,生成一些中间产物,最终交付前端应用程序
对象的数量直接关系到体验,对象间依赖关系的复杂度决定着效率。因此,要么减少主体对象需要关注的顶层对象数量,要么简化对象间的依赖关系