资讯动态

架构即代码:用LikeC4实现动态、可维护的软件架构图

发布时间:2026/8/14 2:29:31 来源:尧图企业网站定制
1. 项目概述当架构图不再是“一次性快照”在软件开发的日常里架构图是个让人又爱又恨的东西。爱它是因为它能清晰地勾勒出系统的骨架是团队沟通、新人上手、技术评审的利器恨它是因为它太容易“过时”了。我们都有过这样的经历花了大半天用绘图工具精心绘制了一张架构图贴在Confluence或文档里没过两个月随着几次迭代发布系统早已面目全非而那张图却成了“历史文物”不仅失去了参考价值甚至可能误导新人。维护它费时费力优先级永远排不上号不维护它就在那里尴尬地提醒着理想与现实的差距。这就是为什么当我第一次接触到LikeC4这个项目时有种眼前一亮的感觉。它不是一个画图工具而是一个基于代码生成架构图的建模语言和工具链。它的核心思想是架构即代码。你不再需要手动拖拽图形而是像写配置一样用结构化的文本DSL来描述你的系统组件、它们之间的关系以及部署环境。然后LikeC4 会自动将这些描述渲染成清晰、美观的架构图并且是可交互、可分层、可过滤的动态视图。最吸引人的一点是既然架构描述是代码那么它就可以和你的业务代码一起被纳入版本控制系统如 Git进行管理。每一次架构的变更都对应着一次代码的提交和一次架构图的重绘。架构图从此不再是静态的“快照”而是随着代码一起“进化”的活文档。目前这个项目在 GitHub 上已经收获了超过 4.4K 的 Star这背后反映的正是广大开发者对“架构图维护之痛”的共鸣以及对“文档即代码”这一理念的深度认同。2. 核心设计理念与方案选型解析2.1 为什么是“架构即代码”在深入 LikeC4 的具体语法之前我们有必要先理解它背后的设计哲学。传统的架构图绘制无论是用 Visio、Draw.io 还是 Miro本质上都是“所见即所得”的图形编辑。这种方式灵活直观但存在几个根本性问题难以维护任何微小的架构变动都需要人工找到对应的图形元素进行修改极易遗漏或出错。难以复用一个组件在多个视图中出现时需要重复绘制一致性难以保证。缺乏语义图形工具不知道你画的方框是“用户服务”还是“数据库”它只是一个方框。这导致无法进行基于语义的查询、过滤或分析。无法集成静态图片很难与 CI/CD 流水线、文档生成工具链深度集成。“架构即代码”正是为了解决这些问题。它将架构元素组件、关系、边界抽象为具有明确类型的代码实体。这样做带来了几个显著优势版本化与可追溯性架构变更历史清晰可见谁在什么时候为什么修改了架构一目了然。一致性保证同一个组件在系统的所有视图中其名称、类型、描述都是一致的。自动化生成通过脚本或 CI/CD可以自动为每次提交生成最新的架构图并嵌入到文档或发布说明中。多视图派生从同一份“事实来源”的架构代码中可以自动生成针对不同受众的视图例如给高管的系统上下文图、给开发者的容器部署图、给运维的基础设施拓扑图。LikeC4 的 DSL 设计得非常简洁它不试图描述系统的所有细节而是聚焦于C4模型的核心概念这使得它既保持了强大的表达能力又避免了过度复杂。2.2 LikeC4 与 C4 模型天生的搭档LikeC4 的名字就暗示了它与C4模型的紧密关系。C4模型是由 Simon Brown 提出的一种用于软件架构可视化的分层模型它通过四个不同抽象层次的视图来描绘一个软件系统系统上下文图Context最高层次展示系统与外部用户及其他系统的交互。容器图Container将系统分解为可独立运行/部署的“容器”如Web应用、移动端、数据库、消息队列等。组件图Component将单个容器进一步分解为内部的逻辑“组件”。代码图Code最底层展示组件内部的具体类、函数等代码结构通常由UML工具生成。LikeC4 完美地支持了前三个层次上下文、容器、组件它允许你定义对应于这些层次的元素并轻松地在不同视图间切换。它的 DSL 语法直观地映射了 C4 的概念例如你可以定义一个person对应C4的“人”一个system对应C4的“系统”或“容器”以及它们之间的-关系。注意LikeC4 并不强制要求你严格遵循C4模型的所有规范它提供了足够的灵活性。你可以用它来绘制非严格C4的架构图、部署拓扑图甚至是简单的流程图。它的核心价值在于“用代码定义关系并生成可视化”C4模型是其一个非常成功和自然的应用范式。2.3 技术栈与工具链选型考量LikeC4 本身是一个 TypeScript 项目它提供了核心的模型解析器和视图生成器。对于最终用户而言你主要通过两种方式使用它本地开发与实时预览这是最常用的方式。你需要安装 Node.js然后通过npm或yarn初始化一个项目安装likec4/core和likec4/cli等依赖。LikeC4 提供了类似 Vite 的开发服务器可以让你在编写.c4文件时在浏览器中实时看到架构图的变化体验非常流畅。集成到文档或CI/CD你可以使用 CLI 工具将.c4文件编译为静态的 SVG、PNG 或 PDF 图片也可以生成一个独立的、可交互的 HTML 页面。这个页面可以轻松地嵌入到你的 MkDocs、Docusaurus、GitBook 等文档站点中或者作为 CI 流水线的一个环节在每次构建时自动更新架构图资产。为什么选择这样的技术栈首先TypeScript 提供了优秀的类型安全这对于定义一套结构化的 DSL 模型至关重要能在开发阶段就捕获许多语法和语义错误。其次基于 Node.js 的生态使得安装和集成非常方便前端开发者几乎零成本上手。最后输出为 Web 可交互视图和静态图片兼顾了在线文档的体验和离线传播的需求。3. 核心语法与建模细节解析3.1 基础元素定义从“人”到“系统”LikeC4 的 DSL 文件通常以.c4或.c4d为后缀。让我们从一个最简单的例子开始定义一个系统上下文。// 定义外部角色 person user 终端用户 { description 使用我们Web应用的用户 } // 定义我们的核心系统 software system online_store 在线商城系统 { description 允许用户浏览和购买商品的Web应用 } // 定义关系用户使用在线商城 user - online_store 浏览商品下订单这段代码定义了三个核心概念person代表系统外部的参与者通常是用户或外部系统角色。software system代表一个你正在构建或分析的软件系统。在C4的上下文图中这就是你要描述的核心。-箭头定义了元素之间的关系方向从源指向目标后面的字符串是关系的描述。你可以为元素添加description、technology使用的技术栈如“Spring Boot”、“PostgreSQL”等属性这些属性会在生成的图表中作为提示信息显示极大地丰富了图表的信息量。3.2 层次化分解容器与组件上下文图描绘了系统边界接下来我们需要深入内部。使用container关键字可以将一个系统分解为多个可执行/部署的单元。software system online_store 在线商城系统 { description 允许用户浏览和购买商品的Web应用 // 将系统分解为容器 container web_app Web前端 { technology React, TypeScript description 提供用户界面的单页应用 } container api 后端API { technology Go, Gin框架 description 处理业务逻辑的RESTful API服务 } container database 主数据库 { technology PostgreSQL description 存储商品、订单、用户等核心数据 } container payment_provider 支付网关 external { technology 第三方HTTP API description 处理信用卡支付的第三方系统 } } // 定义容器间的关系 web_app - api 调用API使用HTTPS api - database 读写数据使用JDBC api - payment_provider 发起支付请求使用HTTPS注意payment_provider后面的external标记。这是一个标签Tag用于标记元素的性质。标记为external意味着这是系统边界外的元素LikeC4 在渲染时会用不同的样式通常是虚线边框来区分内外这非常符合C4模型的绘图惯例。更进一步我们可以使用component关键字在容器内部进行分解。例如将api容器分解为多个组件container api 后端API { technology Go, Gin框架 description 处理业务逻辑的RESTful API服务 component order_service 订单服务 { technology Go description 处理订单创建、查询、状态更新 } component product_catalog 商品目录服务 { technology Go description 管理商品信息、库存查询 } component auth 认证组件 { technology JWT, Go description 处理用户登录和请求鉴权 } } // 组件间的关系 web_app - auth 提交登录凭证 order_service - product_catalog 查询商品库存3.3 视图定义多角度呈现架构定义了所有元素和关系后如何生成我们想要的特定视图呢这就是view关键字的用途。视图允许你从完整的模型中“裁剪”出你关心的部分。// 定义一个“系统上下文”视图只包含顶级系统和外部角色 views { view context of online_store { title 系统上下文图 include * autolayout } // 定义一个“容器”视图聚焦于 online_store 系统内部的容器及其关系 view containers of online_store { title 容器图 - 在线商城 include web_app, api, database, payment_provider autolayout } // 定义一个更聚焦的视图只展示 API 容器的内部组件 view api_components of api { title API 内部组件图 include order_service, product_catalog, auth autolayout } }include *表示包含当前范围of online_store内的所有元素。在上下文视图中这会包含online_store系统和所有直接关联的person及外部系统。include web_app, api...显式列出要包含的元素可以精确控制视图内容。autolayout告诉 LikeC4 自动为视图中的元素排列布局。这是一个非常实用的功能你不需要手动指定位置工具会自动生成一个清晰、可读的布局。当然你也可以通过position属性进行手动微调。实操心得在实际项目中我建议将不同的视图定义在不同的.c4文件中或者使用import语句来组织模型。例如可以将所有基础元素定义在一个model.c4文件中然后将上下文视图、容器视图、组件视图分别定义在context.c4、containers.c4、components.c4中。这样结构更清晰也便于团队协作维护。4. 高级特性与定制化实践4.1 样式与主题定制让图表拥有品牌感默认的 LikeC4 图表风格干净专业但你可能希望让它匹配公司的品牌色或者对特定类型的元素如数据库、外部系统使用更醒目的图标。LikeC4 通过基于 CSS 的样式系统提供了强大的定制能力。你可以在项目根目录创建一个likec4.css文件来覆盖默认样式。例如/* likec4.css */ :root { --likec4-color-primary: #2c3e50; /* 主色调改为深蓝色 */ --likec4-color-secondary: #3498db; } /* 为所有标记为 database 的元素应用特定样式 */ [data-tags~database] rect { fill: #f1c40f; /* 填充色改为黄色 */ stroke-width: 3px; } /* 为所有外部元素添加特殊图标背景 */ [data-tags~external] { /* 这里可以引用一个背景图片或使用其他CSS技巧 */ background-image: url(data:image/svgxml,...); /* 内联SVG图标 */ }更强大的是你可以为元素直接指定style属性进行行内定制container database 主数据库 { technology PostgreSQL style { fill #27ae60 // 绿色填充 stroke #2ecc71 // 边框色 shape cylinder // 使用圆柱体形状表示数据库 } }shape属性支持多种预设形状如rectangle默认、cylinder数据库、folder、mobile、queue消息队列等这些视觉提示能让人一眼就认出元素的类型。4.2 动态视图与过滤应对复杂架构当系统非常庞大时一张图包含所有元素会变得难以阅读。LikeC4 的视图支持强大的过滤和动态聚焦功能。按标签过滤假设我们给所有微服务打上microservice标签给所有存储服务打上storage标签。container redis_cache Redis缓存 { technology Redis tags storage, cache } view microservices_view of online_store { title 所有微服务 include * // 包含所有元素 exclude [tags ! microservice] // 排除没有microservice标签的元素 autolayout }这样生成的视图就只包含微服务关系线也只会显示在这些微服务之间。聚焦特定元素focus指令可以突出显示与某个元素直接相关的元素隐藏其他无关部分。view focused_on_order of online_store { title 订单服务相关依赖 include * focus order_service // 聚焦于 order_service autolayout }这个视图会高亮显示order_service以及所有与它直接相连的组件和关系其他元素会以半透明或灰色显示。这在分析某个服务的上下游依赖时极其有用。4.3 与现有工作流集成LikeC4 的价值只有在融入开发生命周期后才能最大化。以下是几种常见的集成模式作为开发文档的一部分将.c4文件放在项目代码库的docs/architecture目录下。在项目的package.json中添加一个脚本{ scripts: { docs:build: likec4 build -o ./dist, docs:preview: likec4 preview } }开发者可以运行npm run docs:preview本地实时编辑和查看架构图。在构建文档站点时运行npm run docs:build生成静态资源并集成。CI/CD 自动校验与生成在 Git 的pre-commit钩子或 CI 流水线中可以加入 LikeC4 的语法校验确保提交的.c4文件没有语法错误。在发布流程中可以自动生成最新版的架构图并附加到 Release Notes 或部署公告中。与监控/可观测性平台联动进阶思路虽然 LikeC4 本身不提供此功能但它的模型数据是结构化的 JSON。理论上你可以编写脚本将生产环境中服务的真实健康状态如从 Prometheus 获取映射到 LikeC4 模型中的对应元素然后动态修改其样式如将宕机的服务标红生成一个“实时健康架构图”。这需要一定的定制开发但思路非常吸引人。5. 常见问题与实战避坑指南在实际引入 LikeC4 的团队中我观察到一些共性的问题和挑战。这里分享我的解决思路和避坑经验。5.1 问题一模型应该多细会不会变成另一种“代码注释”这是一个关于“度”的哲学问题。LikeC4 模型不是 UML它不应该追求事无巨细。我的经验法则是描述到能够清晰回答“这个系统/服务/容器的主要职责是什么它依赖谁谁依赖它”这个问题的程度即可。对于“容器”级别清晰定义其技术栈、部署方式和对外暴露的接口如API端点。对于“组件”级别描述其核心业务职责即可不需要深入到类和方法。如果一个“组件”内部逻辑非常复杂或许它本身就应该被提升为一个独立的“容器”微服务。避免过度设计不要一开始就试图建立完整的、覆盖所有细节的模型。应该从最重要的、最核心的系统上下文图和容器图开始随着项目演进当某个部分变得复杂到需要额外说明时再为其创建组件图。避坑技巧将 LikeC4 模型视为一种“活的设计文档”。在每次架构设计评审或重大重构之前强制要求更新对应的.c4文件。将更新架构图作为相关代码合并请求Merge Request的准入条件之一。这样能确保文档与代码同步的纪律性。5.2 问题二如何管理大型、多仓库项目的架构模型当一个系统由数十个甚至上百个独立的代码仓库微服务组成时将所有架构描述集中在一个 LikeC4 项目里会变得笨重。此时可以采用分布式模型。方案A每个服务维护自己的局部视图。每个微服务仓库的docs/目录下存放一个描述该服务边界的.c4文件。它定义自己这个“容器”以及它直接依赖的外部容器如数据库、消息队列、其他服务。它不试图描述整个系统。方案B使用一个中心化的“架构仓库”。创建一个独立的 Git 仓库专门用于存放全局架构模型。各个服务仓库通过 Submodule 或软链接的方式引用中心模型库中关于自己的那部分定义。中心仓库负责集成所有局部视图生成完整的系统级架构图。工具链支持LikeC4 支持import语句可以从其他文件导入定义。这为分布式模型提供了基础。你需要设计清晰的目录结构和命名规范避免循环引用和命名冲突。5.3 问题三自动布局autolayout结果不理想怎么办LikeC4 使用的自动布局算法通常是基于力导向图或层级布局在大多数情况下效果很好但对于特别复杂的图有时会产生交叉线过多或布局不直观的问题。第一步分层与分组。检查你的模型是否合理地使用了 C4 的层次。确保上下文、容器、组件视图是分开的。不要在容器视图里塞入组件级别的细节。清晰的层次是自动布局成功的前提。第二步手动微调位置。LikeC4 允许你为任何元素指定position。如果你对自动布局的某个部分不满意可以手动调整几个关键节点的位置然后重新打开autolayout算法会基于你固定的节点重新计算其他节点的位置。view my_view { include service_a, service_b, database autolayout position database at 500, 300 // 将数据库固定在坐标 (500, 300) }第三步简化关系。检查视图中是否包含了过多非直接的关系。有时隐藏一些间接的、非关键的关系线能让视图瞬间清晰。使用exclude或动态视图的focus功能来简化。5.4 问题四如何说服团队接受并坚持使用技术工具的成功一半在技术一半在“人”。推广 LikeC4 最大的阻力往往来自于改变习惯的惰性和对额外工作的担忧。从小处试点不要强迫整个团队立刻为所有系统画图。选择一个正在启动的新项目或者一个亟待理清架构的遗留模块由一两个对此感兴趣的工程师率先使用。展示即时价值在技术评审、新人 onboarding 会议中直接展示由 LikeC4 生成的可交互图表。演示如何通过点击过滤来查看特定服务的依赖如何随着代码提交历史回溯架构演变。让团队成员直观感受到“活文档”的威力。降低上手门槛编写一个极简的团队内部使用指南5分钟上手并提供几个经典的系统模板如“标准的Web后端服务”、“事件驱动微服务”。让大家觉得开始使用是一件很容易的事。将其融入流程如前所述将架构图更新作为设计评审和代码合并的准入门槛。当它变成开发流程中自然而然的一环时坚持就不再是问题。我个人在多个项目中推行 LikeC4 的体会是一旦团队度过了最初的学习曲线并尝到了架构图永远最新、且能自动生成的甜头就再也回不去手动画图的时代了。它不仅仅是一个画图工具更是一种促使团队更严谨地思考架构、更高效地沟通设计的工程实践。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价