forked from 77media/video-flow
136 lines
7.0 KiB
Markdown
136 lines
7.0 KiB
Markdown
|
||
## 🎯 各层职责与内容
|
||
|
||
### 1. Component (UI层)
|
||
**职责**:纯展示逻辑,用户交互处理
|
||
**内容**:
|
||
- React组件(Modal、Form、Button等)
|
||
- 样式和布局逻辑
|
||
- 用户交互事件绑定
|
||
- 越是可复用组件,越要小心定义,越要简单,宁可页面中的组件使用多做点,也要组件少做点,因为复用越多,它就可能发生的变化越多,除非你很确定它的变化不会更多了。
|
||
**设计原则**:
|
||
- 不包含业务逻辑
|
||
- 不直接操作状态
|
||
|
||
|
||
### 2. Hook (状态管理层)
|
||
**职责**:状态管理、副作用处理、业务逻辑组合
|
||
**内容**:
|
||
- 状态管理Hook(useState、useReducer等)
|
||
- 副作用处理(useEffect、useCallback等)
|
||
- 业务逻辑组合(调用多个UseCase)
|
||
- 提供统一的数据接口给组件
|
||
|
||
**设计原则**:
|
||
- 协调全局状态和本地状态
|
||
- 处理异步操作和副作用
|
||
- 组合封装UseCase的调用,让react的方便性和hook思想体现出来
|
||
- 提供响应式的数据接口
|
||
|
||
### 3. UseCase (业务逻辑层)
|
||
**职责**:核心业务规则、业务流程编排、领域逻辑验证,它里面的流程,应该一眼看过去,瞬间就知道这个用例中包含的业务是干啥的,里面应该是去调用一个个service,并且有注释说明,它是会最经常发生更改的,所以它要足够简单,要足够注释。
|
||
```ts
|
||
class DemoUseCase {
|
||
constructor(private readonly aService: AService, private readonly bService: BService,cStore:Store) {}
|
||
async execute(href:string,storedate:any) {
|
||
// 获取a数据
|
||
const aData = await this.aService.getA(href);
|
||
// 处理b请求
|
||
const b = await this.bService.getB(aData);
|
||
// 更新cStore
|
||
this.cStore.update({
|
||
...storedate,
|
||
b,
|
||
});
|
||
|
||
return b;
|
||
}
|
||
}
|
||
```
|
||
**内容**:
|
||
- 业务用例类(ImageStoryUseCase、ScriptGenerationUseCase等)
|
||
- 完整的业务流程方法
|
||
- 业务规则验证逻辑
|
||
- 业务实体构建和管理
|
||
|
||
**设计原则**:
|
||
- 包含完整的业务流程
|
||
- 执行业务规则验证
|
||
- 协调多个Service的调用
|
||
- 返回领域实体,而不是原始数据
|
||
- 无状态,方法调用间不依赖实例状态
|
||
- 无关任何react的东西,纯粹的TS代码
|
||
|
||
### 4. Service (外部服务层)
|
||
**职责**:外部服务集成、技术实现细节、基础设施,它应该是一堆的服务函数,纯函数,输入到输出,没有外部的闭包依赖。不要觉得有时候可以从其它地方直接依赖,就不用参数来接收,它要干净,要是纯函数,要能通过参数判断其全部所需,所以要用接收参数的方式
|
||
**内容**:
|
||
- 技术实现细节(图片处理、网络请求等)
|
||
- 错误处理和重试逻辑
|
||
- 可以被多个UseCase复用的服务
|
||
|
||
**设计原则**:
|
||
- 专注于技术实现细节
|
||
- 处理外部API调用
|
||
- 提供统一的错误处理
|
||
- 实现接口隔离原则
|
||
- 无关任何react的东西,纯粹的TS代码
|
||
|
||
### 5. Repository (数据访问层)
|
||
使用ApiFox去对接好后端的接口文档,然后MCP接入cursor,从而直接生成接口请求函数以及类型,相对于没有这个东西,cursor帮你写的代码将是天差地别的,能提高你大约20%的开发效率。当然这要协同后端好好写接口参数和响应的内容。
|
||
|
||
## 📊 状态管理策略
|
||
|
||
**状态分类**:
|
||
- **功能业务模块状态** → 微型Store,用不同模块功能去拆Store 而非页面,记住要用单例模式处理
|
||
- **纯UI变化状态** → 组件useState,跟业务没有任何关系,只是UI变化所用的状态。
|
||
- **业务流程状态** → UseCase私有状态,从这里开始就是跟react任何关系都没有了,纯TS代码去写的逻辑,状态也是纯粹的业务状态,一定要在这里忘记react的存在。
|
||
- **全局状态** → 全局Store,跨模块共享,比如用户信息、主题色、语言等。
|
||
|
||
## 数据流向
|
||
|
||
**状态流转过程**:
|
||
用户操作 → 组件本地状态 → Store Hook协调 → UseCase业务逻辑 → Store 状态更新 → 组件重新渲染
|
||
|
||
## 设计模式应用
|
||
|
||
**核心模式**:
|
||
1. **依赖注入**:UseCase通过构造函数注入Service依赖,最好的简化useCase的方式。
|
||
2. **策略模式**:要弄清楚,什么是策略,有了这个意识,我们这个项目,很多地方可以用到策略模式,可扩展性将提高一大截
|
||
4. **观察者模式**:我们的项目需要跨页面,跨组件的复杂通讯,采用观察者模式是非常合适的,比如chatBox.如果搞不明白这个模式,那就事件总线,这个东西更容易理解,也能实现相同功能。
|
||
|
||
## 🧪 测试策略
|
||
|
||
**分层测试**:
|
||
- **Component层**:组件渲染和交互测试(目前的前端测试框架,测试这个纯浪费时间,不要为这个层做单元测试)
|
||
- **Hook层**:状态管理和副作用测试(react的hook系统限制太大,不要为这个层做单元测试)
|
||
- **UseCase层**:业务逻辑和规则验证测试(这个层需要做单元测试,最适合的地方就是这个)
|
||
- **Service层**:外部服务集成测试(这个层不需要做单元测试,,因为用例层依赖这个层,如果用例层完备,这个就直接连带测试)
|
||
- **Repository层**:数据访问逻辑测试(对于前端来说,就是接口请求的一堆封装,用apifox 的mcp生成接口请求函数就好,不用再封装和创建更复杂内容。若测试这个,直接apifox)
|
||
-
|
||
>谦卑对象模式(Humble Object Pattern)是一种设计模式,用于将复杂逻辑从难以测试的组件中分离出来,以提高代码的可测试性和可维护性。其核心思想是将与用户界面、外部系统或复杂依赖相关的代码(难以测试的部分)剥离,保留一个“谦卑”的对象,只包含简单逻辑或直接调用,而将主要业务逻辑放入易于测试的独立对象中。
|
||
|
||
## 错误处理机制
|
||
|
||
**错误分类**:
|
||
- **领域错误**:业务规则验证失败(StoryValidationError)
|
||
- **基础设施错误**:外部服务调用失败(ImageUploadError)
|
||
- **应用错误**:应用逻辑错误(UseCaseError)
|
||
|
||
**错误处理流程**:
|
||
1. Service层捕获原始错误并转换为应用错误
|
||
2. UseCase层抛出领域错误
|
||
3. Hook层将用例的错误,变成错误提示,展示给用户
|
||
4. 组件层显示错误信息(组件层不需要做错误处理,因为组件层是纯展示层,不需要处理错误)
|
||
|
||
## 性能优化策略
|
||
|
||
**状态优化**:
|
||
- 使用useMemo优化计算属性
|
||
- 使用useCallback优化函数引用
|
||
- 合理使用React.memo包装组件
|
||
|
||
**业务逻辑优化**:
|
||
- UseCase方法设计为无状态,避免实例状态维护
|
||
- 应用起多个微型的Store,不再让UI组件里面出现一大堆的state,这样可以让我们放心的拆分子组件,而状态和函数可以直接使用,而不是props传递一大堆,回调一大堆,注意store只存状态,不做任何业务逻辑,业务逻辑要写在useCase里面,store中的函数是交互事件+状态修改。
|
||
- 全局定义统一的tailwindcss的一些样式:圆角、边框、主题色、阴影。不要再像是现在这样每次都cursor随意发挥
|