前言
经常听到
TL或者导师要求我们在coding前需要写好技术方案,他们总是喋喋不休的强调技术方案的重要性。但是在我看来coding才是我们程序员最重要的事情呀,技术方案他们要的话就随便写点应付下就行了,毕竟正经人,谁写技术方案呀?你写吗?反正我是不想写!
上面这段话应该是大多数前端程序员的心声,只是大家敢怒不敢言。有些人抱着敷衍的态度对技术方案草草了事,觉得没有必要在这上面折腾太多时间、有些人在借着写技术方案的机会不断摸索,然后慢慢的发现了技术方案的价值。无论大家处于哪种阶段、亦或是对技术方案抱有何种态度,今天我将从前端视角出发,和大家系统的聊聊技术方案的重要性以及『前端如何写好技术方案』
为什么
在聊如何写好技术方案之前,我们先说下『为什么』前端开发需要写技术方案?
对业务需要有更全面的认知
在进入项目开发前,我们对需求的认知大多是来源于产品的 PRD (Product Requirement Document),而 PRD本身会有些局限性:
- PRD 很多时候只是描述了本期新增的需求,并没有将产品的全貌串起来
- PRD 有时候只考虑了主流程,并没有系统的分析全部流程
- PRD 的质量可能也会参差不齐
综上,无论你写不写技术方案,我们在开发前都是需要在脑海中勾勒出整个需求的全貌,并能站在系统和使用者的角度对本期需求有全面的了解和认知。但是脑海中的东西毕竟是虚的, 所以,『只有我们把脑子里对需求的理解写到文档里时,我们才能确保自己或者是团队里的其他成员是否正确的了解到需求的全貌』
技术实现受限于个人能力
这个是无可厚非的客观因素,团队里大家的技术水平总是会良莠不齐,对项目开发也会有如下几点影响:
- 技术方案的可行性
- 组件、模块设计的可拓展性、鲁棒性
- 需求、技术细节是否考虑到位
- 影响面的评估是否到位
- 是否有良好的编程风格、设计模式
正是因为在技术实现上有这么多不确定的因素,所以在才需要有技术方案
更准确的研发估时和风险把控
对于大项目而言,项目的估时和风险是一个必不可少的评估环节。很多时候我们都是用经验做事,我们『觉得』需要开发多久、我们『觉得』会有哪些风险。但是这些『觉得』本身就是个风险。如果没有技术方案的话,我们所有的结论都是缺乏理论依据的。只有把需求分析、技术设计、影响面这几点在技术方案里事无巨细的写下来之后,我们才能给出正确的研发估时,同时也能了解到这个项目可能会对哪些上下游有影响或是依赖。
如何写
团队里或多或少都会有些前端技术方案的模板,我认为万变不离其宗,无论是哪种技术方案,都应该涵盖以下几个要点
项目信息和需求背景
一个常用的项目信息大纲就是这样的,可以根据具体场景做调整(客户端开发需要有版本信息、偏安全的项目会有算法和数据方案等)
| Jira | |
|---|---|
| PRD | |
| UI设计 | |
| 后端技术方案 | |
| 测试用例方案设计 | |
| 人员 | - 产品: - UED: - 技术负责人: - 开发: - 测试: |
另外,『需求背景』也是必不可少的,你总是要知道为什么要开发这些功能、以及你开发的功能可以解决哪些问题吧?
需求分析
需求分析应该是整个技术方案里首当其冲的重点,对需求分析应该是多样化、差异化的:
- 针对业务流程的分析:用流程图
- 针对业务状态的分析:用状态机
- 针对不同系统间的调用:用系统交互图
- 针对复杂交互场景的:用用例图
无论大家在画哪种类型的图,我们都需要明确一点:你所画的分析图应该是面向所有人的,无论是产品、运营、开发还是测试,都能清晰易懂的了解你图中表达的含义 现实中,各个研发团队都有一些画图的规范要求,但是你要记住,需求分析的重点是要能清晰的描述需求的全貌,无论是图还是文字,都只是一个工具而已。
技术实现重难点
敲黑板,记重点
技术方案的重点是由项目决定的,但是技术方案的难点是由开发人员决定的
每个项目的技术重难点都是不一样的,在写技术方案前,我们需要先找到本次实现的重难点,千万不要千篇一律的罗列需求实现和代码逻辑。
- 技术方案的重点:重点是由项目决定的。比如下单业务,其重点就是要保证下单环节的稳定性。对于前端,我们就要保证下单主逻辑的稳定,防止其他组件、模块异常时影响下单链路
- 技术方案的难点:难点是由开发人员决定的。同样的一个功能实现,对于不同技术水平的研发人员,难点就是不一样的。所以技术文档里关于难点的设计需要根据自身水平量力而行
一、先有整体设计
整体设计是指对系统的顶层设计、对核心功能的通用性设计。职责划分和分层设计是它的重点内容
在找到重难点后,进入具体功能设计前,我们需要对项目有个整体的设计。但这种设计很多时候是针对于复杂的前端应用,如果只是单纯的 CRUD这样的后台页面,没必要想破脑袋寄出一个整体设计来。
整体设计很多时候是和设计模式以及架构打交道的。比如说你要做一个前端脚手架,你的整体设计就需要包括微内核模式下,不同插件的职责划分。比如说你要写一个小程序,你的整体设计就需要包括框架依赖和分层设计
我认为整体设计的重点是『职责划分和分层设计』,因为后续具体功能开发都是依赖于整体设计的,它是个指导思想。规定了哪些事情由哪些『人』来做,整体设计做的好,后续开发才能有条不紊的进行
二、组件设计
组合设计需要明确组件的边界和职责
在前端领域,必不可少的会和组件打交道,所以组件设计是技术方案里重要的一环。对于组件,我们需要关心以下几点:
- 组件的 API 设计:组件的
props以及对外的事件 - 组件的数据状态设计:对于复杂的组件,我们需要明确其内部的状态维护、流转机制
- 组件的可拓展性:好的组件应该要保证足够的稳定性和拓展性。针对多种使用场景,我们既要有灵活拓展、又要保证稳定可靠
第二和第三点大多数都是针对于一些复杂和核心的场景而言的,但是如果你的方案里涉及到组件设计,就必须包含第一点。因为从你的 props和emit定义里,就能够表达出该组件的功能定位了。
比如说我们在小程序下单环节里,经常会用到的 ButtonGroup组件,一些不好的设计就会直接体现在 props上:
export interface ButtonGropProps {
options: Array<{ label: string; value: string; checked: boolean }>;
activeIndex: number;
activeValue: string;
activeItem: string;
isFirstActive: boolean;
bizData: Record<string, object>;
}
我们把简单的 ButtonGroup设计的这么复杂且难以理解。既然有了 activeIndex为什么每个 options里都要有一个 checked,为什么还要有 activeValue``activeItem,isFirstActive是什么东西,它和 activeIndex === 0一样吗?bizData有用吗?
有时候我们根本不需要看组件的内部实现,光从 props定义上就能明确一个组件设计的是否好用
三、模块设计
模块设计本质和组件设计一致,需要描述模块的职责和数据状态
这里的模块是指 JS模块,很多时候我们会把一些业务逻辑包含在组件里。但是对于一些复杂的应用,我们可能会将 JS业务逻辑单独抽象出来。包括但不仅限于 react的 Hooks、中后台的业务逻辑函数和模型设计、Android的 Model
和组件设计类似,模块设计需要关注以下几点:
- 模块的
API设计 - 模块的职责和定位
- 复杂模块的数据流
- 模块间依赖关系图
当然,不是所有前端技术方案都需要有这一环节,大家需要根据自己的项目情况做定夺
接口设计
前端需要参与接口协议的设计
这里的接口是指前后端关于 Http TCP Socket这样的网络通信协议,关于这一环节,我们需要明确一点:前端需要参与接口字段、协议的设计,前端需要为应用的整体负责
我们应该在技术方案阶段就和后端 『一起』协商好接口协议,如果后续频繁的变动协议会降低开发时的效率
工时评估
工时评估需要依据技术方案设计做拆分估时
对工时的评估应该是有理可依的,这里的『理』就是上面的所有环节,只有你在方案设计阶段把所有重难点、组件、模块都设计好了,你才能将具体开发时间评估准确。同时到了这一步,你需要根据技术设计拆分估时,我们认为每一子项的估时尽量不要大于 8 小时
小 Tips: 在进入开阶段后,我建议大家统计下每个任务的具体开发用时,再和技术方案里的工时做个对比,通过不断的项目迭代来进一步提升开发估时的准确性
其他
根据项目的情况不同,还需要包含以下几点:
- 依赖方:如何你的项目里使用了二方 / 三方资源,需要在技术方案里明确下,以免重复引入或者引入了一些不安全的模块
- 灰度/推流计划:有些项目的开发、APP 版本开发需要有灰度推流计划,这里需要明确下灰度以及推流的批次和具体计划
- 埋点/监控:这个就不必描述了
- 风险:对项目中的风险点可以单独做阐述说明
- 名词解释:对于一些领域性较强的设计,可以在方案上方标注下通用的名词解释,同时也能做到各方的统一话术
结语
写好技术方案是个循序渐进的技术活,我们在前置把一些问题都思考明白,这样在后续开发中才能得心应手。同时写技术方案也是个长期的活,它能体现出一个人在技术和业务上精进的脚步。 最后,希望大家都能用心写好每一个技术方案,立此目标,与君共勉