From d2dd4e57e4e39a2cf23d26d3c63cf06a6e4cd992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E9=BE=99?= Date: Mon, 1 Sep 2025 19:19:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/service/uml/DDDLayer.md | 107 ++++++++++++++------------------ components/pages/home-page2.tsx | 42 ++++++------- 2 files changed, 67 insertions(+), 82 deletions(-) diff --git a/app/service/uml/DDDLayer.md b/app/service/uml/DDDLayer.md index 25dc8ef..7d9a1bf 100644 --- a/app/service/uml/DDDLayer.md +++ b/app/service/uml/DDDLayer.md @@ -7,13 +7,11 @@ - React组件(Modal、Form、Button等) - 样式和布局逻辑 - 用户交互事件绑定 -- 通过props接收数据和回调函数 - +- 越是可复用组件,越要小心定义,越要简单,宁可页面中的组件使用多做点,也要组件少做点,因为复用越多,它就可能发生的变化越多,除非你很确定它的变化不会更多了。 **设计原则**: - 不包含业务逻辑 - 不直接操作状态 -- 通过回调函数与上层通信 -- 可复用和可测试 + ### 2. Hook (状态管理层) **职责**:状态管理、副作用处理、业务逻辑组合 @@ -26,11 +24,29 @@ **设计原则**: - 协调全局状态和本地状态 - 处理异步操作和副作用 -- 组合多个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等) - 完整的业务流程方法 @@ -43,11 +59,11 @@ - 协调多个Service的调用 - 返回领域实体,而不是原始数据 - 无状态,方法调用间不依赖实例状态 +- 无关任何react的东西,纯粹的TS代码 ### 4. Service (外部服务层) -**职责**:外部服务集成、技术实现细节、基础设施 +**职责**:外部服务集成、技术实现细节、基础设施,它应该是一堆的服务函数,纯函数,输入到输出,没有外部的闭包依赖。不要觉得有时候可以从其它地方直接依赖,就不用参数来接收,它要干净,要是纯函数,要能通过参数判断其全部所需,所以要用接收参数的方式 **内容**: -- 外部API调用服务(ImageProcessingService、AIAnalysisService等) - 技术实现细节(图片处理、网络请求等) - 错误处理和重试逻辑 - 可以被多个UseCase复用的服务 @@ -57,58 +73,41 @@ - 处理外部API调用 - 提供统一的错误处理 - 实现接口隔离原则 +- 无关任何react的东西,纯粹的TS代码 ### 5. Repository (数据访问层) -**职责**:数据持久化、数据查询、数据转换 -**内容**: -- 数据访问类(ImageStoryRepository、CharacterRepository等) -- 数据持久化逻辑 -- 数据查询和过滤 -- 数据转换(Entity ↔ Data) - -**设计原则**: -- 封装数据访问细节 -- 提供统一的CRUD接口 -- 处理数据转换 -- 实现数据访问的抽象 +使用ApiFox去对接好后端的接口文档,然后MCP接入cursor,从而直接生成接口请求函数以及类型,相对于没有这个东西,cursor帮你写的代码将是天差地别的,能提高你大约20%的开发效率。当然这要协同后端好好写接口参数和响应的内容。 ## 📊 状态管理策略 -**状态分类与存储位置**: -- **业务核心状态** → Zustand Store(currentStory、storyList等) -- **UI交互状态** → 组件useState(isModalOpen、localInput等) -- **业务流程状态** → UseCase私有状态(analysisProgress等) -- **用户偏好状态** → Zustand Store(selectedCategory、theme等) -- **临时计算状态** → useMemo/useCallback(filteredStories等) +**状态分类**: +- **功能业务模块状态** → 微型Store,用不同模块功能去拆Store 而非页面,记住要用单例模式处理 +- **纯UI变化状态** → 组件useState,跟业务没有任何关系,只是UI变化所用的状态。 +- **业务流程状态** → UseCase私有状态,从这里开始就是跟react任何关系都没有了,纯TS代码去写的逻辑,状态也是纯粹的业务状态,一定要在这里忘记react的存在。 +- **全局状态** → 全局Store,跨模块共享,比如用户信息、主题色、语言等。 ## 数据流向 **状态流转过程**: -用户操作 → 组件本地状态 → Hook协调 → UseCase业务逻辑 → 全局状态更新 → 组件重新渲染 -**具体流程**: -1. 用户在组件中触发操作 -2. 组件更新本地状态 -3. Hook协调多个UseCase调用 -4. UseCase执行业务逻辑和规则验证 -5. 更新全局状态 -6. 组件重新渲染显示结果 +用户操作 → 组件本地状态 → Store Hook协调 → UseCase业务逻辑 → Store 状态更新 → 组件重新渲染 ## 设计模式应用 **核心模式**: -1. **依赖注入**:UseCase通过构造函数注入Service依赖 -2. **工厂模式**:创建UseCase实例,管理依赖关系 -3. **策略模式**:可插拔的业务策略(如不同的AI分析策略) -4. **观察者模式**:状态变化通知,组件响应式更新 +1. **依赖注入**:UseCase通过构造函数注入Service依赖,最好的简化useCase的方式。 +2. **策略模式**:要弄清楚,什么是策略,有了这个意识,我们这个项目,很多地方可以用到策略模式,可扩展性将提高一大截 +4. **观察者模式**:我们的项目需要跨页面,跨组件的复杂通讯,采用观察者模式是非常合适的,比如chatBox.如果搞不明白这个模式,那就事件总线,这个东西更容易理解,也能实现相同功能。 ## 🧪 测试策略 **分层测试**: -- **Component层**:组件渲染和交互测试 -- **Hook层**:状态管理和副作用测试 -- **UseCase层**:业务逻辑和规则验证测试 -- **Service层**:外部服务集成测试 -- **Repository层**:数据访问逻辑测试 +- **Component层**:组件渲染和交互测试(目前的前端测试框架,测试这个纯浪费时间,不要为这个层做单元测试) +- **Hook层**:状态管理和副作用测试(react的hook系统限制太大,不要为这个层做单元测试) +- **UseCase层**:业务逻辑和规则验证测试(这个层需要做单元测试,最适合的地方就是这个) +- **Service层**:外部服务集成测试(这个层不需要做单元测试,,因为用例层依赖这个层,如果用例层完备,这个就直接连带测试) +- **Repository层**:数据访问逻辑测试(对于前端来说,就是接口请求的一堆封装,用apifox 的mcp生成接口请求函数就好,不用再封装和创建更复杂内容。若测试这个,直接apifox) +- +>谦卑对象模式(Humble Object Pattern)是一种设计模式,用于将复杂逻辑从难以测试的组件中分离出来,以提高代码的可测试性和可维护性。其核心思想是将与用户界面、外部系统或复杂依赖相关的代码(难以测试的部分)剥离,保留一个“谦卑”的对象,只包含简单逻辑或直接调用,而将主要业务逻辑放入易于测试的独立对象中。 ## 错误处理机制 @@ -120,8 +119,8 @@ **错误处理流程**: 1. Service层捕获原始错误并转换为应用错误 2. UseCase层抛出领域错误 -3. Hook层统一捕获和处理错误 -4. 组件层显示错误信息 +3. Hook层将用例的错误,变成错误提示,展示给用户 +4. 组件层显示错误信息(组件层不需要做错误处理,因为组件层是纯展示层,不需要处理错误) ## 性能优化策略 @@ -132,19 +131,5 @@ **业务逻辑优化**: - UseCase方法设计为无状态,避免实例状态维护 -- Service层实现缓存和重试机制 -- Repository层实现数据分页和懒加载 - -## 📋 开发检查清单 - -**新增功能时**: -- [ ] 是否在正确的层次添加代码? -- [ ] 是否遵循单一职责原则? -- [ ] 是否定义了清晰的接口? -- [ ] 是否处理了错误情况? -- [ ] 是否添加了相应的测试? - -**重构代码时**: -- [ ] 是否保持了接口的向后兼容? -- [ ] 是否更新了相关的测试? -- [ ] 是否验证了功能完整性? +- 应用起多个微型的Store,不再让UI组件里面出现一大堆的state,这样可以让我们放心的拆分子组件,而状态和函数可以直接使用,而不是props传递一大堆,回调一大堆,注意store只存状态,不做任何业务逻辑,业务逻辑要写在useCase里面,store中的函数是交互事件+状态修改。 +- 全局定义统一的tailwindcss的一些样式:圆角、边框、主题色、阴影。不要再像是现在这样每次都cursor随意发挥 diff --git a/components/pages/home-page2.tsx b/components/pages/home-page2.tsx index 16c5e8c..5c9acdb 100644 --- a/components/pages/home-page2.tsx +++ b/components/pages/home-page2.tsx @@ -676,27 +676,27 @@ function HomeModule3() { > {mobileVideoList.map((video, videoIndex) => (