Weekly#27

这周看完了生活大爆炸,结局还是挺感人的,真希望他们能一直演下去。

剧里大家相互之间的打趣让人发笑,而让人感动的是他们之间的感情。

尽管 Sheldon 不是故意的,但是他对身边的朋友都有些刻薄,幸运的是,他的家人,朋友都很包容他,爱着他。

他是幸福的,不是因为他得了诺贝尔奖,而是因为身边有一群爱他的人。

Our whole universe was in a hot dense state,

Then nearly fourteen billion years ago expansion started — Wait…

The Earth began to cool,

The autotrophs began to drool,

Neanderthals developed tools,

We built a wall (we built the pyramids).

Math, science, history, unraveling the mystery

That all started with the Big Bang!

(Bang!)

News | Article

Removing Jeff Bezos From My Bed

作者发现他的智能床会泄漏他的信息,如今很多的家具都是智能的,能采集不少信息,还需要连接网络才能运作。

我对于这些设备的内部实现并不了解,如果有人在设备中放入一个后门我也不知道,或许在不知不觉中,我已经被监控或者泄漏了很多个人信息了。

尽管能够联网,提供一些 APP 会带来一些便捷,但这不应该是以牺牲用户隐私为前提的。

我认为一个合格的设备应该在断网情况下也能够提供完整的功能才对,联网不应该成为一个必要的条件。

Are better models better?

模型一直在变得越来越好,基准测试中的表现也在变好,但本质上它们还是 LLM,是基于概率返回结果的。

虽然大概率它们返回的内容是有帮助的,但依然存在概率是错的,误导的。

而一些任务只能是正确的,不能是近似正确的,就可能不适合用 LLM 去完成。

使用 LLM,你应该具备一定能力去判断它返回的结果是否正确。

以编程来说,如果对于一种语言一知半解,依靠模型也不能提高很多效率,因为一旦出错了,你也不太知道问题所在,以及如何去调试。

要用好 LLM,提高自身的能力,拓宽自己的广度也是很重要的。

然而,还有一类我们希望能够自动化的任务,这些任务既无聊又耗时,传统软件无法完成,其结果的质量不是一个百分比,而是一个二元值。

对于某些任务,答案不是更好或更差,而是对或不对。

Source

当然,这些模型并不“正确”。

它们是概率性、统计系统,告诉你一个好的答案可能是什么样子。

它们不是确定性系统,不能告诉你答案是什么。

它们并不“知道”或“理解”—— 它们只是近似

Source

aposd-vs-clean-code

Uncle Bob1John Ousterhout2在 2024 年 9 月至 2025 年 2 月期间进行的一系列讨论的结果。

讨论主要是关于方法长度、注释和测试驱动开发。

对我来说,软件设计的基本目标是使系统易于理解和修改。

我使用“复杂性”这个术语来指代那些使理解和修改系统变得困难的事物。

导致复杂性的最重要因素与信息有关:

  • 开发者在执行任务时必须在脑海中拥有多少信息?
  • 开发者所需的信息有多容易获取和明显?

开发者需要掌握的信息越多,他们在系统上工作的难度就越大。

如果所需的信息不明显,情况会变得更糟。

最糟糕的情况是,当有一条关键信息隐藏在某个开发者从未听说过的遥远代码中。

当我评估与软件设计相关的想法时,我会问它是否会减少复杂性。

这通常意味着要么减少开发者需要知道的信息量,要么使所需信息更加明显。

Source

我想补充的是,我们最想帮助的程序员不是作者。

我们想要让其工作更轻松的程序员是那些必须阅读和理解他人(或自己一周后)编写的代码的程序员。

程序员花在阅读代码上的时间远远超过编写代码的时间,因此我们想要简化的活动是阅读。

Source

此外,您上面的评论违反了我的一条基本规则,即“复杂性在于读者的眼中”。

如果您编写的代码被其他人认为复杂,那么您必须接受这段代码可能确实复杂(除非您认为读者完全无能)。

找借口或暗示这实际上是读者的问题(“你只是练习不够”)是不可接受的。

Source

这里的关键是你我都陷入了同一个陷阱。

我在 18 年前重构了那个旧算法,我认为所有那些方法和变量名称会使我的意图清晰——因为我理解那个算法。

你在一段时间前写了那段代码,并用你认为能解释你意图的注释进行了装饰——因为你理解那个算法。

但我的变量名在 18 年后并没有帮助我。它们也没有帮助你,或者你的学生。而你的注释也没有帮助我。

我们在箱子里试图与那些站在外面、看不到我们所看到的东西的人沟通。

说到底,向一个对你试图解释的细节不熟悉的人解释某件事是非常困难的。

我们的解释往往只有在读者自己理清了细节之后才有意义。

Source

The web on mobile

如今浏览器功能很强大,以前只能通过 APP 才能做的事情,浏览器也能做到了,例如通知,离线模式等。

但是如今移动端的网页体验依然很差,如果应用都通过浏览器能完成,那么手机上就没必要有那么多占用空间很大的应用,唯一需要的就是一个浏览器。

甚至有的产品,只专注于 APP,做什么都需要你先下载 APP,明明通过网页也能完成相同的事情。

网络应用还有一个天然的优点,那就是是跨端,无论什么系统,什么设备,体验都是差不多的。

It's still worth blogging in the age of AI

在如今 LLM 盛行的年代,还有必要写博客吗?毕竟大家有问题直接问 LLM,而不会花力气去找相关博客内容。

博客内容可能也会成为 LLM 的训练语料,别人通过 LLM 就能获取你分享的知识,更不需要找原文看了。

所以如果写博客是为了给别人看,那可能就会失望。

但写博客的另一个作用是整理自己的想法,锻炼自己的逻辑和表达能力,从这个角度看,写博客还是很有用的。

而且如果博客有人看,并且有互动,知道自己写的东西对别人来说有用,也会带来不少快乐。

我看博客也不习惯给留言,或许以后我会做出一些改变,对喜欢的文章进行点赞或者留言,让作者知道文章有人看,也是一种对作者的鼓励。

推论是,如果你发现了那篇帖子,就说点什么。给作者发个消息,留个评论。

没有其他人这样做。

互联网上有成千上万的人在发布优质内容,却不知道是否有人看到或欣赏。

Source

你的 GitHub 个人资料展示了你对开源的贡献,并让人们知道你编程的能力。

但你的博客展示了你对知识的贡献,并展示了你的思维能力。这是有价值的!

Source

A love letter to the personal website

来创建你的个人网站吧!按照你喜欢的方式打造的你网站,分享那些你的“怪癖”,建造一个属于你的小家。

用 HTML 和 CSS(再加一点 JS 作为点缀)反映你的个性。

这可以是一个专业的作品集,列出你的成就

也可以是一个博客写一些与你有关事情

它甚至可以是一个非常奇怪毫无意义的东西(甚至更好)–我喜欢一个有趣的网站

归根结底,这是你的空间,你可以随心所欲。

Source

因此,我再次发出数字号召:建立你自己的网站。让它充满乐趣。让它毫无意义。但最重要的是: 让它属于你自己

Source

If it is worth keeping, save it in Markdown

如果网上看到你觉得有价值的东西,最好是用纯文本的格式将其保存下来,以备以后查看。

毕竟很多网站随着时间都会消亡,原来保存的链接,说不定就无法打开了,幸运点或许还能在 Internet Archive 里找到备份。

但是极端点,如果断网了呢?那基本是所有链接都失效了。

所以如果有的文章真的喜欢,最好保存到本地,用一种通用的格式保存起来。

作者对于什么网页值得保存的判断是: 值得搜索一次的内容就是值得永远保存的内容

值得搜索一次的内容就是值得永远保存的内容。

担心存储太多?磁盘存储很便宜,对于文本文件来说,几乎是免费的。

Source

Comparing local large language models for alt-text generation

作者博客有很多图片,但是没有添加 alt,于是他想利用 LLM 帮他完成添加。

他测试了 10 个本地 LLM 和 2 个云端的 LLM(GPT-4o, Claude 3.5 Sonnet),比较他们生成的结果。

使用本地 LLM 的主要考量是隐私性,但目前本地 LLM 的表现都比不上云端 LLM 的表现。

Tutorial | Resource

On Troubleshooting

作者整理的一些排障经验。有种中医里“望闻问切”的感觉。

我将故障排除定义为用系统性地方法,定位系统的异常,并加以修复。

心态相关
  • 后退一步

    有的时候排障会陷进去,像打地鼠一样闷头做,会很乱,像一团乱麻。

    这个时候应该停下来,后退一步,思考一下现状,思考一下问题到底是什么。

  • 保持耐心
  • 不要想太多

    不要假设它很复杂。仅仅因为调试很复杂并不意味着原因也复杂。但也不要认为这很简单。

  • 平衡获取信息和修复的投入比例

在解决问题的尝试中应该投入多少精力,以及在获取有关问题的信息时应该投入多少精力?

如果我的直觉没错,直接跳入解决问题会快得多。

但如果不是,从系统上收集信息在长远来看更有效。

  • “学习钓鱼”

    你可以选择交给别人来帮你解决问题。

    也可以选择让对方指导自己,一起解决问题。

    后者虽然短期内对双方而言都更慢,你能学到东西。

  • 与系统保持良好关系

    把系统当作对手,而不是敌人。对手必须被尊重并理解才能被击败。敌人你不会尝试去理解。

    我注意到:不喜欢自己电脑的人往往在使用电脑时效率低下;而不喜欢他人的人往往无法从他们那里得到自己想要的东西,除非他们擅长隐藏自己的感受。

    这听起来有些模糊,但我认为欣赏出故障的系统的美丽和复杂性会使人更有效地进行故障排除。

    将系统视为敌人会使其成为敌人。

  • 理解问题

    一个被理解的问题已经大部分解决,除非某些部件难以获得或难以安装。

    要找到真正的问题所在。

    这些陈述可能都是真的:

    • 这个音响系统坏了。
    • 这个 MP3 播放器坏了。
    • 这个 MP3 播放器的耳机插孔坏了。
    • 这个 MP3 播放器的耳机插孔上的焊接点坏了。

    我可以更换 MP3 播放器。我可以更换耳机插孔。或者,我可以重新焊接一个焊点。结果将是一样的。

    虽然更换超过必要的部件是浪费且不优雅的,但一个好的故障排除者也需要知道何时放弃深入解决一个并不重要的问题,而选择一个更节省资源的权宜之计解决方案。

    回答一个 “为什么” 的问题总是有几个不同的层次,这取决于你在寻找什么样的答案。

σ(´∀`*)

方法相关
  • 做一些保证会产生效果的事情

    例如在排查 CSS 错误时,可以先设置 * {color: red !important;} ,确保写的代码在正确的文件中,并且确实被执行。

    有时候同时在多个分支开发,发现写了逻辑但是没有执行,调试半天才发现是写错位置了。

    所以在调试的时候,可以先做点简单的事情,确保在正确的地方调试。

  • 确定数据/状态流向

    确定数据,状态的流向。输入、输出和转换是什么?

    花很多时间去“修复”问题是很容易的。但这只是简单的部分。

    困难的部分是理解系统,然后隔离和理解问题。

  • 观察症状

    这里应该发生什么,实际上发生了什么,两者之间有什么不同?

    我相信我理解系统的想法常常成为故障排除的障碍。

    即使我“对系统了如指掌”,我也不太可能完全理解它。

    即使是我构建的系统也由我没有构建的系统组成;

    而且即使是看似简单的系统也是无比复杂的。

    (正如卡尔·萨根所说:“如果你想从头开始做一个苹果派,你必须首先创造宇宙。”)

  • 隔离问题

    找出是什么位置出现问题,尽可能排除影响因素,将范围不断缩小。

    影响因素可能是内部的,也可能是外部的。

    通过隔离一些子系统,方法(例如注释掉),排除可能的影响。

    可以像做科学研究一样去隔离问题:

    1. 对问题形成假设。

      假设可能是什么造成的,首先去排除最简单和最可能的问题区域。

      如果没有方向,可以尝试二分法(git bisect),排除法。

    2. 找到最简单的方法来证伪假设。
  • 收集系统信息

    从系统获取的信息越多,最好是在错误发生时获取,效果就越好。

    在软件中,这意味着记录日志或在进程运行时附加调试器。

  • 善用搜索

    知道去什么地方获取信息,可能是一些专门的论坛,可能是某个专家,或者搜索引擎。

    一些搜索引擎技巧:

    关于日志信息:

    大多数系统会发出多种信息,且相关性差异很大。

    只有错误信息的某些部分是重要的。

    大多数软件错误信息在谷歌中直接粘贴时几乎没有什么有用的结果,因为它们包含与我的设备相关的特定内容。

    我通常从完整的错误信息开始,去掉明显与设备相关的信息。

    如果没有找到任何结果,我就扩大搜索范围。我停止寻找关于特定版本的信息。我停止寻找关于特定硬件的信息。

    甚至我停止寻找关于特定软件的信息,然后我在论坛中找到使用不同笔记本电脑、运行不同应用程序的人,他们共享导致错误的依赖项。

    他们的修复方法可能不奏效,但可能会指引我找到问题所在。

    然后我可以获取更多数据并重复这个过程。

  • 缩短反馈循环

    想办法缩短反馈的回路,可以更快地复现问题,从而可以更快地尝试更多可能去排查问题。

  • 把它写下来

    像专业人士一样进行橡皮鸭调试:我经常通过起草一个论坛帖子来解决我的问题,而不发布它。

    阐明系统和问题的关键细节所需的努力,远高于我通常在决定需要帮助时所投入的努力。

    看那一串面包屑:我发现写作和绘图虽然对许多故障排除项目有帮助,但对于多次会话的故障排除项目来说是必不可少的。

    我高估了自己对上下文的记忆程度,以及我会多快继续这个项目。

    无论我写下的信息在当时看起来多么明显或不完整,故障排除笔记文件都留下了一条我下次可以追踪的面包屑路径。

  • 将特定的输入放入黑盒中观察结果

    有时一个系统是一个黑盒,不知道里面是怎么运行的,可以尝试造一些特定数据,输入进去,观察它的输出。

How Core Git Developers Configure Git

一些作者推荐的 Git 配置。

Welcome to the 🤗 AI Agents Course

Hugging Face 的 AI 代理教程。

macOS Tips & Tricks

一些 macOS 的使用技巧。

Code Related

Mastodon Comments

作者原来用 Disqus 作为博客的留言系统,但是最近 Disqus 不允许关闭广告,所以作者想替换它,并且自己实现相关逻辑,通过 Mastodon 实现留言功能。

cp - copying all files of a directory, including hidden ones | Jayesh Bhoot

使用 cp 命令,将一个目录下的所有文件(包括隐藏文件)复制到另一个空目录中,你会怎么写?

我的第一反应是 cp -r src dist ,但是这样复制过去,得到的结构是 dest/src/{.hidden,unhidden} 而不是 dest/{.hidden,unhidden}

可行的命令是 cp -r src/. dest

作者分析了为什么要这么写,可以看看原文。

Migrating 160,000 Lines of Production Banking JavaScript to TypeScript with Zero Downtime

一个团队将 160000 行的代码库从 JS 迁移到了 TS,并且确保服务不暂停。

他们的做法可以借鉴:

  • 单独分支进行重构
  • 定期合并主分支代码,保持同步
  • 从核心模块开始,渐进式地迁移到 TS
  • CICD,足够的测试,贴近生产环境的测试

Cool Bit

Let's Hold Hands

作者做了一个网站,可以让你和一个陌生人握手。

网站很可爱。

想象这样一种互动:当某人心情低落(或只是无聊)时,碰巧打开了 Let's Hold hands ,然后屏幕上出现了另一个人,他们伸出手来,你们在一起玩了 30 分钟,然后离开。

离开时,你只知道你和另一个无名的人度过了这段时间。

你并不期望与人交谈,了解某个人,甚至为某个人服务。

两个人在黑暗的房间里互相说着我是我是我是

Source

Whimsical Animations

Josh W.Comeau 为他的课程做了一个 landing page,有不少的交互,挺好玩的。

他还写了篇文章分享他是如何实现的

eelslap.com

哈哈哈,无聊但是好玩。

Making any integer with four 2s - Eli Bendersky's website

给定 4 个数字 2,可以用它们表达任意数字,不过对于数学知识有一定的要求。

有点像 24 点,给定四张牌,通过一些数学运算计算得到 24。

"The closer to the train station, the worse the kebab" - A "Study"

作者看到一个帖子说,“距离火车站越近,烤肉的味道越差”,于是他从网络搜集数据分析,去看看这个说法是否成立。

一番搜索后,距离和评分的数据相关性不高,不过整个探索过程还是挺有趣的。

adenta/fire_red_agent

作者实现了让 LLM 玩宝可梦,厉害。

Tool | Library

beatcode

让 leetcode 变得有趣,你可以和别人比赛,双方都会有血条,每当你通过一个用例,就会给对方造成一点伤害。

Accessible Color Palette Generator

一个颜色面板生成工具,生成的颜色符合可访问性要求。

Emacs

一些话 | 摘抄

Knowing CSS is mastery to Frontend Development

这也就意味着,最终还是要靠自己:如果你了解 CSS,你也就了解了样式框架。

如果你了解 JavaScript,TypeScript 对你来说就不是什么大问题。

这样,你就能成为高级或主管。

Source

Making o1, o3, and Sonnet 3.7 Hallucinate for Everyone

LLMs大多数时候真的很聪明。

但是,一旦涉及到小众话题,并且没有足够的背景,它就开始像我职业生涯早期的自己。

打开 StackOverflow,Ctrl+C,Ctrl+V,Leeroy Jenkins 风格。

Source.

Write to Escape Your Default Setting

对于我们这些灰质极其贫乏的人来说,我们的思维所及有限。

对于过去,它们是热情但无能的档案保管员。

对于当下,我们的大脑会捕捉最具煽动性的思想片段,但往往宁可分散注意力,也不愿清晰明了。

写作提供了脚手架。为无组织、无纪律的思维提供结构。它是更有效思考的实用工具。

有时,它是真正开始思考的最佳方式。

Source

Your Next Two Zeroes

你可以花 $1M 买一栋漂亮的房子。你可以用 $100M 购买一幢漂亮的摩天大楼。

10 人可参加无主持人讨论。1000 人需要会议组织者。

你的工具/方法通常可以扩展一个数量级;增加两个零会迫使你重新思考一切。

Source

每一次 10 倍跳跃都会将知识/资源推向逻辑极限,而 100 倍跳跃则会扰乱问题领域的所有维度。

每隔两个零,你最保守的成功秘诀就会变成你最臭的直觉。

为了向前迈进,放弃你最喜欢的技能/工具/方法/才能。

超越自我,一次又一次地成为新手。

Source

Model Context Protocol

Model Context Protocol(MCP) 是一个开放协议,它规范了应用程序为 LLMs 提供上下文的方式。

将 MCP 视为人工智能应用的 USB-C 端口。

正如 USB-C 提供了将设备连接到各种外设和配件的标准化方式一样,MCP 提供了将人工智能模型连接到不同数据源和工具的标准化方式。

福利院中最特别的女孩:她4岁那年,主动抛弃了妈妈|有爱孤儿院 09

我们都不强行干预,不打扰悲伤,不强行关起门要治愈她们,给他们提供了一个了有爱、自由、包容的环境,她们的伤口就自然愈合了。

良好的环境就像免疫系统,把时间交给它,它自有能力让我们复原,而不是打开心理的伤口做手术,一遍遍剖析她们的伤痛。

真正的治愈不是拔掉刺猬的刺,而是给她一个柔软的环境,让她找到可以让自己卸下硬刺的家人。

刺猬的刺不是一直绷着,只有紧张、发脾气时才是锋利的、刺人的。它放松的时候,身上的刺很顺,一点也不扎人。

Source

晓荷问:“你为什么喜欢她?你喜欢她什么?”

男朋友说:“如果真的能说出一二三条,也太功利了吧,没有具体的原因,因为是她。”

晓荷说:“那你给我个承诺吧。”

我男朋友说:“承诺什么?永远爱她吗?”

晓荷哈哈笑着说:“才不要咧!只有软弱的人才需要一个人永远爱她,她才不需要这种东西呢,你要承诺,你会尊重她的每一个想法和选择,即使那个想法是荒唐的。”

Source

在日常生活里,我们好像总能遇见一些专家,他们总是想给我们强行定制一套“幸福标准”,好像偏离了这套标准,我们就得被矫正。

我觉得很多问题就是这样产生的。每个人出身不同,经历也不同,怎么能被简单粗暴地塞进一个“正常”的模板里评判呢?

在这篇故事里,我没想过改变晓荷身上的怪异,而是想为她的怪异,寻找一片自由发挥的土壤。

也许真正的爱,不是改变那个人,而是给他提供一个温暖、舒适,能够包容他的环境。

我也想和所有的“晓荷”说:

人是生命,不是一个个要解决的问题。多肉有多肉的养殖方式,百合有百合的规则,你就是你独有的样子,不必盯着自己的问题,也不用和自己过不去,活得舒服就好了。

让广阔的世界去理解你。

Source

多媒体

Music

方大同 - 没啥好说

109951170031584299.jpg?param=130y130
图1  《梦想家》专辑封面

I framed your picture on my wall

说过的话 美丽的夏 都过完了

I didn’t know that I would fall

都忘了吧 说不需挂 回忆放下

得知方大同去世的消息很意外,像是一个刚认识没多久的朋友,突然知道他已经不在了。

喜欢他的歌还是不久之前,看了Hopico 的采访,重新认识了他。

很可惜没有机会去听他的演唱会了(15 Live in HK 神现场),也无法听到他的新歌了。

看到他最近发布的专辑里的留言是:

感谢大家,晚饭时间到了!大家吃完饭也早点休息,身体健康,下次再见!

没想到再见是再也无法见到了,R.I.P。

都要保重身体。

简约情人 - 走失的人不悲伤

109951170514121023.jpg?param=177y177
图2  《走失的人不悲伤》专辑封面

简约情人 2025-02-28 发的新专辑,比较喜欢里面的《起风的日子》,《逃》,《走失的人不悲伤》。

脚注:

1

《Clean Code(整洁代码)》的作者

2

《A Philosophy of Software Design(软件设计哲学)》的作者

1

《Clean Code(整洁代码)》的作者

2

《A Philosophy of Software Design(软件设计哲学)》的作者

Author: Spike Leung

Date: 2025-03-03 Mon 00:00

Last Modified: 2025-03-06 Thu 10:50

License: CC BY-NC 4.0