谁都逃不过迷路
我敢说,所有开发者都有过这样的体验,代码跳来跳去就迷路了!
就算是对项目的基本原理有充分了解之后,仍然会产生这样的感觉!比如,Mybatis 的原理非常简单,大致就是三个步骤,"函数参数映射成SQL"、"执行 SQL"、"把执行结果映射成 Java 对象",很多开发者都知道,但如果要想去看懂 Mybatis 源码,仍然有一定难度。而如果是 Netty 这种异步多线程的项目,则更难了。
这说明代码有着其内在的深刻复杂性,不是看几篇原理性的文章就能搞定的。
存在理想代码吗
当我们去评价一个代码时,通常会要求它满足以下特性:
- 高性能
- 稳定性
- 扩展性
- 可读性
那你发现没有,其它三个特性都是与"可读性"相冲突的!
Netty 不好懂,那是因为它运用了大量的异步来提升性能,抽象Handler和责任链模式来提升扩展能力,写了大量看似无用的代码来提升稳定性。这已经算是优秀的代码了,至少逻辑清晰。而企业内部的祖传代码,在众多参差不齐的堆砌之下,可能连命名规范、逻辑清晰都做不到了,那更是一个大大的灾难。
那么,XCodeMap 是怎么破解这个问题的呢?
首先,我们可以想象一下,一个理想的易于阅读的代码,应该是针对每个功能,按顺序写完流程,没有无关的分支,一步一步完成目标。
但我们上面分析了,真实的代码不会这么写,这一点我们暂时无法改变,那我们能否做到给代码增加一个阅读模式,让其尽可能地接近这种顺序特点呢?
XCodeMap 就是按照这种思路一步步演进出来的。
去除噪声
当我们想理解某个功能的代码实现时,会遇到大量无关的分支,有些是与其它功能复用造成的,有些是提升稳定性而必要的防御代码,但不管怎样,这些无关的代码,都形成了噪声,会给我们造成了巨大的干扰。
在这个问题上,测试覆盖率组件 JaCoCo 给了我们很多的启发。如果执行一个请求,然后把覆盖的代码分支记录下来,那未覆盖的代码分支自然就去掉的了。这个想法,非常简单,但却十分有效。
现在打开 XCodeMap,左侧行号栏那里的 X 标记,就是代码覆盖标记。

看上图,请求的执行流程,到底是走的哪个分支,一目了然。
缩短记忆间隔
经常调试源码的小伙们,肯定会有这样的体验,某个关键位置未打断点,而导致请求要重新触发一次,等到一番折腾之后,可能已经忘记,之前的思路走到哪了,接下来要看什么。
这就是典型的代码复杂性遭遇人脑记忆限制的结果。
而解决的办法也很简单,那就是缩短记忆间隔!具体来讲,就是无需断点,随时查看任意函数的输入与输出。
XCodeMap 记录代码覆盖情况的时候,顺带记录了每个函数的输入输出数据。这些数据给行号 X 标记注入了灵魂,你只需点击一下它,就可以恢复出完整的调试现场。

熟悉的面板,类似于 Idea Debug,但信息更加丰富。整个数据都是存储下来的,不需要再次触发请求,就可以查看任意代码位置的执行详情。
用数据存储代替人脑记忆,大大减少了人脑的记忆负担和认知压力。你只需要,静下来,慢慢看,大部分情况都能轻松搞定。
除非你遇到了链路的断裂!
谁破坏了链路
回到我们最开始表达过的一个理念,最好读的程序,就是按照顺序一步步写下来的程序。这种程序的特点就是,任何数据对象,都是实时构建,以便我们可以直接看到其执行过程。
而在一个真实的程序中,有些步骤满足这种"顺序特性",有些不满足。
举个例子,当我们阅读 MyBatis 源码时,使用 XCodeMap 顺着入口可以很快找到"函数参数映射成SQL"、"执行 SQL"、"把执行结果映射成 Java 对象"这些过程,这些过程都是满足"顺序特性"的,顺着链路走就可以搞懂。
但这些过程依赖一个关键动作 getMappedStatement,我们去走读它时,却发现它来自于一个 HashMap,这是一个预先构建好的集合,顺着这函数走读,无法了解到 MappedStatment 的构建过程。
也就说,getMappedStatement 破坏了我们预期的"顺序链路",自然就带来了阅码的困难。
除了"预构建",还有 "异步" ,也会破坏"顺序链路"。
比如,当我们阅读 Netty 源码时,顺着 Channel.writeAndFlush 走读时,会发现对象直接被放到了某个队列里,无法了解到其真实的写入过程,这同样会带来阅码的困难。
那么,对于这种问题,有什么破解思路呢?
XCodeMap 的答案是全链路追踪。
全链路追踪
这一思路基于一个基本的观察,不同的链路之间,是通过数据对象来进行衔接的。
当我们全链路追踪 MappedStatement 对象的轨迹,包括它的构建、传递、使用过程,生成一个明细列表,类似如下的结果:

顺着这个追踪结果,可以很容易找到 MappedStatement 对象的构建和传递过程。
Netty 的过程也类似,通过追踪对象的轨迹,可以连接被破坏的链路。
浏览轨迹
作为一个辅助认知的工具,可视化是一个必不可少的功能。
但 XCodeMap 仍然做出了一些努力,只因一个程序的函数调用千千万,序列图无法展示得下,提供一个特别的按钮,把我们关心的节点,也就是浏览轨迹,给展示出来,可以快速帮我们进行回忆总结。

AI 与 未来
AI 生成代码越来越多,这是不可逆的大势,但这并不意味着程序员的效率就大大提升了。某车厂老板在采访中表示,公司全面采用 AI 之后,写代码时间平均减少了 22 %,但其它工作增加了 22%,整体效率几乎没有提升。
这所谓的"其它工作",就是阅读和调试的时间。代码是一块块生成的,大部分开发者的调试却还在一行行 Debug,这个效率自然比较低。
未来的程序员,其核心能力,将不再是编码能力,而是编码前的设计能力和编码后的调试能力。
设计能力需要阅读大量的优秀项目才能提升,调试能力需要趁手的工具才行。不论哪一种,XCodeMap 都致力于成为开发者最喜欢的工具!