☰
代码仓库秒变架构图:Archify 从源码自动生成代码地图的完整实践
2026/9/28 17:48:10 网站建设 项目流程

接手一个陌生代码仓库的第一周,大部分人都干过同一件蠢事:打开仓库根目录,看到十几个子目录、上万行代码,然后决定从 README.md 开始读,读完了才发现 README 是五年前写的,架构早就不一样了。我经历过三次类似的事情,最后得出的结论是——与其直接埋头啃代码,不如先拥有一张"代码地图"。

这里说的"代码地图",就是标题里的 Archify 这类工具干的事:把整个代码仓库丢进去,几十秒自动生成一张架构图。它不是 UML 类图,也不是在 Visio 里手动拖拽出来的那种系统蓝图,而是直接从仓库真实代码里反推出"系统有哪些模块、谁依赖谁、整体分几层"的高层视图。Archify 本身支持本地仓库扫描,也能直接接 GitLab、Gitee 这类远程代码仓库,属于"代码仓库秒生架构图"这个赛道里比较有代表性的工具。

这篇内容适合谁读?如果你跟我一样,经常接手老项目、要给微服务梳理依赖、带团队做架构评审,或者只是希望自己手上的仓库不再是黑盒,那 Archify 这套从扫描到出图、再到团队落地的完整玩法,你应该用得上。下面我会从它解决的问题、底层原理、实际操作、常见翻车点,一直讲到怎么把它放进团队协作流程,全程都是我自己实际跑过的流程和踩过的坑。

1. 为什么需要"代码地图":先搞清楚它解决的是哪个问题

1.1 一个真实的新人上手场景

我团队里有个刚入职两个月的开发,有次被分配去改一个老订单服务的 bug。他从 clone 仓库到开始动手改代码,花了整整一天半,其中大部分时间在干嘛?在"考古":打开一个包名,点进去,看几个类,回到入口,再跳到另一个服务,最后在群里问我"订单状态这个字段到底是在这边改还是那边改"。

这其实是常态。代码仓库的本质是大量不可见关系的集合,光靠文件和目录,你只能看到"有哪些零件",看不到"零件之间怎么咬合"。如果当时有一张自动生成的代码架构图,他要做的事就简单得多:先在图上定位订单服务,看到它依赖了哪些基础模块、被谁调用,再顺着边找到真正需要改的包。整个过程从"读源码猜结构"变成"按图索骥看实现"。

1.2 手工画架构图的三座大山

有人会说:"架构图这东西,我们团队有啊,用 Visio 画的,还有专门的架构图软件。"这就说到点子上了。我见过很多团队维护架构图的方式:每年画一次,放在 wiki 里吃灰。手工作图这件事,至少有三个绕不过去的坑。

第一是时间成本。你不把代码读明白是画不出正确架构图的,而"读明白"恰恰是整个流程里最贵的事。拿 Visio 根据 Excel 生成组织架构图来类比:前提是你已经把人员结构整理成了数据;而代码架构图的前提,是把几万行代码的真实依赖关系整理成数据,这份名单本身就是巨量工作。大部分团队根本收集不起这份数据,所以图只能靠架构师的记忆硬画。

第二是失真速度。代码每周都在变,架构图不一定。上个月还是标准三层架构,这个月因为一个紧急需求插了个旁路模块,图还是老样子。三个月后新人照着旧图定位问题,跟对着五年前的 README 一样不靠谱。很多人问"总体架构图怎么画",我的答案通常很扫兴:先放弃手画,让代码自己诚实交代。

第三是主观性。同一个仓库,让两个人分别画架构图,画出来的模块边界大概率不一样,因为每个人对"高内聚"的判断标准不同。谁画的图,后续就只能靠谁解释,这个人一离职,图基本就废了。架构图这门 skill,真正的难点从来不是"画",而是"准确理解代码并转成结构化关系",这一步恰恰最适合自动化。

1.3 代码地图是什么,不是什么

要理解 Archify 这类工具,先得把它和常见的类图、组件图区分开。Archify 生成的不是 UML 类图——它不会把每个类的属性和方法都画出来,那样在大型仓库里只会变成一团乱麻。它生成的是"模块级"架构图:一个服务、一个包、一个聚合根级别的模块作为节点,节点之间用有向边表示依赖关系,再按逻辑或运行时的层次做布局。

打个比方:类图是城市里每栋楼的户型图,代码地图是整座城市的路网图。你要找一个具体房间,确实需要户型图;但你要想搞清楚"从哪儿走到哪儿、先经过哪个片区",路网图才是能用的东西。Archify 做的就是自动测绘路网,并且这份路网永远和真实街道一致,因为它的数据来源就是代码本身。

2. Archify 的工作原理:从源码到架构图的完整链路

2.1 第一步:识别语言和项目骨架

Archify 拿到一个仓库之后,第一件事不是读代码,而是"认门"。它会根据根目录的特征文件判断这是什么类型的项目:有package.json是 Node 项目,有pom.xml或build.gradle是 Java 项目,有go.mod是 Go 项目,有requirements.txt或pyproject.toml是 Python 项目。同时它会扫描整体目录结构,识别出约定俗成的代码组织方式,比如 Maven 的src/main/java、Go 的cmd和internal分层、前端项目的src/pages这类约定。

这一步还会顺带做一件关键的事:把第三方依赖和自家代码分开。node_modules、Python 虚拟环境里的 site-packages、本地 Maven 仓库,这些都不算"地图"上的节点,否则整张图会被几万个第三方包淹没。它只关注"你自己的代码"之间的依赖关系,外部依赖会被折叠成边界上的一个小标签,告诉你这个模块引入了哪些外部能力。

2.2 第二步:静态分析提取依赖关系

核心环节是静态分析。Archify 会为每种支持的语言拉起对应的解析器,把源码解析成抽象语法树(AST),然后从 AST 里提取"谁引用了谁":

  • Java 的 import 语句、包路径、类型引用关系,以及 Spring 这类框架的注解(@Service、@Controller、@Repository);
  • JavaScript/TypeScript 的 import/require 语句,外加路径别名(如@/utils)的解析;
  • Go 的 import 与包路径引用;
  • Python 的 import 语句,包括相对导入。

除了直接的 import,Archify 还会做一层"函数级调用分析",把入口方法一路追踪下去,看它实际调用了哪些业务模块里的方法,从而补出那些"没有直接 import、但通过框架路由串起来"的调用关系。比如 Spring 里 Controller 调 Service、Service 调 Mapper,这种关系是理解业务架构的关键,静态分析会结合注解和配置一起处理。

需要说明的是,纯静态分析天然有盲区:动态 import、反射调用、SPI 加载、字符串拼接出来的类名,这些是它"看不见"的。后面我会专门讲这些盲区怎么补,这里先记住一个结论:代码地图的价值是"八九不离十 + 自动更新",而不是"字节级精确"。

2.3 第三步:模块聚合,从类到包再到子系统

解析出来的原始关系是"类到类"级别的,数量动辄上千个节点,直接画出来没法看。所以 Archify 会做聚合,这一步最见功力。它的聚合规则大致有三类。

一是目录边界聚合。按包名和目录把类归成模块,同一个目录或顶层包里的类默认是一个模块,除非内部有明显再分层。二是框架约定聚合。Java 后端里controller、service、mapper/repository是天然的逻辑层,聚合之后再分层编排,出图时从上到下就是 Controller -> Service -> DAO 的经典三层。三是行为相关性聚合。两个类虽然不在同一个包,但其中一个被另一个高频引用、存在强调用关系,算法会把它们"拽"到一起,避免出现两个模块之间几十条交叉引用的混乱局面。

聚合之后,工具会重新计算模块之间关系权重,并顺手完成循环依赖识别:A 依赖 B、B 又依赖 A。这类结构在图上会用醒目颜色标出,因为它往往是后续重构的重点区域。

2.4 第四步:布局算法与渲染

关系数据算出来了,最后一步是把图"画出来"。这里用的是图布局算法,常见的是分层布局(layered layout)和力导向布局(force-directed layout)的组合:先按逻辑层把模块归到不同泳道,再在泳道内部根据依赖权重做力导向排布,让关系密的节点挨得近、关系疏的隔得远。

真正的 Archify 出图不是一张静态大图,而是支持缩放的交互式画布。不同的放大层级,看到的粒度不同:最上层是服务/子系统视图,往下钻一层是模块视图,再往下是包视图。你也可以选中一个模块,只看它"依赖了什么"和"被谁依赖",这就是地图上的"高亮街区"。渲染完成后可以导出 SVG、PNG 或者 JSON 关系数据,方便放进文档或做二次分析。

3. 实操:把一个真实仓库变成架构图的完整流程

3.1 环境准备与仓库接入

Archify 的典型使用方式有两种:连接远程仓库和扫描本地目录。远程仓库方面,目前主流的 GitLab、Gitee、GitHub 都支持接入,方式是在设置里添加个人访问令牌(Personal Access Token),把仓库授权给 Archify。如果你习惯把代码推到 Gitee 管理,思路完全一样:Gitee 上开一个 token,在 Archify 里通过 token 导入仓库,之后每次 push 新代码,它可以自动触发重新扫描,保证图上反映的是最新状态。

本地扫描更直接,适合不想把代码传给第三方服务的团队。我自己通常先用本地模式做验证:

# 安装命令行工具(不同版本命令略有差异,以官方文档为准) npm install -g @archify/cli # 进入仓库根目录并初始化 cd ~/projects/order-service archify init # 执行扫描并生成架构图 archify scan . --out ./archify-output

如果你是先本地开发再推到 Gitee 的节奏,流程也很顺:git push推送到远程仓库之后,在 Archify 控制台选择该仓库,点一次"扫描"即可。对一个中型仓库来说,首次全量扫描通常在几十秒到几分钟之间,起手速度确实对得起"秒生架构图"这个说法。

3.2 第一次扫描前的关键配置

很多第一次用的人上来就archify scan .,然后发现生成的图乱七八糟、什么都看不清。问题多半出在没做配置。Archify 会在初始化时生成一个archify.yml,我建议你至少改这几个字段:

project: name: order-service languages: [java] scan: ignore: - "**/test/**" - "**/target/**" - "**/generated/**" entryPoints: - "src/main/java/**/controller/**" aggregate: maxNodes: 60 groupBy: ["packagePrefix"]

这里面我最看重ignore。测试代码、构建产物、自动生成的代码,对架构分析来说都是噪声,不忽略掉它们,图里会多出一堆不属于业务架构的节点。maxNodes控制聚合颗粒度:节点太多就提高聚合层级,节点太少就降低。这个参数值得多试几个值,直到图上恰好能一眼看全又不损失关键信息。

提示:代码地图追求的不是 100% 还原,而是"主要依赖不遗漏、架构趋势不错位、信息始终新鲜"。想通这一点,很多边角细节就不会纠结太久。

3.3 怎么读懂生成的架构图

图生成了,怎么读是关键。我习惯按三步走:先看分层,再看依赖走向,最后找异常点。

第一步看布局。Java 后端服务呈三层排列很常见:最上层 Controller 接 HTTP 请求,中间 Service 处理业务,下层 Mapper/Repository 访问数据库,最下面往往挂着 Redis、MQ、外部 API 这类基础设施节点。如果你发现某个模块明明叫util,却被画在顶层,说明它被 Controller 直接引用了,这里往往藏着分层违规。

第二步看依赖走向。从任意模块点进去,看出边(它依赖谁)和入边(谁依赖它)。入边很多说明它是被大量复用的基础模块;出边很多说明它是聚合入口或"上帝模块"。一个健康的模块依赖数量应当可控,出边别超过十个,超过就怀疑职责过重。

第三步找异常点。循环依赖标红的优先处理;孤立节点(没有任何依赖关系的模块)多半是死代码;"所有边都指向它一个"的模块就是架构上的单点瓶颈。这三类问题,手工读代码往往要好几天才能发现,一次扫描就全标出来了。

3.4 导出与维护

出图之后,我强烈建议把它当成一等公民来维护。Archify 支持导出 SVG、PNG 和 JSON。SVG 可以保持清晰度嵌进团队 Wiki 或 README;JSON 关系数据则可以喂给其他分析脚本做二次处理。

维护节奏有两种。手动模式:每次发布前在 CI 里跑一次archify scan,把生成结果和上一次做 diff,重点看有没有新增的循环依赖或不合理依赖。自动模式:接入远程仓库,每次 push 后自动重新扫描,架构图永远和主分支同步。

实测下来,自动模式省心得多。人工维护的架构图活不过三个月,自动生成的图才可能真的被团队用起来。

4. 翻车现场:我用 Archify 踩过的坑和解决办法

4.1 扫描慢得像蜗牛:先查这三处

我试过一个接近上百万行代码的 Java 老仓库,第一次扫描跑了快四十分钟,一度怀疑工具坏了。排查下来是三个原因叠加:一是没有配置 ignore,把几个generated-source目录和测试代码全扫进去了,这部分占了至少一半时间;二是分析器默认开启函数级调用追踪,对巨型仓库是很大负担;三是没开增量扫描,每次都是从零开始全量解析。

解决办法对应三条:把构建产物、生成代码、测试代码全部加进 ignore;函数级追踪只对入口模块开启,其余走 import 级别快速分析;接入远程仓库后开启"仅扫描变更文件"模式。调整完之后,同样这个仓库的增量扫描压缩到一分钟以内。

4.2 依赖爆炸,图变成一盘意面

另一个常见问题是依赖关系太多,图上全是密密麻麻的线,节点之间互相交叉,完全失去可读性。这通常是聚合参数没调好:模块边界切得太细,把同一个业务域拆成十几个小模块,彼此大量互相引用;或者循环依赖太多,算法为了把这些循环关系画出来,不得不拉出无数条边。

解决思路是先合并、再过滤。把maxNodes调小,强制模块聚合成更大粒度,比如把user-service下的多个包合并成一个user模块,线上数量立刻降下来。再开启"边权重过滤",只显示权重超过阈值的依赖边,那些个别的一次性调用不画,图上立刻清爽很多。

依赖爆炸本身也在说明架构有问题,别只顾着调图——它提示你该做模块间解耦了。

4.3 多语言仓库和微服务仓库怎么处理

现在很多仓库是前后端同仓或多语言混合:Java 后端 + TypeScript 前端 + Python 脚本。Archify 对多语言仓库是逐个语言分别分析,再通过"共享节点"拼到一起。比如同一个 API 路径,后端是被调用方、前端是调用方,工具会根据接口定义或者手动规则把两边连起来。

微服务场景更复杂一点。我的做法是把各服务仓库分别扫描,然后导出关系数据,在 Archify 里用"多仓库聚合"视图合并成一张服务级架构图。这张图上的节点是各个服务,边是服务间调用。如果服务间用的是 gRPC,proto 文件里的 service 定义就是现成的调用关系;如果用的是 REST,可能需要在配置里维护一份服务间调用清单。

聚合视图的价值在于,你可以第一次同时看到十几个服务的完整拓扑:哪个服务被依赖得最多、哪些服务之间互相调用形成环,一目了然。这其实是很多人想要的"微服务架构图",而且是自动生成、随代码更新的,不是发布会前熬夜手绘的静态 PPT。

4.4 动态代码造成的误报和漏报

前面提到静态分析的盲区,实际使用时会真实碰到。最常见的场景:一个类不是通过 import 直接引用的,而是在配置文件里写死了类名,启动时通过反射加载(Spring 的@Bean动态注册、Java SPI 机制都属于这类)。Archify 对这类节点可能会漏,导致图上出现"失踪的依赖"。

另一种是相反方向的误报:两个类只是名字像,或者通过字符串拼接生成类名,静态分析把八竿子打不着的两个模块连在了一起,图上出现"幽灵依赖边"。

我一般是这么处理的:把图当作参考而不是唯一事实;遇到反射和动态加载场景,在 Archify 里手工补一条白名单依赖或者画一条"已知边";同时定期用运行时调用链数据(比如 APM 里的链路追踪)和静态图对照,两边一拼,盲区就小多了。

四种高频问题我整理成了一张速查表,排查时可以照着来:

翻车现象常见原因我优先检查的点
扫描极慢未设置 ignore、函数级追踪全开、未开增量ignore 列表、追踪开关、增量扫描
依赖爆炸聚合粒度过细、循环依赖过多maxNodes、边权重过滤、模块合并
多语言关系断裂各语言独立分析、缺少桥接共享节点配置、手动补边
反射/动态加载盲区静态分析看不到运行时行为手工依赖补充、运行时链路对照

5. 把代码地图放进团队协作:我总结的一套落地方法

5.1 新人 onboarding:先看图,再读代码

我后来在团队里定了一条规矩:新同学入职、接受仓库讲解之前,先花十分钟自己看一遍 Archify 生成的架构图,然后回答三个问题:系统分成几层?核心服务依赖了哪些基础模块?它调用了哪些外部依赖?答不上来再去看代码。

这套流程跑下来效果很直接:新人第一次上手改代码的时间,从原来的一天半缩短到大约小半天。他们不是不用读代码了,而是带着地图去读,读到每个类都知道"我现在在整条路上的哪个位置",而不是打开一个目录就开始猜。

5.2 架构评审与重构辅助:让问题可视化

代码地图最被低估的场景是架构评审。以前评审靠 PPT 和架构师的记忆,现在直接打开项目的最新架构图过一遍:哪个模块依赖数量超阈值、哪里出现循环依赖、哪些模块没人引用,全部在图上现场标注。评审从"听人讲"变成了"看数据说话"。

重构场景用得更多。我之前负责过一个支付服务老模块的重构,重构前先导出一份现状架构图的 JSON 数据,重构完成后再导出一份新的,两张图做 diff:哪些依赖被清掉了、哪些边界变清晰了,一目了然。这种"重构前后对比图"拿给领导和组员看,比任何文字汇报都有说服力。

5.3 让统计说话:代码量和注释率的补充视角

"代码仓库代码量和注释率统计"这类需求,其实和代码地图是很好的搭配。光看架构图,你能知道模块之间的依赖结构,但不知道每个模块的规模和维护状况。我会把两类数据放在一起看:某个模块被大量依赖、同时代码行数上万、注释率又很低,那它就是整个系统的"高危区"——所有人都在依赖一个没人读得懂的黑盒。

Archify 在导出架构图时,通常能顺带带出各模块的代码行数、文件数、注释率这类基础统计。我习惯在架构评审表格里把这三个指标一起列上,作为"这个模块是否值得优先重构"的量化依据。架构问题一旦跟规模数据挂钩,优先级排序就容易得多。

5.4 与文档、CI 的联动:让图活在流程里

最后一步是把它焊进日常流程。我的做法很简单:

  1. 在项目 README 顶部放一张最新架构图的链接或 SVG 预览图,旁边注明"本图由 Archify 自动生成,随 CI 自动更新";
  2. 在 CI 脚本里加一步archify scan,把生成的图作为构建产物上传到内部文档系统;
  3. 代码评审模板里加一条 checkbox:"本次改动涉及模块的依赖关系是否合理?是否存在新增循环依赖?"。

这套闭环跑起来之后,"架构图过期"这件事基本消失了。因为图的更新是自动的,旧图没有机会存在。团队对"系统整体长什么样"的认知,第一次真正意义上跟上了代码演进的节奏。这也是我理解中代码地图类工具最大的价值:它把架构这个原本靠人脑维护的东西,变成了和 CI 一样可靠的自动化资产。

最后再分享一个小技巧:新项目从第一天就用 Archify,体验比老项目半路接入好太多。老项目扫描出来的第一版地图往往千疮百孔,容易打击信心;新项目或刚做完大重构的项目,代码结构还规整,首图就很漂亮,大家看了有成就感,也更容易把"看图说话"的习惯坚持下去。如果你也是团队里那个经常被人问"这个东西在哪改"的人,建议先拿自己手里最大的那个仓库跑一次扫描,看看 Archify 画出来的第一张图,跟你脑子里对系统的印象差了多少——这个差距,就是团队里每个人每天都在付出的沟通成本。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询