如何让“学源码”变得轻松、有意义

大家好,我卡颂。

程序员与其他行业有个很大不同 ------ 这行很多极有价值的资料都是开源的。

这意味着你只要肯学,就能变强。

很多同学都知道学源码的重要性,但由于如下2个原因,很少有人能坚持啃下一些优秀的源码:

  1. 源码难懂

这里的难懂,除了核心功能本身代码复杂外,还有个因素 ------ 附加功能的代码会干扰我们学习核心功能的代码。

  1. 学起来没意义

功利地讲,一些与工作息息相关的库的源码(比如ReactVue)学完后尚且可以在简历中体现。

但大部分库的源码,学完就完了。

即使你照着源码写一个一摸一样的库出来,也没有实际意义,因为不会有其他人用。

对于"缺少意义的事",动力自然没那么足了。

综上两个因素,难学 + 没意义,能坚持下来的人自然就少了。

本文将向你介绍一种全新的源码学习方式,能够巧妙突破以上两个卡点,让你轻松、有意义感的学源码。

两个核心理念

这种源码学习方式包含两个核心理念:

  1. AI驱动:我们先让AI完整理解源码,再让AI作为老师教我们学源码,完美突破难学的卡点

  2. 语言转换:有了AI的加持,我们可以学习不会的语言编写的源码

举个例子,你只会JS,但可以选一个Rust写的库作为学习目标。

这样做有两个好处:

  1. 有大量优秀的库是用你不熟悉的语言写的,如果只局限在会的语言写的库,会错失很多开源宝藏

  2. 照着目标语言写一个你会的语言实现的同功能库是有实际意义的,因为可能还没有人用你会的语言实现过这个库

准备工作

我们需要借助两个工具的帮助:

  • Cursor

  • Code2Prompt

Cursor是什么

Cursor是一款AI驱动的IDE,由于他是在VSCode基础上魔改的,所以如果你之前用的是VSCode,可以一键迁移配置。

截止24.9.18,Cursor提供了15天试用,试用到期后换个新邮箱就能继续试用。

如果你用的GMail,甚至不用换邮箱,修改邮箱别名即可。

PS:可能有同学觉得白嫖不好,但Cursor团队留下这么明显的"漏洞",可能也是为了推高DAU,进而推高估值

Cursor本身只是工具,核心的AI辅助功能还得交给具体的大模型实现。

本文介绍的源码学习法需要用到Claude-3.5-sonnet-200k模型,他不仅有优秀的代码理解能力,更重要的是,上下文最大支持200k。

极限工况下,他能一次性理解"包含大概1.6w行代码的项目"。

当然,越接近上下文上限,理解能力衰减越快。经过我的测试,代码量9k行以内的项目比较合适。

Code2Prompt是什么

虽然Cursor默认会为项目启用RAG,也就是说,你对项目中任何代码进行提问时,Cursor都会将与代码相关的内容加入提示词中。

这能让AI的回答更有针对性,显得更懂项目。

但这种方式的底层依赖分词,如果分词效果不佳,对AI最终回答的质量影响很大。

举个例子,下面的代码是个完整的函数调用:

js 复制代码
const embeddings = new OllamaEmbeddings({
  model: "mxbai-embed-large",
  baseUrl: "http://localhost:11434",
});

如果分词成了两个document

js 复制代码
// document1
const embeddings = new OllamaEmbeddings({
  model: "mxbai-embed-large", 

js 复制代码
// document2
  baseUrl: "http://localhost:11434",
});

那么,当提问与OllamaEmbeddings相关的内容时,document2就不会作为相关上下文 出现在提示词中,AI就不知道baseUrl的存在。

但显然,baseUrl是与OllamaEmbeddings有关的。

所以,要让AI理解项目,最好的方式是 ------ 在token限制内,尽可能将如下信息都给到AI:

  • 项目的背景(README.md)、工程信息(package.json)

  • 目录结构

  • 每个文件对应的代码

可以使用Code2Prompt这个库实现上述功能。

这是个Rust写的库,可以通过cargo安装:

sh 复制代码
cargo install code2prompt

使用方式也很简单:

sh 复制代码
code2prompt 项目路径

执行命令后,上述提到的信息就会被复制到剪贴板。

举个例子,我对code2prompt项目仓库执行上述命令后得到的提示词中,目录结构部分如下:

包含code2prompt项目完整信息的提示词只有3k行,完全可以被Claude-200k理解。

接下来,我作为不会Rust 的人,展示下如何学习code2promptRust写的)源码,并最终输出一个node版本的code2prompt

实践 ------ 基础部分

首先,我们执行如下命令获得包含code2prompt项目完整信息的提示词

sh 复制代码
code2prompt code2prompt项目所在路径

这里你可以选任何"代码量符合标准"的项目

接下来,在Cursor中,按Shift + cmd + L打开AI侧边栏,选择Long Context Chat模式,这会使用200k的Claude3.5模型。

将上述3k行的提示词输入后,Cursor尝试理解项目:

Cursor的回复中我们可以大概知道项目的实现原理并区分核心功能与附加功能。

比如,可以明显看出如下几个功能是附加功能:

  1. 结果包含git diff信息

  2. 计算结果的token数量

  3. 支持不同输出形式(剪贴板、文件)

  4. 支持添加行号

当剔除这些附加功能后,我们可以让Cursor我们熟悉的语言创建项目并实现核心功能。

相比原始的code2prompt项目,当前Cursor生成的项目:

  1. 使用我熟悉的Node,而不是Rust编写

  2. 剔除了附加功能,只保留核心功能,代码一目了然

到这一步,学源码已经很简单了,但还能更直观一点 ------ 我们可以让Cursor根据flowchart DSL规范,根据代码逻辑生成流程图:

flowchart.js是一款轻量的流程图应用,可以将flowchart DSL渲染为流程图。

code2prompt举例,Cursor生成的DSL数据如下(你不需要理解这个数据,大概感受下他的格式就行):

ini 复制代码
st=>start: Start
e=>end: End

op_parse_args=>operation: Parse command line arguments
(program.parse())

cond_path=>condition: Valid path provided?

op_traverse=>operation: Traverse directory
(traverseDirectory())

op_git_diff=>operation: Get Git diff
(getGitDiff())

cond_diff=>condition: --diff option?

op_prepare_data=>operation: Prepare template data

op_render=>operation: Render template
(renderTemplate())

cond_output=>condition: -o option?

op_write_file=>operation: Write to file
(fs.writeFile())

op_console_log=>operation: Log to console
(console.log())

op_count_tokens=>operation: Count tokens
(countTokens())

cond_tokens=>condition: --tokens option?

op_log_tokens=>operation: Log token count
(console.log())

st->op_parse_args->cond_path
cond_path(yes)->op_traverse
cond_path(no)->e

op_traverse->cond_diff
cond_diff(yes)->op_git_diff->op_prepare_data
cond_diff(no)->op_prepare_data

op_prepare_data->op_render->cond_output
cond_output(yes)->op_write_file->cond_tokens
cond_output(no)->op_console_log->cond_tokens

cond_tokens(yes)->op_count_tokens->op_log_tokens->e
cond_tokens(no)->e

flowchart可视化网站粘贴上述DSL,可以得到如下流程图:

通过流程图,你可以清晰知道核心功能是如何实现的(精确到方法调用)。

当了解核心功能的实现原理后,你可以尝试运行代码,代码大概率无法一次跑通。

这时候只需要将报错信息提供给Cursor,他就会修改代码尝试帮你解决问题。

这一过程也能进一步加深你对源码的理解。

实践 ------ 进阶部分

如果你不满足于只了解"核心功能是如何实现的",接下来还有很多玩法,比如:

  • 在AI帮助下,继续实现附加功能(比如计算结果的token数量

  • 将语言由JS改为TS

  • 让AI为你生成测试用例

同样,以上改动不一定能一次跑通,反复修正的过程也是加深学习的好方法。

总结

本文介绍了一种源码学习方法 ,适合总代码量低于9k行的项目

具体步骤包括:

  1. Code2Prompt将项目重要信息汇总为一条提示词

  2. Cursor中使用Claude3.5-200k处理提示词

  3. 让AI帮你分析项目的核心功能、附加功能

  4. 让AI帮你重新实现核心功能,并生成核心功能流程图

  5. 根据代码和流程图学习项目工作原理

  6. 进阶部分:在AI帮助下,补足、增强项目

最终,你不仅学会了项目源码,还收获一个独属于你的项目。

虽然当前这种方式只能用来学习9k行代码内的项目,但是:

  1. 对于代码量超标的项目,可以按功能拆分,用该方法先分析子功能,农村包围城市

这种方式对MonoRepo形式的大项目尤其适用。

  1. 未来大模型的推理能力、上下文大小会持续提高

所以,这会是一种长期有效,且越来越有效的源码学习方式。

在践行AI驱动学源码过程中,我还发现一个硬件上的趋势 ------ 由于需要频繁与AI交互,笔记本自身屏幕可承载信息太少,能满足如下条件的外接屏或将成为刚需:

  1. 合适的显示比例(承载更多信息)

  2. 恰到好处的自适应设置

合适的显示比例

要保持AI与代码频繁交互,需要保留:

  • 右侧AI交互区域(用于与AI对话)

  • 底部Terminal区域(用于提取报错信息输入给AI)

这些区域会挤占编码区域,传统16:9的4k屏其实更适合看视频而不是编码这样的向下滚动的场景。

对于编码场景,3:2的屏幕比例更适合。

市面上基本只有明基RD280U这样的编程专用屏才满足这样的比例。

恰到好处的自适应设置

屏幕的核心功能归根结底还是显示,再详细点说就是:

  1. 内容清晰

  2. 护眼

作为编程专用屏,明基RD280U有针对代码显示的专业模式。

开启后,代码会刻画的更清晰,背景也会变得更柔和。

下图是明基RD280U开启深色代码主题防蓝光后,与Macbook Pro的视网膜屏的对比:

护眼 上,明基RD280U也有很多创新,比如:

  1. 屏幕自带可调节的背光光圈

即使夜晚室内完全不开灯,靠光圈的照明效果就足够了:

  1. 屏幕有抗反射涂层,阳光直射也不会看不清屏幕

这些功能配置起来会不会很麻烦?完全不会。

屏幕自带光线传感器,当开启昼夜模式,屏幕参数(比如亮度、蓝光等级)会随着光线变化自动调节,做到完全无感。

对于有自定义需求的高阶用户,屏幕配套了控制软件Display Pilot 2,你可以根据使用习惯自定义工作流。

在什么时间段设定什么屏幕参数、打开什么应用这些都可以控制。

有了这些恰到好处的自适应设置,明基RD280U看一天眼睛也不会疲劳。

相信随着AI驱动编程越来越普及,这款外接屏的热度也会越来越高。

相关推荐
学不会•1 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
活宝小娜3 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点3 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow3 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o3 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
开心工作室_kaic4 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
刚刚好ā4 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
沉默璇年6 小时前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder6 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_882727576 小时前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架