de_DEen_USes_ESfa_IRfr_FRhi_INid_IDjapl_PLpt_PTru_RUvizh_CNzh_TW

深入剖析:理解C4代码图——它们是什么,何时具有价值,以及实用的PlantUML示例

什么是C4代码图?

代码图是第4层——西蒙·布朗C4模型中最深层、最详细的层级。

The Ultimate Guide to C4 Model Visualization with Visual Paradigm's AI Tools - ArchiMetric

它展示了:

  • 接口枚举记录,或其他实现特定组件(来自第3层)。

  • 关系这些类之间的关系(继承、组合、依赖、接口实现等)。

  • 关键设计元素例如组件内部应用的设计模式(如仓库、服务、DTO、领域实体、工厂等)。

实际上,这一层级几乎总是UML类图(或其简化变体),专注于一个(或极少数)组件。

重要说明:

  • 第4层是并非关于整个代码库。

  • 它并非并非需要展示每个类。

  • 它映射了仅关键结构理解一个复杂或关键组件实际构建方式所必需的。

  • 官方C4建议:理想情况下自动生成从源代码生成(通过Doxygen、Javadoc + UML插件、yWorks、Structurizr、CodeSee等工具),而不是手绘。

何时创建代码图

谨慎创建第4级图——仅在以下情况下:

  • 该组件是高度复杂任务关键,或难以理解仅从源代码难以理解(例如,复杂的领域逻辑、大量使用设计模式、加密流程、状态机、充满技术债务的遗留代码)。

  • 你正在一个高度监管的行业(金融、医疗、航空航天、国防)中,审计师或合规团队要求明确展示从架构→设计→实现的映射关系。

  • 重大重构逐步淘汰遗留组件,或引入新的架构模式(六边形、整洁、垂直切片、DDD聚合)——前后视图有助于传达变更。

  • 入职高级开发人员架构师需要快速理解高风险代码中不明显的内部结构的人。

  • 您已经投入了自动生成工具——因此维护Level 4的成本几乎为零。

  • 团队已同意“动态文档”在类级别上对这个特定子系统是有价值的。

当以下情况时,请勿创建Level 4图示:

  • 组件结构从良好的命名、较小的规模或清晰的代码中显而易见(大多数现代微服务属于此类)。

  • 您已经拥有良好的单元/集成测试清晰的接口,以及解释性注释.

  • 团队中的大多数成员可以轻松浏览代码。

  • 维护成本超过收益(手绘类图会很快过时)。

西蒙·布朗和大多数实践者强调:大多数团队根本不需要Level 4Level 1 + 2覆盖了80%到90%的沟通需求;Level 3处理了其余大部分情况。Level 4是例外,而非常规。

为何使用代码图示?(当它们带来价值时)

  • 连接架构 ↔ 实现——展示高层组件在代码中是如何实际实现的。

  • 阐明复杂的内部设计——揭示了设计模式(策略、工厂、装饰器、仓储)的使用、分层违规、紧密耦合或巧妙的领域建模。

  • 支持审计与合规 — 展示了架构决策是否在代码中得到贯彻。

  • 辅助重构与迁移讨论 — 前后类结构的对比使提案更加具体直观。

  • 减少“部落知识” — 帮助新任高级员工比阅读所有源文件更快地理解复杂部分。

  • 自动生成的版本成为“活文档” — 如果具备工具支持,它们几乎无需额外努力就能保持准确。

如何创建出色的代码图(分步指南 + 最佳实践)

  1. 选择一个组件 — 通常来自第3级图,其内部复杂性足以支持放大查看。

  2. 决定:手绘还是自动生成?

    • 手绘 → 仅用于工作坊、提案或自动工具难以处理的混乱区域。

    • 自动生成 → 推荐使用(仍可使用PlantUML对输出进行样式化/微调)。

  3. 聚焦核心要素 — 展示:

    • 关键类/接口

    • 重要关系(→ 依赖,— 组合,<| 实现,^ 继承)

    • 聚合体、实体、值对象(DDD风格)

    • 你希望突出的关键模式或反模式

  4. 保持简洁 — 最多8–15个类。如果更大 → 拆分为聚焦的图表(例如:“认证部分”、“订单处理实体”)。

  5. 最佳实践

    • 优先选择 自动生成 在可能的情况下(减少过时)。

    • 使用 PlantUML classDiagram 语法 — 清晰且可版本化。

    • 添加 注释用于非显而易见的决策(例如:“使用贫血领域模型——计划重构”)。

    • 避免显示所有内容—— 省略平凡的 getter/setter 和工具类。

    • 存储在代码仓库中 → 视为代码(将 .puml 文件与组件附近一起提交)。

    • 谨慎使用——每个复杂组件使用一次,而不是每个微服务都使用。

    • 与……结合使用动态视图(顺序图/协作图),当运行时流程比静态结构更重要时使用。

PlantUML 示例 – 认证组件(Big Bank plc 风格扩展)

以下是一个真实的 Level 4 示例,聚焦于安全 / 认证组件来自之前 API 应用程序的图表。

@startuml
title C4 Level 4 – 代码图:API 应用程序中的认证

skinparam monochrome true
skinparam shadowing false
skinparam class {
  BackgroundColor White
  BorderColor Black
  ArrowColor Black
}

abstract class AuthenticationProvider {
  + authenticate(credentials): Authentication
}

class JwtAuthenticationProvider {
  - tokenProvider: JwtTokenProvider
  - userDetailsService: UserDetailsService
  + authenticate(credentials): Authentication
}

class JwtTokenProvider {
  - secretKey: String
  - validityInMilliseconds: long
  + generateToken(userDetails): String
  + validateToken(token): boolean
  + getUsernameFromToken(token): String
}

interface UserDetailsService {
  + loadUserByUsername(username): UserDetails
}

class DatabaseUserDetailsService {
  - userRepository: UserRepository
  + loadUserByUsername(username): UserDetails
}

class UserRepository {
  + findByUsername(username): Optional<User>
}

class User {
  - username: String
  - passwordHash: String
  - roles: Set<Role>
}

class JwtAuthenticationToken << (T,orchid) Authentication >> {
  - principal: UserDetails
  - credentials: Object
  - authorities: Collection<GrantedAuthority>
}

' 关系
JwtAuthenticationProvider -up-> JwtTokenProvider : 使用
JwtAuthenticationProvider -up-> UserDetailsService : 使用
DatabaseUserDetailsService .up.|> UserDetailsService
DatabaseUserDetailsService --> UserRepository : 使用
UserRepository --> User : 返回

JwtAuthenticationToken .up.|> Authentication

note right of JwtAuthenticationProvider
  JWT 无状态会话的主要认证流程
end note

note bottom of JwtTokenProvider
  使用 HS512 签名和验证 JWT
end note

@enduml

这个小型图表:

  • 仅关注认证的内部实现

  • 展示关键类、接口和依赖关系

  • 突出显示设计模式(提供者、仓库)

  • 使用注释提供上下文

粘贴到任意 PlantUML 渲染器中——根据你的领域进行自定义(例如,将 JWT 替换为 OAuth2,添加 MFA 类等)。

总结提醒:Level 4 功能强大,但罕见。应有意识地使用,优先选择自动生成,永远不要让它变成繁琐的工作。C4 的大部分价值来自 Level 1–3。愉快地(有选择地)建模吧!

资源