
程序员们也许是互联网上最爱分享的群体之一,他们不仅喜欢开源自己写的软件,也爱通过写文章来分享知识。从业以来,我阅读过大量技术文章,其中不乏一些佳作。这些佳作中,有些凭借深刻的技术洞见令我深受启发,也有些以庖丁解牛般的精湛手法解释一项技术,让我读后大呼过瘾。
作为“爱分享”的程序员中的一份子,我想当一次推荐人,将读过的好文章分享给大家。我给这个系列起名为 《程序员阅读清单:我喜欢的 100 篇技术文章》。
受限于本人的专业与兴趣所在,清单中的文章对以下几个领域有所偏重:程序员通识、软件工程、后端开发、技术写作、Python 语言、Go 语言。
下面是阅读清单的第三部分,包含第 41 到 50 篇文章。
系列索引:
清单
41. 《抽象泄露法则》
- 原文链接:The Law of Leaky Abstractions
- 作者:Joel Spolsky
用 AI,花 5 分钟开发一个新功能。验证时,却发现新功能在某个特殊情况下无法正常工作。为了解决这个 bug,你只能逐行排查调试。等修复好问题,一看表, 1 个小时过去了。
上面的经历对你来说是否有些似曾相识?早在 2002 年,程序员 Joel Spolsky 就敏锐地发现了这类现象,并将它们总结为:“抽象泄露法则”。软件世界是一层抽象套着另一层的千层饼,就好像 HTTP 协议下有 TCP、TCP 下有 IP,每一层抽象都声称自己是完美的:“你无需关注在我之下的任何细节”。
但事实却是,所有抽象必定泄露。而当抽象泄露时,就像要从 AI 的 1000 行代码里找到那个错误——事情非常棘手,但我们别无选择。
42. 《如何设计一个好的 API 及其重要性》
- 原文链接:How to Design a Good API and Why it Matters
- 演讲视频:How To Design A Good API and Why it Matters - Youtube
- 作者:Joshua Bloch
这份资料来自 Joshua Bloch(时任首席 Java 架构师)在 Google 公司的内部演讲。虽然距今已 17 年,但它读起来却没有任何过时的感觉,对现代软件开发仍具备指导价值。
Joshua 系统性地阐述了 API 设计的方方面面。包括:
- 带着怀疑的眼光收集用户用例(use cases);
- 写代码前,先用最简单的文字描述 API(一页纸以内),并和相关人员讨论完善;
- 如果迟疑于是否提供某个功能,就先不要提供(后续新增比删除要简单得多);
- API 应当和它所被使用的平台和谐共存,比如 SDK 不应被原样从一门语言搬运到另一门。
如果你之前从未深入思考过 API 设计,读读看,它极有可能改变你未来开发软件的方式。
43. 《我构建软件的原则+实践“让无效状态不可表示”》
- 原文链接:My Principles for Building Software
- 原文链接:Applying "Make Invalid States Unrepresentable"
- 作者:Kevin Mahoney
关于软件开发原则的文章有很多,这篇的特别之处在于,作者 Kevin 着重强调了数据对于软件设计的影响。
比如,Kevin 提出在设计时,应当优先考虑数据结构而不是代码,因为前者更为重要。正如《人月神话》的作者 Fred Brooks 曾经说过:“如果提供了程序流程图,而没有表数据,我仍然会很迷惑。而给我看表数据,往往就不再需要流程图,程序结构是非常清晰的。”
Kevin 提到的另一条原则是“让无效状态不可表示”。软件的业务逻辑中,难免会存在一些“无效状态”。为了处理它们,代码常需要做一些额外工作。然而,通过调整数据结构设计,使得数据层无法表现无效状态后,程序复杂度就可以降低。《实践“让无效状态不可表示”》中有本原则的一个具体应用案例。
除了上述原则外,文章中的其他原则,比如“关注基础概念而不是具体技术”、“避免用局部简单换取全局复杂”,等等,都充满智慧。
44. 《不,不是编译器的问题,从来都不是》
- 原文链接:No, it is not a compiler error. It is never a compiler error.
- 作者:Mark Dominus
一段代码的正常运行,依赖着无数隐藏在其背后的组件和库。当程序出现 bug 时,程序员不在第一时间怀疑自己的代码,而是去质疑那些久经考验的依赖库,从来不是一个明智的选择。正如文章的标题所言:“从来都不是编译器的问题。”
然而,“编译器”也是由人编写,并非真的永远正确。“编译器”一旦犯错,问题的诡异程度常常会出乎意料。在文章的后半段,常年信奉“编译器不出错”的作者,还真就遇上了一次“编译器错误”。
45. 《关于在除夕前一天换了一个洗衣机的故事》
- 原文链接:关于在除夕前一天换了一个洗衣机的故事
- 作者:wklken
一名程序员家中服役 6 年的洗衣机坏了,不能脱水。因为之前花大价钱换过一次排水泵,他以为这次是旧病复发,便决定置换一台新机器。可没想到的是,新洗衣机装好后同样不能脱水。
本来只是一件普普通通的糟心事,但作者显然不这么想,他在文章后半居然从洗衣机转向了软件开发。从故障码到说明书,从 debug 到选品牌,真是很有意思。相当好的观察与思考。
46.《你的函数是什么颜色?》
- 原文链接:What Color is Your Function?
- 作者:Bob Nystrom
有人发明了一门编程语言,它非常特别,因为它的函数以颜色来区分类型。函数一共有两种颜色:“红色”和“蓝色”。函数的颜色不止影响外观,更会影响你使用它们的方式,比方说:红函数只能调用红函数,不能调用蓝函数。
虽然以上面这略为不知所云的内容开场,但这篇文章讨论的主题实际上相当严肃。在文章中,作者 Bob 分享了自己对异步编程风格一些思考(猜猜函数的“颜色”代表什么?),从回调、Promise,到线程和 await/async,均有涉及。
除了观点鞭辟入里,文章的写作质量也相当高。严肃内容间不时穿插一点作者的小幽默。对于爱好异步编程的人来说,这是一篇不可错过的佳作。
47. 《健康的文档》
- 原文链接:Healthy Documentation
- 作者:Vadim Kravcenko
程序员们是一个奇怪的群体,他们对许多事物持有矛盾态度,“文档”就是其中之一。
作为消费者时,每位程序员都希望自己所使用的每个 API、函数,接手的每个系统都能找到详尽而准确的文档。而当他摇身一变,变成生产者时,却很少愿意在“写文档”这件事上投入精力——常常是“宁编百行码,不写一行字”。
然而,文档对于软件开发的重要性毋庸置疑。正如作者提到:“每个未被记录下的东西,都等同于一种资源的浪费,会在未来带来麻烦。”通过写文档,我们将自己脑中的知识具象化,从而在未来帮助到其他人。对于个人而言,文档不仅是一种学习、交流和分享知识的工具,也是一种建立个人影响力的捷径。而对于团队来说,如果每位成员都重视文档的价值,乐于编写清晰、可靠的文档来替代无休止的会议,那么这种“文档优先”的氛围,对于团队的长期发展大有裨益。
48. 《如何像人类一样做代码评审》
- 原文链接:How to Do Code Reviews Like a Human (Part One)
- 作者:Micheal Lynch
一篇关于代码评审的文章,里面涵盖了许多入门和进阶经验,包括:别把评审时间花在风格与样式问题上,让工具来代劳;评论应该以“请求”的口吻,而不是“命令”;评审不是只找缺点,对于好代码应该不吝赞美,等等。
强烈推荐给每一位需要参与代码评审的程序员。
49. 《关于 Python 3.13 你需要了解的一切 - JIT 和 GIL》
- 原文链接:Everything you need to know about Python 3.13 – JIT and GIL went up the hill
- 作者:Drew Silcock
Python 3.13 版本引入了许多激动人心的改动,比如基于 “copy-and-patch”技术的即时编译(JIT),以及终于去掉了全局解释器锁(GIL)的“自由线程”模式,等等。
Drew 的这篇文章介绍了以上改动。文章的写作风格非常友好,内容也很全面。既有零基础的概念科普,也有实际的代码实验与 benchmark 环节。知识多,篇幅却控制得恰到好处,推荐阅读。
50. 《入行 14 年,我还是觉得编程很难》
- 原文链接:入行 14 年,我还是觉得编程很难
- 作者:piglei
这是清单的第 50 篇,也标记着整个“程序员阅读清单”系列完成了一半。考虑再三,决定奉上拙作一篇,我把这作为对自己的一个小小鼓励。
编程难吗?不同的人会有不同的答案。十几岁时,还在上学的我觉得编程很难,各类算法、API 让人头晕目眩。我期望多年以后,大量的开发经验会让编程变得像吃饭一样简单。
如今十几年过去,编程好像只是变简单了那么一丁点,距离“像吃饭一样简单”还差得很远。
在这篇文章里,我分享了自己对编程这件事的一些思考与总结。比如:打造高效试错的环境至关重要,编程的精髓是“创造”,等等,希望能对你有所启发。
结语
以上就是“程序员阅读清单”第三期的全部内容,祝你阅读愉快!
题图来源:Photo by Jametlene Reskp on Unsplash
😊 如果你喜欢这篇文章,也欢迎了解我的书: 《Python 工匠:案例、技巧与工程实践》 。它专注于编程基础素养与 Python 高级技巧的结合,是一本广受好评、适合许多人的 Python 进阶书。