Files
bq_react/doc/基础知识/DDD是什么.md

73 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DDD是什么
这里的 DDD 指领域规则写在领域对象上,再用分层规定代码放在哪一层。本仓库用它来规定功能模块的写法。
## 目录
- [四层](#四层)
- [聚合](#聚合)
- [端口](#端口)
- [本仓库里怎么落](#本仓库里怎么落)
## 四层
一个功能模块在 `src/features/<name>/` 下按层分目录。
| 层 | 放什么 | 不放什么 |
|---|---|---|
| `domain` | 聚合根、值对象、领域方法、端口 | React、`src/app`、本地或远程的说法 |
| `application` | 用例。一次业务动作,例如登录、按 `store` 保存项目 | 页面状态、axios、IndexedDB |
| `infra` | 端口的实现。访问网络或本地库,并把接口数据收成领域对象 | 页面和 ViewModel |
| `presentation` | 页面和 ViewModel | 领域规则,例如笔画长短、撤销栈 |
没有内容的层不建空目录。首页只有 `presentation`,因为它不持有自己的用例,列表和新建都调用 `ProjectApplication`。
用例是模块的业务。`SecurityApplication.login` 负责登录,并把 `LoginResult` 里的访问凭证写入会话。ViewModel 是页面的业务,只保存当前页的表单、错误和加载状态,再调用用例。
## 聚合
`Project` 是项目聚合的根。文件:`src/features/project/domain/entities/project.ts`。外部通过它的方法改文档:
| 方法 | 作用 |
|---|---|
| `Project.create(name)` | 新建一个项目 |
| `addShape(shape)` | 位移小于 2 时拒绝;接受后把当前 `Document` 快照记进聚合,再加入图形 |
| `undo()` / `redo()` | 在聚合内部的 `past`、`future` 之间恢复 `Document` |
| `touch()` | 更新 `updatedAt`。保存前由用例调用 |
`Document.addShape` 只由 `Project` 调用。`past` 和 `future` 是聚合上的普通字段,不是 `tProp`,所以 `getSnapshot(project)` 不会把撤销栈写进本地库或接口。
安全模块的领域对象是 `AuthCredentials`、`RegisterCredentials`、`User` 和 `LoginResult`。用户名不少于 3 个字符,密码不少于 6 个字符,注册时两次密码相同。`User.hasPermission` 判断角色。`LoginResult` 持有 `User` 和 `accessToken`。
`AUTH_CHANGED` 由 `src/app/session` 在凭证写入或清除后通知界面。它属于会话,不属于领域对象。
## 端口
`domain` 里的端口是抽象类。方法名只表达业务,不写 `local` 或 `remote`。
`ISecurityRepository.login` 返回 `LoginResult`,`register` 接收 `RegisterCredentials`。`SecurityRepository` 用 `Http` 访问接口,再把响应收成 `User` 和 `LoginResult`。
`IProjectRepository` 声明 `list`、`get`、`save`。`LocalProjectRepository` 和 `RemoteProjectRepository` 都实现这一个端口。存在哪一侧由领域枚举 `ProjectStore` 决定,`Project` 上没有这个字段。
## 本仓库里怎么落
登录:
```text
presentation/security_view_model.ts 校验表单,调用 login
application/security_application.ts 调用端口,把 accessToken 交给 TokenStore
domain/i_security_repository.ts 声明 login,返回 LoginResult
infra/security_repository.ts 用 Http 访问 /auth/login,收成 LoginResult
```
绘制:
```text
presentation/editor_view_model.ts 记录草稿,调用 Project.addShape
domain/entities/project.ts 判定笔画,维护撤销栈
application/project_application.ts 按 store 调用 save
infra/..._project_repository.ts 把项目快照写入 IndexedDB 或 Http
```
`TokenStore`、`Http`、`Database` 属于 `src/app`,是全库能力,不是功能模块的领域规则。