“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
认知负荷才是关键:软件设计的根本度量
软件设计的核心目标是降低认知负荷,而非追逐教条式的最佳实践。
引言:为什么大多数最佳实践都失败了
技术圈充斥着各种流行语和最佳实践,但其中大部分最终都失败了。它们失败的原因在于:这些理念是被想象出来的,而非基于真实世界的事实。它们建立在美学偏好和主观判断之上,而非客观规律。
我们需要更根本的东西——某种不可能出错的度量标准。
当我们在阅读代码时感到困惑,这种困惑会直接转化为时间和金钱的浪费。困惑的根源是什么?是高认知负荷。这不是什么玄乎的抽象概念,而是人类认知的根本生理约束。它不是被想象出来的,而是真实存在且可以感知的。
我们阅读和理解代码的时间远超编写代码的时间,因此应该持续自问:我们是否在代码中嵌入了过多的认知负荷?
在 AI 时代,这一点变得尤为重要——我们需要用自己有限的脑力去处理大量 LLM 生成的代码。
什么是认知负荷
认知负荷指开发者在完成任务时需要投入的思考量。阅读代码时,需要将变量值、控制流逻辑、调用序列等信息放入工作记忆。普通人平均只能同时记住大约 4 个信息块。一旦认知负荷达到这个阈值,理解就会变得异常困难。
假设我们被要求在一个完全陌生的项目中修复问题,有人告诉我们贡献这个项目的开发者非常聪明。项目里满是酷炫的架构、花哨的库和时髦的技术——换句话说,作者为我们创造了高认知负荷。
我们应该尽可能降低项目中他人的认知负荷。
注:本文使用"认知负荷"的非正式含义;它有时与科学上的 Cognitive Load 概念重合,但我们不确定在多大程度上吻合。
认知负荷的类型
- 内在负荷——由任务本身的固有难度引起。无法减少,是软件开发的核心本质。
- 外在负荷——由信息呈现方式创造。由与任务不直接相关的因素引起(如作者的古怪风格),可以大幅降低。
我们聚焦于外在负荷,直接看具体例子。用以下标签标识认知负荷水平:
- 🧠:工作记忆清新,零负荷
- 🧠++:两个信息在工作记忆中,负荷上升
- 🤯:认知过载,超过4个信息块
真实人脑远比这复杂,但这个简化模型足够说明问题。
复杂条件表达式
js
if (val > someConstant // 🧠+
&& (condition2 || condition3) // 🧠+++ 之前条件须为真,且c2或c3有一个为真
&& (condition4 && !condition5)) { // 🤯 到这里已经乱了
...
}
解决方案:引入带语义的中间变量:
js
const isValid = val > someConstant;
const isAllowed = condition2 || condition3;
const isSecure = condition4 && !condition5;
// 🧠 无需记住每个条件,有描述性变量
if (isValid && isAllowed && isSecure) {
...
}
嵌套 if vs 提前返回
嵌套版本:
js
if (isValid) { // 🧠+ 只有合法输入才执行内部代码
if (isSecure) { // 🧠++ 只对合法且安全的输入做处理
doStuff(); // 🧠+++
}
}
提前返回版本:
js
if (!isValid) return;
if (!isSecure) return;
// 🧠 无需考虑前置条件,能到这里说明一切就绪
doStuff(); // 🧠+
我们可以只关注快乐路径,从而将各种前置条件从工作记忆中释放。
继承噩梦
场景:我们被要求为管理员用户修改一些功能。
js
AdminController extends UserController extends GuestController extends BaseController
🧠 哦,部分功能在 BaseController 里,去看看:
🧠+ 基本角色机制在 GuestController 中引入:
🧠++ 部分逻辑在 UserController 中被修改过:
🧠+++ 终于到了 AdminController,开始写代码!
🧠++++ 等等,还有一个 SuperuserController 继承了 AdminController。修改 AdminController 可能破坏子类,先去 SuperuserController 看看:
🤯
优先使用组合而非继承——相关材料已经很多,无需赘述。
过小的方法、类或模块
方法、类、模块此处可互换。
"方法应小于15行"或"类应该小"之类的戒律,其实是错的。
深模块 vs 浅模块
- 深模块:简单接口,复杂功能
- 浅模块:接口相对于其提供的少量功能而言过于复杂
过多的浅模块会让项目难以理解。我们不但要记住每个模块的职责,还要记住它们之间的所有交互。理解浅模块的目的,必须先查看所有相关模块的功能——在浅模块之间跳转极耗心智。线性思维对我们更自然。
信息隐藏至关重要,而浅模块恰恰无法隐藏足够的复杂度。
实际案例:两个项目对比
作者有两份约 5000 行的个人项目:
- 项目一:80个浅类
- 项目二:7个深类
一年半未维护后回来,项目一极难解开80个类之间的交互——需要重建巨量认知负荷才能开始编码;而项目二能快速理解,因为只有少数深类和简单接口。
最好的组件是那些提供强大功能却拥有简单接口的组件。
—— John Ousterhout,《软件设计的哲学》
Unix I/O 接口:深模块的经典范式
Unix I/O 接口极其简单,仅5个基本调用:
open(path, flags, permissions)
read(fd, buffer, count)
write(fd, buffer, count)
lseek(fd, offset, referencePosition)
close(fd)
现代实现有数十万行代码,大量复杂性被隐藏在底层,但接口简单得易用如初。
这个深模块例子来自 John Ousterhout 的《A Philosophy of Software Design》。这本书不仅触及了软件开发复杂性的本质,还提供了对 Parnas 经典论文《On the Criteria To Be Used in Decomposing Systems into Modules》最精彩的诠释。两者都是必读。
延伸阅读:
- 《A Philosophy of Software Design vs Clean Code》
- 《It's probably time to stop recommending Clean Code》
- 《Small Functions considered Harmful》
重要的东西应该大——肉眼可见的重要性
如果允许关键函数更大("不修边幅"),就能在函数海中一眼辨认——它们大,自然显眼。
图片来源:Carson Gross 的《Codin' Dirty》文章,那里有深函数的真实案例。
注意:我们并非提倡臃肿的上帝对象及过多职责——那完全是误读。
关于"单一职责"的滥觞
我们经常根据模糊的"一个模块应该只对一个(且仅一个)东西负责"原则,制造大量浅模块。
但什么才是那模糊的"一个东西"?
实例化一个对象算一件事吧?那 MetricsProviderFactoryFactory 似乎也没问题。
然而,这类类的名字和接口往往比它们整个实现更耗费心智——这算什么抽象?显然出问题了。
我们修改系统是为了满足用户和利益相关者的需求。我们在...
核心结论
- 认知负荷是人类认知的根本约束,不是可选的风格偏好。
- 降低外在认知负荷是设计的第一要务——它可被大幅削减。
- 警惕教条:方法长度、类大小等武断规则往往适得其反。
- 偏爱深模块:强大功能 + 简单接口 = 最优设计。
- 在 AI 时代,低认知负荷的代码比以往更重要——我们每天都要亲自审查大量 AI 生成的代码。