640 lines
14 KiB
Markdown
640 lines
14 KiB
Markdown
# DDD 脚手架生成工具
|
||
|
||
一个功能强大、高度可配置的领域驱动设计(DDD)项目脚手架生成工具,支持模块化单体架构。
|
||
|
||
## 核心特性
|
||
|
||
### 灵活的架构支持
|
||
|
||
- **多上下文管理**:一次生成多个有界上下文(Bounded Context)
|
||
- **分层架构**:支持 API、Domain、Application、Infrastructure、Interfaces 等标准 DDD 分层
|
||
- **目录结构自定义**:支持标准 Maven 结构或自定义扁平结构
|
||
- **模块化命名**:灵活的模块命名模式,满足不同团队规范
|
||
|
||
### 强大的配置能力
|
||
|
||
- **树形目录配置**:直观的嵌套结构定义,所见即所得
|
||
- **文件模板系统**:在配置中直接定义文件内容和模板
|
||
- **模板变量**:完全可配置的变量系统,支持多层引用
|
||
- **占位符选项**:自动生成 `.keep`、`package-info.java`、README 等文件
|
||
|
||
### 安全的回滚机制
|
||
|
||
- **文件哈希验证**:基于 SHA256 哈希确保文件未被修改
|
||
- **智能跳过**:自动跳过用户修改的文件,不会误删
|
||
- **父目录保护**:自动保护包含用户文件的目录结构
|
||
- **清单追踪**:完整记录所有生成的文件和目录
|
||
|
||
### 其他实用功能
|
||
|
||
- **Dry-run 模式**:预览生成结果,不实际创建文件
|
||
- **覆盖策略**:skip、overwrite、fail 三种策略可选
|
||
- **详细日志**:支持 verbose 模式,方便调试
|
||
- **向后兼容**:完全兼容旧版配置格式
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### 安装
|
||
|
||
```bash
|
||
# 克隆仓库
|
||
git clone https://github.com/huiyiruciduojiao/scaffold_ddd.git
|
||
cd scaffold_ddd
|
||
|
||
# 无需额外依赖,Python 3.8+ 即可运行
|
||
python scaffold_ddd.py --help
|
||
```
|
||
|
||
### 初始化配置
|
||
|
||
```bash
|
||
# 生成示例配置文件
|
||
python scaffold_ddd.py --init-config scaffold.json
|
||
|
||
# 编辑配置文件
|
||
vim scaffold.json
|
||
```
|
||
|
||
### 生成项目
|
||
|
||
```bash
|
||
# 基本用法
|
||
python scaffold_ddd.py --config scaffold.json --contexts auth,user
|
||
|
||
# 预览模式(不实际创建文件)
|
||
python scaffold_ddd.py --config scaffold.json --contexts auth --dry-run
|
||
|
||
# 详细日志
|
||
python scaffold_ddd.py --config scaffold.json --contexts auth -v
|
||
```
|
||
|
||
### 回滚
|
||
|
||
```bash
|
||
# 预览回滚
|
||
python scaffold_ddd.py --rollback modules/auth/manifest.json --dry-run
|
||
|
||
# 执行回滚
|
||
python scaffold_ddd.py --rollback modules/auth/manifest.json
|
||
```
|
||
|
||
---
|
||
|
||
## 配置文件详解
|
||
|
||
### 基本配置
|
||
|
||
```json
|
||
{
|
||
"root": "modules", // 上下文根目录
|
||
"package_base": "top.ysit.travel", // 基础包名
|
||
"contexts": ["auth", "user"], // 要生成的上下文列表
|
||
"layers": [ // 要生成的层
|
||
"api",
|
||
"domain",
|
||
"application",
|
||
"infrastructure",
|
||
"interfaces"
|
||
],
|
||
"use_standard_structure": false, // 是否使用标准 Maven 结构
|
||
"overwrite": "skip" // 覆盖策略:skip | overwrite | fail
|
||
}
|
||
```
|
||
|
||
### 模块命名配置
|
||
|
||
```json
|
||
{
|
||
"naming": {
|
||
"module_name_pattern": "{layer}", // 模块名模式
|
||
"context_dir_pattern": "{context}" // 上下文目录模式
|
||
}
|
||
}
|
||
```
|
||
|
||
**示例**:
|
||
- `{layer}` → 生成 `api/`, `domain/`, `application/`
|
||
- `{context}-{layer}` → 生成 `auth-api/`, `auth-domain/`
|
||
|
||
### 占位符配置
|
||
|
||
```json
|
||
{
|
||
"placeholders": {
|
||
"create_keep_files": true, // 为空目录创建 .keep 文件
|
||
"create_package_info": true, // 创建 package-info.java
|
||
"create_layer_readme": false, // 创建层级 README
|
||
"create_context_readme": false // 创建上下文 README
|
||
}
|
||
}
|
||
```
|
||
|
||
### 模板变量配置
|
||
|
||
```json
|
||
{
|
||
"template_vars": {
|
||
"package": "{package_base}.{context}",
|
||
"context_package": "{package_base}.{context}",
|
||
"layer_package": "{package}.{layer}",
|
||
"author": "Your Name",
|
||
"organization": "Your Org"
|
||
}
|
||
}
|
||
```
|
||
|
||
**内置变量**:
|
||
- `{context}` - 上下文名称(如 `auth`)
|
||
- `{layer}` - 层名称(如 `domain`)
|
||
- `{module}` - 模块名称(如 `auth-domain`)
|
||
- `{package_base}` - 基础包名(如 `top.ysit.travel`)
|
||
|
||
**自定义变量**:支持引用其他变量,自动多轮解析
|
||
|
||
### 目录结构配置
|
||
|
||
#### 方式一:树形结构(推荐)
|
||
|
||
```json
|
||
{
|
||
"layer_dirs": {
|
||
"api": {
|
||
"contract": {},
|
||
"event": {},
|
||
"client": {},
|
||
"_files": {
|
||
"package-info.java": "package {layer_package};\n"
|
||
}
|
||
},
|
||
"domain": {
|
||
"model": {
|
||
"aggregate": {
|
||
"_files": {
|
||
".gitkeep": ""
|
||
}
|
||
},
|
||
"entity": {},
|
||
"vo": {}
|
||
},
|
||
"repository": {},
|
||
"service": {}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 方式二:列表格式(兼容旧版)
|
||
|
||
```json
|
||
{
|
||
"layer_dirs": {
|
||
"domain": [
|
||
"model/aggregate",
|
||
"model/entity",
|
||
"repository"
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 使用示例
|
||
|
||
### 示例 1: 生成单个上下文
|
||
|
||
```bash
|
||
python scaffold_ddd.py \
|
||
--config scaffold.json \
|
||
--contexts auth
|
||
```
|
||
|
||
**生成结构**:
|
||
```
|
||
modules/
|
||
└── auth/
|
||
├── manifest.json
|
||
├── api/
|
||
│ ├── package-info.java
|
||
│ ├── contract/
|
||
│ ├── event/
|
||
│ └── client/
|
||
├── domain/
|
||
│ ├── package-info.java
|
||
│ ├── model/
|
||
│ │ ├── aggregate/
|
||
│ │ ├── entity/
|
||
│ │ └── vo/
|
||
│ ├── repository/
|
||
│ └── service/
|
||
└── ...
|
||
```
|
||
|
||
### 示例 2: 生成多个上下文
|
||
|
||
```bash
|
||
python scaffold_ddd.py \
|
||
--config scaffold.json \
|
||
--contexts auth,user,order
|
||
```
|
||
|
||
### 示例 3: 使用命令行参数覆盖配置
|
||
|
||
```bash
|
||
python scaffold_ddd.py \
|
||
--config scaffold.json \
|
||
--contexts auth \
|
||
--package-base com.mycompany.project \
|
||
--overwrite overwrite
|
||
```
|
||
|
||
### 示例 4: 预览生成结果
|
||
|
||
```bash
|
||
python scaffold_ddd.py \
|
||
--config scaffold.json \
|
||
--contexts auth \
|
||
--dry-run \
|
||
--manifest-stdout
|
||
```
|
||
|
||
### 示例 5: 安全回滚
|
||
|
||
```bash
|
||
# 1. 先预览回滚效果
|
||
python scaffold_ddd.py --rollback modules/auth/manifest.json --dry-run -v
|
||
|
||
# 2. 确认无误后执行
|
||
python scaffold_ddd.py --rollback modules/auth/manifest.json
|
||
```
|
||
|
||
---
|
||
|
||
## 高级功能
|
||
|
||
### 1. 文件模板
|
||
|
||
在配置中直接定义文件内容:
|
||
|
||
```json
|
||
{
|
||
"layer_dirs": {
|
||
"domain": {
|
||
"exception": {
|
||
"_files": {
|
||
"DomainException.java": "package {context_package}.domain.exception;\n\n/**\n * Base domain exception for {context} context\n * @author {author}\n */\npublic class DomainException extends RuntimeException {\n public DomainException(String message) {\n super(message);\n }\n}\n"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 从外部文件读取
|
||
|
||
```json
|
||
{
|
||
"_files": {
|
||
"README.md": {
|
||
"content_from": "templates/domain_readme.md"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 智能回滚
|
||
|
||
**场景 1**:所有文件未修改
|
||
```bash
|
||
$ python scaffold_ddd.py --rollback modules/auth/manifest.json
|
||
INFO ✓ Verified 34 file(s) by hash
|
||
INFO Deleted 35 file(s)
|
||
INFO Deleted empty context directory: modules\auth
|
||
INFO Rollback completed successfully
|
||
```
|
||
|
||
**场景 2**:部分文件被修改
|
||
```bash
|
||
$ python scaffold_ddd.py --rollback modules/auth/manifest.json
|
||
WARNING ⚠ Hash verification failed for 2 file(s). These files will be skipped.
|
||
WARNING - modules\auth\api\README.md
|
||
INFO Deleted 32 file(s)
|
||
INFO Protected 5 path(s) due to skipped files
|
||
WARNING ⚠ Rollback completed with 2 file(s) skipped
|
||
```
|
||
|
||
### 4. 自定义包结构
|
||
|
||
**标准结构**(`use_standard_structure: true`):
|
||
```
|
||
modules/auth/domain/
|
||
└── src/main/java/
|
||
└── top/ysit/travel/auth/domain/
|
||
├── model/
|
||
└── repository/
|
||
```
|
||
|
||
**扁平结构**(`use_standard_structure: false`):
|
||
```
|
||
modules/auth/domain/
|
||
├── model/
|
||
└── repository/
|
||
```
|
||
|
||
---
|
||
|
||
## 完整配置示例
|
||
|
||
```json
|
||
{
|
||
"root": "modules",
|
||
"package_base": "top.ysit.travel",
|
||
"contexts": ["auth", "user", "order"],
|
||
"layers": ["api", "domain", "application", "infrastructure", "interfaces"],
|
||
"java_source_dir": "src/main/java",
|
||
"resources_dir": "src/main/resources",
|
||
"overwrite": "skip",
|
||
"dry_run": false,
|
||
"emit_manifest": true,
|
||
"manifest_name": "manifest.json",
|
||
"use_standard_structure": false,
|
||
|
||
"naming": {
|
||
"module_name_pattern": "{layer}",
|
||
"context_dir_pattern": "{context}"
|
||
},
|
||
|
||
"placeholders": {
|
||
"create_keep_files": true,
|
||
"create_package_info": true,
|
||
"create_layer_readme": false,
|
||
"create_context_readme": false
|
||
},
|
||
|
||
"template_vars": {
|
||
"package": "{package_base}.{context}",
|
||
"context_package": "{package_base}.{context}",
|
||
"layer_package": "{package}.{layer}",
|
||
"author": "DDD Scaffold Tool",
|
||
"organization": "YSIT",
|
||
"license": "MIT"
|
||
},
|
||
|
||
"layer_dirs": {
|
||
"api": {
|
||
"contract": {},
|
||
"event": {},
|
||
"client": {},
|
||
"_files": {
|
||
"package-info.java": "/**\n * API contracts for {context} context.\n * @author {author}\n */\npackage {layer_package};\n"
|
||
}
|
||
},
|
||
|
||
"domain": {
|
||
"model": {
|
||
"aggregate": {
|
||
"_files": {
|
||
".gitkeep": ""
|
||
}
|
||
},
|
||
"entity": {},
|
||
"vo": {},
|
||
"enum": {}
|
||
},
|
||
"repository": {},
|
||
"event": {},
|
||
"service": {},
|
||
"exception": {
|
||
"_files": {
|
||
"DomainException.java": "package {context_package}.domain.exception;\n\npublic class DomainException extends RuntimeException {\n public DomainException(String message) {\n super(message);\n }\n}\n"
|
||
}
|
||
}
|
||
},
|
||
|
||
"application": {
|
||
"command": {},
|
||
"usecase": {},
|
||
"query": {
|
||
"dto": {}
|
||
},
|
||
"assembler": {},
|
||
"port": {
|
||
"in": {},
|
||
"out": {}
|
||
},
|
||
"security": {},
|
||
"handler": {}
|
||
},
|
||
|
||
"infrastructure": {
|
||
"persistence": {
|
||
"mapper": {},
|
||
"po": {},
|
||
"convert": {},
|
||
"repository": {}
|
||
},
|
||
"event": {},
|
||
"config": {}
|
||
},
|
||
|
||
"interfaces": {
|
||
"web": {
|
||
"request": {},
|
||
"response": {}
|
||
},
|
||
"facade": {},
|
||
"doc": {}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 命令行参数
|
||
|
||
```bash
|
||
python scaffold_ddd.py [OPTIONS]
|
||
|
||
Options:
|
||
--config PATH 配置文件路径
|
||
--init-config PATH 生成示例配置文件
|
||
--root DIR 上下文根目录(覆盖配置)
|
||
--package-base PKG 基础包名(覆盖配置)
|
||
--contexts CONTEXTS 逗号分隔的上下文列表
|
||
--layers LAYERS 逗号分隔的层列表
|
||
--overwrite POLICY 覆盖策略:skip | overwrite | fail
|
||
--dry-run 预览模式,不创建文件
|
||
--no-manifest 不生成 manifest.json
|
||
--manifest-stdout 输出 manifest 到标准输出
|
||
--manifest-write-in-dry-run 在 dry-run 模式也写入 manifest
|
||
--rollback MANIFEST_PATH 使用指定 manifest 回滚
|
||
-v, --verbose 详细日志输出
|
||
--help 显示帮助信息
|
||
```
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 如何选择目录结构?
|
||
|
||
**标准 Maven 结构** (`use_standard_structure: true`):
|
||
- 适合传统 Maven/Gradle 项目
|
||
- IDE 友好,自动识别源码目录
|
||
- 目录层级较深
|
||
|
||
**扁平结构** (`use_standard_structure: false`):
|
||
- 目录结构简洁
|
||
- 适合模块化单体架构
|
||
- 需要手动配置 IDE 源码目录
|
||
|
||
### Q2: 回滚会删除我修改的文件吗?
|
||
|
||
**不会!** 回滚功能使用 SHA256 哈希验证:
|
||
- 自动跳过被修改的文件
|
||
- 保护包含被修改文件的父目录
|
||
- 详细日志显示被跳过的文件
|
||
|
||
### Q3: 如何处理包名?
|
||
|
||
使用模板变量灵活控制:
|
||
|
||
```json
|
||
{
|
||
"template_vars": {
|
||
"package": "{package_base}.{context}",
|
||
"layer_package": "{package}.{layer}"
|
||
}
|
||
}
|
||
```
|
||
|
||
在文件模板中引用:
|
||
```java
|
||
package {layer_package}; // → top.ysit.travel.auth.domain
|
||
```
|
||
|
||
### Q4: 可以只生成部分层吗?
|
||
|
||
可以!使用 `--layers` 参数:
|
||
|
||
```bash
|
||
python scaffold_ddd.py \
|
||
--config scaffold.json \
|
||
--contexts auth \
|
||
--layers api,domain
|
||
```
|
||
|
||
### Q5: 如何在团队中共享配置?
|
||
|
||
1. 将 `scaffold.json` 提交到版本控制
|
||
2. 团队成员使用相同的配置文件
|
||
3. 根据项目需要在 CI/CD 中自动生成
|
||
|
||
### Q6: 支持哪些编程语言?
|
||
|
||
虽然默认配置面向 Java,但通过自定义配置可以支持任何语言:
|
||
- 修改文件扩展名
|
||
- 自定义文件模板
|
||
- 调整目录结构
|
||
|
||
---
|
||
|
||
## 最佳实践
|
||
|
||
### 1. 版本控制策略
|
||
|
||
```bash
|
||
# 提交配置文件
|
||
git add scaffold.json scaffold_ddd.py
|
||
git commit -m "Add DDD scaffold configuration"
|
||
|
||
# 不要提交生成的代码到主分支
|
||
echo "modules/" >> .gitignore
|
||
|
||
# 或者只提交初始骨架,后续开发不提交
|
||
git add modules/auth/domain/model/
|
||
git commit -m "Add domain model skeleton"
|
||
```
|
||
|
||
### 2. 配置组织
|
||
|
||
```json
|
||
{
|
||
"_comment": {
|
||
"description": "Auth context scaffold configuration",
|
||
"author": "Team Name",
|
||
"last_updated": "2026-01-11"
|
||
},
|
||
|
||
"template_vars": {
|
||
"_comment": "Package naming conventions",
|
||
"package": "{package_base}.{context}",
|
||
...
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 渐进式采用
|
||
|
||
```bash
|
||
# 步骤 1: 预览效果
|
||
python scaffold_ddd.py --config scaffold.json --contexts auth --dry-run
|
||
|
||
# 步骤 2: 生成一个上下文测试
|
||
python scaffold_ddd.py --config scaffold.json --contexts auth
|
||
|
||
# 步骤 3: 确认无误后生成所有上下文
|
||
python scaffold_ddd.py --config scaffold.json
|
||
```
|
||
|
||
### 4. 模板复用
|
||
|
||
将常用文件模板提取到外部:
|
||
|
||
```
|
||
templates/
|
||
├── domain_exception.java
|
||
├── package-info.java
|
||
└── README.md
|
||
|
||
scaffold.json:
|
||
{
|
||
"_files": {
|
||
"DomainException.java": {
|
||
"content_from": "templates/domain_exception.java"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 贡献指南
|
||
|
||
欢迎提交 Issue 和 Pull Request!
|
||
|
||
### 报告问题
|
||
|
||
提交 Issue 时请包含:
|
||
- Python 版本
|
||
- 完整的配置文件
|
||
- 错误信息和日志
|
||
- 重现步骤
|
||
|
||
### 提交代码
|
||
|
||
1. Fork 项目
|
||
2. 创建特性分支
|
||
3. 提交变更
|
||
4. 创建 Pull Request
|
||
|
||
---
|
||
|
||
## License
|
||
|
||
MIT License - 详见 [LICENSE](LICENSE) 文件
|
||
|