↑ ↓ 移动 · Enter 打开 · Esc 关闭点按一个结果

蓝图

选择形态,harness 负责执行。

每个蓝图都是一个 YAML 文件,包含模块、depends_on、forbidden_imports、包映射以及必填的取舍说明。新增架构无需改动任何 skill、智能体或提示词,CI 会在每次推送时检查这一点。

  • hexagonal

    领域居中,端口为接口,输入与输出适配器位于边缘,每个适配器一个 Maven 模块。

    有多个输入或输出通道:REST、消息、批处理。

  • hexagonal-single-module

    同样的端口与适配器,作为单个 Maven 模块中的包。适配器之间不能互相导入。

    多个通道,但不想为每个适配器配一个 POM。

  • clean-architecture-multi-module

    领域、应用与基础设施分为三个 Maven 模块;由构建强制依赖规则。

    业务规则需要与基础设施隔离。

  • clean-architecture-single-module

    同样的分层放在一个 Maven 模块中;模块变为包。bank-app 使用的就是它。

    三个 POM 的成本无人能摊薄。

  • layered

    controller → service → repository,沿用大多数 Spring Boot 教程的词汇。

    团队已熟悉这套说法,端口/适配器只会是翻译负担。

  • onion

    Palermo 本人的术语:Application Core 与 Gateway,每一层一个 Maven 模块。

    团队更偏好这些术语,而非 hexagonal 或 clean 的说法。

  • onion-single-module

    Palermo 的各层作为单个 Maven 模块中的包。持久化层与表现层互不依赖。

    要 Application Core 与 Gateway,但不想为每一层配一个 POM。

  • vertical-slice

    按功能而非技术层组织代码:Command/Query、Handler、Endpoint 与 Response 放在一起。

    各功能之间差异大于共性。

  • modular-monolith

    多个限界上下文在一个可部署单元中,边界比口头约定更强。

    上下文尚不足以拆成独立部署。

  • custom-template

    你自己的架构,用 YAML 描述。

    九种都不合适时。

§ 一条声明,三种效果

forbidden_imports

# blueprints/hexagonal.yaml
modules:
  - id: domain
    depends_on: []
    forbidden_imports:
      - "org.springframework.."
      - "jakarta.persistence.."
      - "jakarta.validation.."
  - id: application
    depends_on: [domain, commons]
    forbidden_imports:
      - "jakarta.persistence.."
      - "org.springframework.web.."
  1. domain/CLAUDE.md模型知道
  2. .claude/forbidden-imports.txtcheck hook 拦截写入,exit 2
  3. pom.xml · depends_on在多模块布局中编译器拒绝

规范的 glob(paths)在生成时根据包映射重写,因此规范只为该蓝图实际拥有的包加载。

§ CI 检查什么

先作为数据验证,再生成并构建

每次推送,validate.yml 都会对蓝图运行这些检查:

  • 每个蓝图两次导出得到相同的目录树,且没有失效引用。
  • 每个 templates.<role> 都指向真实存在的文件。
  • 新增蓝图文件不会改动任何 skill、agent 或提示词。
  • hexagonal-single-module 让各适配器互相隔离,且十个包的矩阵完整。

validate.yml从不构建项目,所以由 blueprints.yml 来构建。对每个可能受一次改动影响的蓝图,它根据 YAML 生成骨架(不使用语言模型),并分别用 Maven 和 Gradle 构建:九个蓝图、两种工具、18 个 job。

  • 骨架是 Initializr 的 starter,按蓝图塑形:多模块时依据 modules[] 与 depends_on 建立 reactor,并为包映射中的每个角色生成一个 package-info.java。
  • ArchHook.jar boundary-map 与 export 写出项目的 .claude/,随后运行 ./mvnw verify 或 ./gradlew build,且 doctor gate 必须通过。
  • 接着,每条边界规则对应一个类,导入该规则禁止的内容:doctor gate 必须失败并点名每个这样的文件,check 必须以 exit 2 拦截其中一个。
  • 仅当蓝图、project-bootstrap、hook 或 schema 改动时才运行。改动某个蓝图只生成该蓝图。它不是必需检查。

在三个 -single-module 蓝图中,编译器不强制边界。强制边界的是每次编辑时的 check hook、项目 CI 中的 doctor gate 以及 ArchUnit。骨架并非完整的生成过程:测试自己写最小化的构建文件,因此 project-bootstrap 根据 templates/pom.*.xml.example 调整的 POM、功能依赖以及 agent 自身的步骤都未被证明,这里也没有声称 /init-project 经过端到端运行。