395 lines
16 KiB
Markdown
395 lines
16 KiB
Markdown
|
|
# Messages模块与PostService/Manager架构对比分析报告
|
|||
|
|
|
|||
|
|
## 一、Messages模块架构分析
|
|||
|
|
|
|||
|
|
### 1.1 架构层次结构
|
|||
|
|
|
|||
|
|
Messages模块采用了**清晰的分层架构**,各层职责明确:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────┐
|
|||
|
|
│ 表现层 (Screens) │
|
|||
|
|
│ ChatScreen, MessageListScreen, NotificationsScreen │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Hooks层 │
|
|||
|
|
│ useDifferentialMessages, useChatScreen │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 用例层 (UseCases) │
|
|||
|
|
│ ProcessMessageUseCase │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 领域层 (Entities) │
|
|||
|
|
│ Message, Conversation, GroupNotice │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 仓库层 (Repositories) │
|
|||
|
|
│ MessageRepository, IMessageRepository │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 数据源层 (DataSources) │
|
|||
|
|
│ SSEClient, LocalDataSource, ApiDataSource │
|
|||
|
|
└─────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.2 核心组件详解
|
|||
|
|
|
|||
|
|
#### 1.2.1 领域实体层 (Core/Entities)
|
|||
|
|
- **Message.ts**: 定义消息、会话、群通知等核心领域模型
|
|||
|
|
- 包含工厂函数:`createMessage`, `createConversation`
|
|||
|
|
- 包含业务逻辑函数:`isMessageFromCurrentUser`, `shouldIncrementUnread`, `buildTextContent`
|
|||
|
|
|
|||
|
|
#### 1.2.2 用例层 (Core/UseCases)
|
|||
|
|
- **ProcessMessageUseCase**: 核心业务逻辑编排器
|
|||
|
|
- 订阅SSE事件(chat, group_message, read, recall, typing, group_notice等)
|
|||
|
|
- 消息去重处理(processedMessageIds Set)
|
|||
|
|
- 已读状态保护(pendingReadMap + 版本号机制)
|
|||
|
|
- 用户信息缓存与去重请求(pendingUserRequests Map)
|
|||
|
|
- 事件发布订阅模式(subscribers Set)
|
|||
|
|
|
|||
|
|
#### 1.2.3 仓库层 (Data/Repositories)
|
|||
|
|
- **IMessageRepository**: 定义数据访问接口
|
|||
|
|
- 消息操作:getMessages, saveMessage, updateMessageStatus, markAsRead
|
|||
|
|
- 会话操作:getConversations, saveConversation, updateUnreadCount
|
|||
|
|
- 同步操作:syncMessages, getServerLastSeq
|
|||
|
|
|
|||
|
|
- **MessageRepository**: 实现接口
|
|||
|
|
- 封装SQLite数据库操作
|
|||
|
|
- 消息与CachedMessage的转换
|
|||
|
|
|
|||
|
|
#### 1.2.4 映射器层 (Data/Mappers)
|
|||
|
|
- **MessageMapper**: 数据转换
|
|||
|
|
- `fromApiResponse`: API响应 → 应用模型
|
|||
|
|
- `fromDbRecord`: 数据库记录 → 应用模型
|
|||
|
|
- `toDbRecord`: 应用模型 → 数据库记录
|
|||
|
|
- `toApiRequest`: 应用模型 → API请求
|
|||
|
|
- 创建消息片段:`createTextSegment`, `createImageSegment`
|
|||
|
|
|
|||
|
|
#### 1.2.5 差异计算基础设施 (Infrastructure/Diff)
|
|||
|
|
- **MessageDiffCalculator**: 消息列表差异计算
|
|||
|
|
- 计算added, updated, deleted, moved, unchanged
|
|||
|
|
- 变化比例检测(changeRatio > 0.5 时触发重置)
|
|||
|
|
- 增量差异计算(基于缓存)
|
|||
|
|
|
|||
|
|
- **MessageUpdateBatcher**: 批量更新处理器
|
|||
|
|
- 16ms批量间隔(约60fps)
|
|||
|
|
- 去重和合并更新
|
|||
|
|
- 100ms最大等待时间
|
|||
|
|
- 统计信息:totalBatches, totalUpdates, averageBatchSize
|
|||
|
|
|
|||
|
|
- **types.ts**: 完整的类型定义
|
|||
|
|
- MessageUpdateType枚举:ADD, UPDATE, DELETE, MOVE, BATCH_*
|
|||
|
|
- DiffResult, DiffConfig等接口
|
|||
|
|
|
|||
|
|
#### 1.2.6 Hook层
|
|||
|
|
- **useDifferentialMessages**: 差异更新Hook
|
|||
|
|
- 集成DiffCalculator和Batcher
|
|||
|
|
- 自动处理批量更新
|
|||
|
|
- 提供flush, reset, forceUpdate方法
|
|||
|
|
- 支持配置:enableDiff, enableBatching, maxMessageCount, changeRatioThreshold
|
|||
|
|
|
|||
|
|
### 1.3 数据流
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
SSE事件 → ProcessMessageUseCase → 事件发布 → useChatScreen → useDifferentialMessages
|
|||
|
|
↓ ↓
|
|||
|
|
MessageRepository 差异计算 + 批量处理
|
|||
|
|
↓ ↓
|
|||
|
|
SQLite数据库 优化后的消息列表
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 1.4 状态管理方式
|
|||
|
|
|
|||
|
|
- **发布-订阅模式**:ProcessMessageUseCase作为事件中心
|
|||
|
|
- **本地SQLite缓存**:消息持久化存储
|
|||
|
|
- **内存状态**:通过Hook返回,组件直接消费
|
|||
|
|
- **差异更新**:通过MessageDiffCalculator + MessageUpdateBatcher减少重渲染
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、PostService/Manager架构分析
|
|||
|
|
|
|||
|
|
### 2.1 架构层次结构
|
|||
|
|
|
|||
|
|
Post模块采用了**扁平化架构**,Service和Manager层职责混合:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────┐
|
|||
|
|
│ 表现层 (Screens) │
|
|||
|
|
│ HomeScreen, PostDetailScreen, CreatePostScreen │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Hooks层 │
|
|||
|
|
│ useCursorPagination (通用), usePrefetch │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Store层 (Zustand) │
|
|||
|
|
│ useUserStore (直接操作状态), postManager (缓存管理) │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Service层 │
|
|||
|
|
│ postService (API调用 + 状态更新) │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 数据源 │
|
|||
|
|
│ API (直接调用) │
|
|||
|
|
└─────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 核心组件详解
|
|||
|
|
|
|||
|
|
#### 2.2.1 Service层 (Services)
|
|||
|
|
- **postService.ts**: 帖子服务
|
|||
|
|
- CRUD操作:getPosts, getPost, createPost, updatePost, deletePost
|
|||
|
|
- 互动操作:likePost, unlikePost, favoritePost, unfavoritePost
|
|||
|
|
- 分页支持:传统分页 + 游标分页
|
|||
|
|
- **问题**:直接操作useUserStore(违反分层原则)
|
|||
|
|
|
|||
|
|
#### 2.2.2 Manager层 (Stores)
|
|||
|
|
- **postManager.ts**: 帖子缓存管理器
|
|||
|
|
- 继承CacheBus(发布订阅基类)
|
|||
|
|
- 内存缓存:listCache, detailCache
|
|||
|
|
- 请求去重:pendingRequests Map
|
|||
|
|
- TTL管理:LIST_TTL=30s, DETAIL_TTL=60s
|
|||
|
|
- 后台刷新机制
|
|||
|
|
|
|||
|
|
#### 2.2.3 Store层 (Zustand)
|
|||
|
|
- **useUserStore**: 用户状态存储
|
|||
|
|
- 直接存储posts数组
|
|||
|
|
- 帖子操作副作用直接修改状态
|
|||
|
|
- 混合了用户数据和帖子数据
|
|||
|
|
|
|||
|
|
#### 2.2.4 映射器层 (Data/Mappers)
|
|||
|
|
- **PostMapper**: 数据转换
|
|||
|
|
- `fromApiResponse`: API响应 → 应用模型
|
|||
|
|
- `fromApiResponseList`: 批量转换
|
|||
|
|
- `toApiRequest`: 应用模型 → API请求
|
|||
|
|
- 相比MessageMapper缺少数据库记录转换方法
|
|||
|
|
|
|||
|
|
### 2.3 数据流
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
HomeScreen → useCursorPagination → postService.getPostsCursor
|
|||
|
|
↓
|
|||
|
|
useUserStore.setState(posts)
|
|||
|
|
↓
|
|||
|
|
PostCard组件渲染
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.4 状态管理方式
|
|||
|
|
|
|||
|
|
- **Zustand Store**:集中式状态管理
|
|||
|
|
- **内存缓存**:postManager提供应用级缓存
|
|||
|
|
- **请求去重**:dedupe方法防止重复请求
|
|||
|
|
- **直接修改**:postService直接调用useUserStore.setState
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、主要架构差异
|
|||
|
|
|
|||
|
|
### 3.1 分层复杂度
|
|||
|
|
|
|||
|
|
| 维度 | Messages模块 | Post模块 |
|
|||
|
|
|------|-------------|---------|
|
|||
|
|
| 层次深度 | 6层(Entity→UseCase→Repository→Mapper→Hook→Screen) | 4层(Service→Store→Hook→Screen) |
|
|||
|
|
| 用例层 | 独立ProcessMessageUseCase | 无 |
|
|||
|
|
| 仓库接口 | IMessageRepository抽象接口 | 无 |
|
|||
|
|
| 基础设施 | Diff模块(Calculator + Batcher) | 无 |
|
|||
|
|
|
|||
|
|
### 3.2 数据持久化
|
|||
|
|
|
|||
|
|
| 维度 | Messages模块 | Post模块 |
|
|||
|
|
|------|-------------|---------|
|
|||
|
|
| 本地存储 | SQLite数据库 | 无 |
|
|||
|
|
| 缓存抽象 | MessageRepository封装 | postManager内存缓存 |
|
|||
|
|
| 离线支持 | 完整 | 不支持 |
|
|||
|
|
|
|||
|
|
### 3.3 实时更新
|
|||
|
|
|
|||
|
|
| 维度 | Messages模块 | Post模块 |
|
|||
|
|
|------|-------------|---------|
|
|||
|
|
| 推送机制 | SSE实时推送 | 轮询/下拉刷新 |
|
|||
|
|
| 事件订阅 | ProcessMessageUseCase发布订阅 | 无 |
|
|||
|
|
| 增量更新 | MessageDiffCalculator | 无 |
|
|||
|
|
|
|||
|
|
### 3.4 状态管理
|
|||
|
|
|
|||
|
|
| 维度 | Messages模块 | Post模块 |
|
|||
|
|
|------|-------------|---------|
|
|||
|
|
| 管理方式 | 发布订阅 + Hook局部状态 | Zustand全局Store |
|
|||
|
|
| 状态来源 | useChatScreen, useDifferentialMessages | useUserStore |
|
|||
|
|
| 批量更新 | MessageUpdateBatcher | 无 |
|
|||
|
|
| 差异检测 | MessageDiffCalculator | 无 |
|
|||
|
|
|
|||
|
|
### 3.5 依赖方向
|
|||
|
|
|
|||
|
|
**Messages模块(正确)**:
|
|||
|
|
```
|
|||
|
|
Hook → UseCase → Repository → DataSource
|
|||
|
|
↓
|
|||
|
|
Entity(不依赖外部)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Post模块(问题)**:
|
|||
|
|
```
|
|||
|
|
Service → Store(循环依赖风险)
|
|||
|
|
↓
|
|||
|
|
API直接调用
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.6 核心问题总结
|
|||
|
|
|
|||
|
|
| # | 问题 | Messages | Post |
|
|||
|
|
|---|------|---------|------|
|
|||
|
|
| 1 | 违反分层原则 | 无 | postService直接操作useUserStore |
|
|||
|
|
| 2 | 缺少UseCase层 | ProcessMessageUseCase | 无业务逻辑编排 |
|
|||
|
|
| 3 | 缺少Repository抽象 | IMessageRepository | 无数据访问接口 |
|
|||
|
|
| 4 | 无差异更新 | useDifferentialMessages | 无 |
|
|||
|
|
| 5 | 无批量处理 | MessageUpdateBatcher | 无 |
|
|||
|
|
| 6 | 无本地持久化 | SQLite | 无 |
|
|||
|
|
| 7 | 无实时推送 | SSE | 无 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、对齐建议
|
|||
|
|
|
|||
|
|
### 4.1 架构重构目标
|
|||
|
|
|
|||
|
|
将Post模块对齐到Messages模块的架构模式:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────┐
|
|||
|
|
│ 表现层 (Screens) │
|
|||
|
|
│ HomeScreen, PostDetailScreen │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Hooks层 │
|
|||
|
|
│ useDifferentialPosts (新增) │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 用例层 (UseCases) │
|
|||
|
|
│ ProcessPostUseCase (新增) │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 领域层 (Entities) │
|
|||
|
|
│ Post, PostComment (新增) │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ 仓库层 (Repositories) │
|
|||
|
|
│ PostRepository, IPostRepository (新增) │
|
|||
|
|
├─────────────────────────────────────────────────────────────┤
|
|||
|
|
│ Service层 │
|
|||
|
|
│ postService (仅保留API调用,移除状态操作) │
|
|||
|
|
└─────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 具体改造项
|
|||
|
|
|
|||
|
|
#### 4.2.1 创建Post领域实体
|
|||
|
|
```typescript
|
|||
|
|
// src/core/entities/Post.ts
|
|||
|
|
export interface Post {
|
|||
|
|
id: string;
|
|||
|
|
authorId: string;
|
|||
|
|
title: string;
|
|||
|
|
content: string;
|
|||
|
|
images: string[];
|
|||
|
|
likeCount: number;
|
|||
|
|
commentCount: number;
|
|||
|
|
// ... 其他字段
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2.2 创建ProcessPostUseCase
|
|||
|
|
```typescript
|
|||
|
|
// src/core/usecases/ProcessPostUseCase.ts
|
|||
|
|
class ProcessPostUseCase {
|
|||
|
|
// 帖子增删改查
|
|||
|
|
// 点赞/收藏逻辑
|
|||
|
|
// 事件发布订阅
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2.3 创建IPostRepository接口
|
|||
|
|
```typescript
|
|||
|
|
// src/data/repositories/interfaces/IPostRepository.ts
|
|||
|
|
interface IPostRepository {
|
|||
|
|
getPosts(type: string, page: number, pageSize: number): Promise<Post[]>;
|
|||
|
|
savePost(post: Post): Promise<void>;
|
|||
|
|
updatePost(postId: string, updates: Partial<Post>): Promise<void>;
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2.4 创建PostRepository实现
|
|||
|
|
```typescript
|
|||
|
|
// src/data/repositories/PostRepository.ts
|
|||
|
|
// 封装SQLite操作,实现IPostRepository接口
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2.5 创建useDifferentialPosts Hook
|
|||
|
|
```typescript
|
|||
|
|
// src/hooks/useDifferentialPosts.ts
|
|||
|
|
// 类似useDifferentialMessages,处理帖子列表差异更新
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2.6 改造postService
|
|||
|
|
- 移除对useUserStore的直接依赖
|
|||
|
|
- 仅保留API调用职责
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、架构对比图
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
subgraph "Messages模块 [理想架构]"
|
|||
|
|
E1[Entity<br/>Message.ts]
|
|||
|
|
U1[UseCase<br/>ProcessMessageUseCase]
|
|||
|
|
R1[Repository<br/>MessageRepository]
|
|||
|
|
M1[Mapper<br/>MessageMapper]
|
|||
|
|
H1[Hook<br/>useDifferentialMessages]
|
|||
|
|
D1[Diff基础设施<br/>DiffCalculator + Batcher]
|
|||
|
|
S1[(SQLite)]
|
|||
|
|
|
|||
|
|
E1 --> U1
|
|||
|
|
U1 --> R1
|
|||
|
|
U1 --> D1
|
|||
|
|
R1 --> S1
|
|||
|
|
M1 --> R1
|
|||
|
|
D1 --> H1
|
|||
|
|
H1 --> S1
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
subgraph "Post模块 [当前架构]"
|
|||
|
|
E2[PostMapper]
|
|||
|
|
SV2[postService<br/>直接操作Store]
|
|||
|
|
ST2[useUserStore<br/>Zustand]
|
|||
|
|
H2[Hook<br/>useCursorPagination]
|
|||
|
|
PM2[postManager<br/>内存缓存]
|
|||
|
|
|
|||
|
|
E2 --> SV2
|
|||
|
|
SV2 --> ST2
|
|||
|
|
H2 --> SV2
|
|||
|
|
PM2 --> ST2
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
style E1 fill:#90EE90
|
|||
|
|
style U1 fill:#90EE90
|
|||
|
|
style R1 fill:#90EE90
|
|||
|
|
style D1 fill:#90EE90
|
|||
|
|
style H1 fill:#90EE90
|
|||
|
|
style S1 fill:#90EE90
|
|||
|
|
|
|||
|
|
style SV2 fill:#FFB6C1
|
|||
|
|
style ST2 fill:#FFB6C1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、结论
|
|||
|
|
|
|||
|
|
Messages模块是一个**架构完善**的模块,具备:
|
|||
|
|
1. 清晰的分层架构
|
|||
|
|
2. 独立的业务逻辑编排层(UseCase)
|
|||
|
|
3. 完整的数据持久化(SQLite)
|
|||
|
|
4. 高效的差异更新机制
|
|||
|
|
5. 实时事件推送能力
|
|||
|
|
|
|||
|
|
Post模块当前存在以下问题:
|
|||
|
|
1. **违反分层原则**:Service直接操作Store
|
|||
|
|
2. **缺少UseCase层**:业务逻辑分散
|
|||
|
|
3. **无数据抽象**:缺少Repository接口
|
|||
|
|
4. **无差异更新**:每次全量更新导致性能问题
|
|||
|
|
5. **无本地持久化**:无法离线使用
|
|||
|
|
|
|||
|
|
建议按照对齐建议逐步重构Post模块,使其架构与Messages模块对齐。
|