整洁的业务组件架构
上一篇章,笔者针对 AI 赋能前端研发,进行了全流程的分析,建议还没看过的同学先看上一章。 点击详见
上次提到,AI 赋能的重点会围绕:从 0 ~ 1 开发业务组件这个步骤。
这个步骤的内容有点多,为了让内容更具有结构性,便于读者理解,也将会拆成一些个小节来说。
本篇咱们讨论:什么是整洁的业务组件架构,如何写出干净整洁的业务组件。
Clean Components
Clean Code —— 干净的代码。
不同的公司可能存在不同的 codding 规范,但是万变不离其宗。
简而言之:编写容易理解、修改、可维护的代码。
笔者在公司提出了 clean component
,目前已经在前端项目中落地,同时老项目的技术重构也也在推行新的 clean component
规范。
何为 clean component
?
其中最重要的一个原则就是:服务端状态和前端状态
分离。
服务端状态和前端状态
先来看一段代码,这种类型的代码大部分的前端同学可能都不陌生。
使用 mobx 或者 redux 来管理所有的数据状态,包括服务端状态(请求 api 拿到的数据状态)和前端状态(组件的 loading、visible 等)。
在任意组件中请求 api、对接联调数据,然后再将这些状态通过 inject 等方式注入到任意层级的组件中。
存在的问题:
1、前后端状态数据混合在一起,随着项目的扩大,状态将会越来越多,同时这些状态会在各种组件中被赋值及消费,导致数据的维护越来越复杂。
2、在任意的业务组件中请求接口,对接服务端数据,功能职责耦合严重,导致业务组件强依赖于服务端的接口数据、接口的任何变更会直接影响到大范围的业务组件。
优化后的方案:
规范前端页面开发的工作流:业务组件开发 -> 数据对接联调。
从组件的层级结构来看 👇
其中包含一个最基本的原则:服务端状态和前端状态分离
所有业务组件均可独立运行
业务组件中不能直接请求 api 数据,需要触发接口请求的地方通过 props 回调给到外部对接层。
这样做的好处:
功能职责单一:业务组件可独立运行,不依赖于外部数据,api 的对接层也不依赖于业务组件。
整体的数据流向十分清晰:对接层请求数据给到业务组件层,业务组件通过 props 回调触发对接层的数据变更。
高内聚、低耦合:业务组件只关心自己的业务逻辑,对接层只关心数据的请求和处理。
技术迭代维护很简单,以我公司的一个场景举例:
由于后端将所有的 restful api 迁移到了 graphql,因此前端也需要配合修改所有的 api 对接。
如果是在以前:由于服务端状态数据和前端状态数据混合在了一起
,同时在很多业务组件中都直接对接了 api
,因此我们需要找到每一个直接对接了 api 组件,然后逐个替换为 graphql,还得要保证服务端数据的变化不会影响到耦合在一起的前端状态数据
现在:由于服务端状态数据和前端状态数据分隔开来了
,所以我们不需要关心业务组件,只需要在对接层将 restful api 换成 graphql 即可。
接入 AI 十分友好
(功能职责单一,需要给到 AI 的上下文十分清晰)
那么,基于这个原则,如何从 0 ~ 1 开发一个整洁的业务组件呢?
业务组件从 0 ~ 1 的开发步骤
1、明确业务组件的代码规范
千人千面,不同的公司有不同的代码规范,甚至同一个公司的不同项目可能也有不同的规范。
但是要想一个项目具有长期的可维护性,代码规范至关重要。
如下为我司业务组件的规范示例:
- 代码结构
StorybookExample // 业务组件名称
├─ index.ts // 仅仅将组件内容暴露给外部
├─ interface.ts // 定义组件内部用到的所有类型,包括 interface、type、enum等
├─ StorybookExample.stories.tsx // 组件的storybook文档,包含组件的使用示例
├─ StorybookExample.tsx // 组件的主体逻辑,如果组件太大可以拆分为其它的文件
├─ styles.ts // 组件所有的样式资源存放在此,使用styled-components来编写
├─ helpers.ts // 如果存在一些工具函数,那放在此处
├─ StorybookExample.test.tsx // 存放业务组件的单元测试
- 通过 storybook 管理所有业务组件。
好处:1、基于 storybook 运行环境,能快速进行业务组件的开发;2、便于业务组件的统一管理维护,基于 storybook 示例文档,新人可以快速熟悉业务组件;
2、拆分业务组件
基于整个设计稿页面,按照模块的 独立性
和 可复用性
来拆分业务组件。
提示
如果作为标准的研发流程,组件拆分的颗粒度
最好参考 UI 稿中的组件拆分,比如 Figma 设计稿体系中都会存在组件
和变体(可以理解为同一个组件的不同形态)
的概念,那前端代码中的组件跟设计师的组件保持一致,这样对于后续的维护和迭代,尤其是组件的复用性会更加友好。
注意
设计稿中并不是所有的组件都归纳为业务组件
,还有很多是不带业务属性的基础组件
,只是可能在原始的基础组件库(Mui、Antd 等)中没有,需要开发人员自行开发,并归纳到基础组件库
中。
3、定义 业务组件的 props
业务组件的 props 决定了这个组件的功能,这也是正式开发代码前的第一步。
如何设计呢?
简单来看:一进一出
;
一进:组件的运行和渲染依赖什么样的外部数据
一出:组件能够给外部提供什么数据
4、根据定义好的 props 和代码规范编写代码
在开发业务组件的步骤中,这一步开发人员花的时间最多,同样也是我们 AI 赋能的重点。
下一篇,我们来初步探索 AI 生成业务组件。