写在最前面

从面向过程的角度来看前端工程,就是各个过程,以及过程之间的衔接:
(面向过程视角下的)前端工程 = 过程 + 过程间的衔接
其中,过程旨在解决效率问题,而过程衔接关注更多的是体验问题,前端工作流相关的所有工程设施都可以按照这个标准划分,要么是过程要么是衔接

反过来从问题角度看,体验问题能够通过衔接来缓解,比如打通上下游工具/平台、写个批处理工具、搭建个管理平台,效率问题则必须通过更优、更快的过程来解决,比如协作模式升级、构建速度优化,但面向过程的划分也存在一些问题,例如:

  • 一些想的过程横跨多个生产环节;打包工具跨开发、构建阶段、调试套件跨开发、测试阶段,迭代管理跨全流程
  • 过程之间需要大量的衔接:一些工具需要配合使用,如脚手架与公共库、编辑器与构建工具、调试套件
  • 过程边界不清晰,缺少层次结构:很容易产生一大堆拉拉扯扯的零散的工具/平台,如性能日志导出工具、性能分析诊断工具、性能监控平台、性能工具可视化平台

既然如此,不妨换个视角观察,从面向对象的角度来看

一.前端工程中的OO概念

对象

对象,是对前端应用生产活动中各个实体的抽象,其中一些对象是主体(比如充当不同角色的人),另外一些是客体(比如工具、平台等各种具体事物)

对象之间通过一系列交互行为来完成前端应用的开发和交付:**

  1. 产品经理:从现实生活中的问题i发现用户需求,并将用户需求转化成产品需求
  2. 设计师:根据产品需求设计UI效果和交互操作流程,以设计稿的形式输出
  3. 后端工程师:根据产品需求设计数据模型,实现数据读写,约定前后端数据协议
  4. 前端工程师:根据产品需求还原设计稿,并根据前后端数据协议实现交互功能,产出前端应用程序
  5. 测试工程师:对前端应用程序及逆行充分测试,保证产品需求得到了一致的满足
  6. 运维工程师:将质量可靠的前端应用程序部署到生产环境
  7. 运营专员:将已上线的前端应用程序推广给用户

与面向过程的视角不同,这里更关心的是对象和对象间的交互行为,以前端开发工作为例:

  • 面向过程视角:现在处于开发阶段,我要通过模块拆分、编码、调试等步骤来完成开发任务,接着项目进入下一阶段
  • 面向对象视角:我是前端工程师,我需要产品经理、设计师、后端工程师提供的产品需求
  • 设计稿和数据协议,产出前端应用程序给到测试工程师

也就是说:
(面向对象视角下的)前端工程 = 对象 + 对象的关系及交互
其中,对象的数量关系到体验,对象数量越多,主体需要关注的东西越多,体验越差,对象依赖关系的复杂度决定了效率,都西昂关系越复杂,交互越繁琐,效率越低

接口

接口,是在前端应用生产过程中的一些抽象产物,不直接体现在最终交付物中,例如:

  • 协议/约定
  • 规范

这些抽象产物定义了对象间通信的的消息格式,让人与人、工具与工具、工具与人都能够紧密协作

抽象类

抽象类,也是前端应用生产过程中的一些抽象产物,定义了不同对象之间的关联和交互方式,例如:

  • 研发模式
  • 技术方案
  • 流程标准
  • 工具链

与接口不同,这些”抽象类”能够约束多个对象之间的联动关系,而接口要约束的是两个对象之间的一次交互行为

二.面向对象的前端工程设计

审视前端生产环境

先将视角爬升到白云之上足够高的地方,再看其阿奴但生产活动:

现实问题(用户需求) -> 前端生产活动 -> (解决方案)前端应用程序

P.S.前端生产活动,指的是前端项目从需求到发布线上的一个生命周期
即,通过前端应用程序解决现实问题,中间的生产活动就是前端工程所关注的领域
如果把前端工程看作一个系统其运作原理大致是这样:
一些人,通过一些交互,生成一些中间产物,最终交付前端应用程序
输入用户需求,输出前端应用程序,前端工程一直要解决的问题无非两个:

  • 效率:减少一些人、减少一些交互、规划一些中间产物
  • 体验:简化一些交互,减少一些中间产物

P.S.当然质量是前提条件,就像CAP中的P,实属没得选。所以伤及质量的效率、体验提升不在讨论范围内

建模前端工程

首先,识别出系统中的所有主题对象:

  • 项目经理
  • 产品经理
  • 设计师
  • 前端工程师
  • 后端工程师
  • 测试工程师
  • 运维工程师
  • 运营专员

那么顶层应该是前端生产平台,定义了研发模式和流程标准,让这些角色能够协同工作

前端生产平台
项目中心 研发中心 发布中心 监控中心 运营中心

第二层是五大中心,承载前端应用程序在生命周期不同阶段的生产活动,关键类如下:

  • 项目中心:项目、迭代及相关资源类(需求文档、设计稿、数据协议)
  • 研发中心:脚手架、物料池、IDE、构建工具、调试器、测试套件等
  • 发布中心:部署服务类
  • 监控中心:应用数据报表、报警服务类
  • 用户数据报表、配置后台类

其中,以源代码编辑为中心的研发工作台已成为趋势,前端工作流相关的工具、平台与定制化IDE/云IDE提供的开发环境充分融合,集中解决过程间衔接的体验问题

另一方面,传统的前端研发模式也正在发生变革,例如:

  • 工具化/自动化设计还原:设计是直接产出可用的前端代码,而不再输出设计稿,减少了反复确认视觉效果的低效交互
  • 基于标准逐渐的低代码开发模式:将中间产物规范化,脱离全套开发工具(脚手架、IDE、构建工具等)也能产出前端应用程序,同样减少了一些对象的交互,效率有所提升

整个前端工程系统都是为了更快捷的交付前端应用程序,从这个角度看,研发模式上的这些变革也是顺理成章的

三.抽象、封装、继承与多态

抽象

抽象的目的是增加灵活性和通用性(抵抗变化),前端工程中有三种常见的抽象:

  • 从诸多同类客体对象抽象出通用模型:跨容器框架(如Rax)、跨引擎接口(如React Native JSI)、标准容器
  • 从中间产物抽象出标准协议:跨端组件、通用API
  • 从对象交互活动中抽象出规范流程:研发模式、技术方案

其中抽象层的作用分两种:

  • 把变化的部分圈起来:抽象层以下能够灵活变化,抽象层之上对这些变化没有感知
  • 将不变的部分固化:流程固定不变,但流程中的某些环节可替换,就像模板方法方式

封装

封装的目的是信息隐藏,就像一个柜台窗口,隔开了后厨与前厅,用来区分实现者和使用者,在前端工作中按关注点的是平台维护者和用户,例如:

  • IDE:是对前端开发相关整套工具环境的封装,包括脚手架、编辑器、调试器、依赖管理工具、构建工具等在内
  • 构建工具:是对本地开发、测试/正式部署等环节所需资源处理步骤的封装,包括源码编译、资源优化、源码/产物静态检查等步骤
  • 发布服务:是对正式测试环境下的部署,灰度发布、回滚等功能的封装,让测试工程师、产品经理无需专业的运维知识也能完成前端应用的部署和发布

封装能有效减少顶层对象数量,将内部的以来隐藏起来,主体对象需要关注的对象更少,不必了解内部具体交互细节也能轻松完成一些复杂工作

继承

继承的目的是服用现有对象的属性或行为,前端工程中常见的复用形式有:

  • 工具包:将相对完整的工程能力打包成CLI/GUI工具或IDE插件包,可集成到其他工程体系中
  • SDK:将工程能力中可复用的部分抽离出来,允许在此基础上二次开发和扩展

其中,IDE插件包是一种相对新的复用形式,比如定制IDE和GUI客户端的成本更低,也不失为一种好的选择

多态

多态的目的是扩展,从前端工程上看,多态体现在:

  • 面向角色的定制:比如产品经理、前端工程师对应的系统主页不同
  • 面向场景的横向扩展:比如小程序、Web、移动端、PC后台等等,一个流程环节在不同场景对应各自的实现

因此,不同角色能能够在一套系统中完成各自的工作,同样的研发模式能够产生出不同类型的前端应用工程

四.总结


从面向对象的角度来看,前端工程是对象和对象间的关系及交互行为:
一些人,通过一些交互,生成一些中间产物,最终交付前端应用程序
对象的数量直接关系到体验,对象间依赖关系的复杂度决定着效率。因此,要么减少主体对象需要关注的顶层对象数量,要么简化对象间的以来关系