跳转到内容

后端项目目录结构规范

模块分层、包划分(DDD / 分层架构)


  • Standard:后端项目默认采用经典四层分层架构,自顶向下依赖,禁止反向依赖。
层级职责依赖方向
Controller 层HTTP 入口、请求校验、响应组装→ Service
Service 层业务逻辑编排、事务控制→ Repository / Domain
Repository 层数据访问(DAO)、ORM 映射→ Database
Entity/Model 层数据模型定义—
  • Requirement:上层可依赖下层,下层 禁止 依赖上层。
  • Requirement:同层模块之间通过接口依赖,禁止直接依赖具体实现类。
  • Standard:Controller 层不得包含业务逻辑,仅做参数校验与响应转换。
  • Standard:Service 层不得直接处理 HTTP 请求对象(Request/Response),应接收领域对象或 DTO。
  • Caution:禁止跨层调用,如 Controller 直接调用 Repository。
Controller → Service → Repository → Database
│ │
▼ ▼
Request Domain
Response Object

  • Standard:业务复杂度高、领域模型丰富的项目,采用 DDD(领域驱动设计)分层。
层级包名职责
用户接口层interfacesController、DTO、Assembler
应用层application应用服务、Command/Query、事件编排
领域层domain实体、值对象、聚合根、领域服务、仓储接口
基础设施层infrastructure仓储实现、外部 API 客户端、消息队列
  • Requirement:领域层定义仓储接口(Repository),基础设施层提供实现。
  • Requirement:领域层 禁止 依赖基础设施层,通过依赖注入解耦。
  • Standard:应用层编排多个领域服务,不包含核心业务规则。
  • Caution:禁止将领域逻辑泄漏到应用层或基础设施层。
  • Standard:按业务领域划分为独立的模块(限界上下文),每个模块拥有独立的领域层与基础设施层。
  • Standard:跨上下文通信通过应用服务或领域事件,禁止直接访问其他上下文的领域对象。

  • Requirement:包名全部小写,使用点分隔,禁止使用下划线或驼峰。
  • Requirement:包名前缀为 com.<公司>.<项目>,如 com.example.user。
  • Standard:按分层或领域组织包,以下两种方式二选一:

按分层组织(简单项目):

com.example.user
├── controller
├── service
├── repository
├── entity
├── dto
└── config

按领域组织(DDD / 复杂项目):

com.example.user
├── interfaces
│ ├── controller
│ ├── dto
│ └── assembler
├── application
│ ├── command
│ ├── query
│ └── service
├── domain
│ ├── model
│ ├── service
│ └── repository
└── infrastructure
├── repository
├── client
└── mq
  • Requirement:包名全部小写,使用下划线分隔多单词(PEP 8)。
  • Standard:按模块划分顶层包,模块内部按职责划分子包。
user_service/
├── api/ # Controller 层(路由、请求/响应模型)
├── service/ # 业务逻辑
├── repository/ # 数据访问
├── models/ # 数据模型 / ORM 实体
├── schemas/ # Pydantic 模型(请求/响应 DTO)
├── core/ # 配置、安全、工具
└── tests/ # 测试
  • Requirement:包名全部小写,简短且语义明确,禁止使用下划线或驼峰。
  • Standard:按职责或领域组织包,避免 common、utils 等含义模糊的包名。
user-service/
├── cmd/ # 入口 main
├── internal/ # 内部包(不对外暴露)
│ ├── handler/ # HTTP handler
│ ├── service/ # 业务逻辑
│ ├── repository/ # 数据访问
│ ├── model/ # 领域模型
│ └── config/ # 配置
├── pkg/ # 可复用的公共包
└── api/ # API 定义(protobuf / OpenAPI)

user-service/
├── src/main/java/com/example/user/
│ ├── UserServiceApplication.java
│ ├── interfaces/
│ │ ├── controller/
│ │ │ └── UserController.java
│ │ ├── dto/
│ │ │ ├── request/
│ │ │ └── response/
│ │ └── assembler/
│ ├── application/
│ │ ├── command/
│ │ ├── query/
│ │ └── UserApplicationService.java
│ ├── domain/
│ │ ├── model/
│ │ │ ├── User.java
│ │ │ └── UserId.java # 值对象
│ │ ├── service/
│ │ │ └── UserDomainService.java
│ │ └── repository/
│ │ └── UserRepository.java # 接口
│ └── infrastructure/
│ ├── repository/
│ │ └── UserRepositoryImpl.java
│ ├── persistence/
│ │ └── entity/ # JPA Entity
│ ├── client/ # 外部 API 客户端
│ └── config/
│ └── DataSourceConfig.java
├── src/main/resources/
│ ├── application.yml
│ ├── application-dev.yml
│ ├── application-prod.yml
│ ├── mapper/ # MyBatis XML(如使用)
│ └── db/migration/ # Flyway 脚本
└── src/test/java/com/example/user/
├── unit/
├── integration/
└── e2e/
user-service/
├── app/
│ ├── main.py # 应用入口
│ ├── api/
│ │ ├── __init__.py
│ │ ├── routes/
│ │ │ ├── __init__.py
│ │ │ └── user.py
│ │ └── deps.py # 依赖注入
│ ├── schemas/ # Pydantic 请求/响应模型
│ │ ├── __init__.py
│ │ ├── user.py
│ │ └── common.py
│ ├── services/ # 业务逻辑
│ │ ├── __init__.py
│ │ └── user_service.py
│ ├── repositories/ # 数据访问
│ │ ├── __init__.py
│ │ └── user_repository.py
│ ├── models/ # ORM 模型(SQLAlchemy)
│ │ ├── __init__.py
│ │ └── user.py
│ ├── core/ # 配置、安全、工具
│ │ ├── __init__.py
│ │ ├── config.py
│ │ ├── security.py
│ │ └── exceptions.py
│ └── db/
│ ├── __init__.py
│ ├── base.py
│ └── session.py
├── alembic/ # 数据库迁移
├── tests/
│ ├── unit/
│ ├── integration/
│ └── conftest.py
├── pyproject.toml
└── .env.example
user-service/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── handler/ # HTTP handler
│ │ ├── user_handler.go
│ │ └── response.go
│ ├── service/ # 业务逻辑
│ │ └── user_service.go
│ ├── repository/ # 数据访问
│ │ └── user_repository.go
│ ├── model/ # 领域模型
│ │ └── user.go
│ ├── config/ # 配置
│ │ └── config.go
│ └── middleware/
├── pkg/ # 公共可复用包
│ ├── logger/
│ └── errors/
├── api/ # API 定义
│ └── openapi.yaml
├── migrations/ # 数据库迁移
├── configs/
│ ├── config.yaml
│ └── config.prod.yaml
└── tests/

反模式问题建议
所有类放在一个包下无法区分职责,难以维护按分层/领域分包
common / utils 大包什么都往里塞,变成垃圾桶按职责拆分到具体模块
Controller 包含业务逻辑违反分层,无法复用业务逻辑移到 Service
Service 直接操作 HTTP 请求对象耦合传输层用 DTO 解耦
领域层依赖 ORM 框架领域模型被基础设施污染领域层定义接口,基础设施层实现
跨模块直接访问数据库表破坏模块边界通过服务接口或事件通信
测试与源码混放构建产物包含测试代码测试独立 tests/ 目录
  • ❌ 包名使用大写或驼峰:com.example.UserService。
  • ❌ 包名使用下划线:com.example.user_service。
  • ❌ 类名与包名重复:user/user/User.java。
  • ❌ 文件名与类名不一致(Java)。
  • ❌ Python 模块使用驼峰命名:userService.py。
  • ❌ Go 包名使用下划线:user_service。
  • Caution:禁止创建无边界的 Utils、Helper、Common 类。
  • Standard:工具方法应归属到具体领域模块,或按职责拆分为独立工具包(如 DateUtils、StringUtils、CryptoUtils)。
  • Standard:每个工具类职责单一,方法数 ≤ 20,超过应拆分。