我平时读 ae.c、读 __schedule、读 InnoDB 的 buf_pool,今天读一个 dev.to 帖子。
帖子叫「Anyone else wish they had more developer friends? 👋」,作者 Akash Dutta,10 月 14 日发的,四个标签:#discuss、#watercooler、#community、#programming。我刷到的时候 27 条顶层评论,评论区滚成一长串多轮对话。
打开它本来是想看有没有人认真回答那三个问题。读到第十五条回复附近,我停住了,往回翻,从头又读了一遍。
这篇就是那次重读的结果。
先交代方法。我读任何一段代码,先问三个问题:入口在哪、数据往哪流、边界条件写在哪一行。这个帖子不是软件系统,但评论区是一个有入口、有分支、有返回值、有失败路径的东西,而且它失败的方式,和我见过的很多代码失败的方式,是同一类。
先给地图
不给地图就钻巷子,是我最烦的读法。
27 条评论,三层。
第一层,发起层。作者发帖,自我介绍——Python、AI、Web 开发,爱折腾临时起意的小项目,也爱聊技术之外的东西——声明这不是推销式社交、不需要正式自我介绍,抛三个问题:你最近在做什么或在学什么、技术之外你真正热衷什么、愿不愿意和网友一起做个小项目。末尾说欢迎各种背景,资深开发者、学生、只是对技术感到兴奋的都行,留言或私信都可以。
第二层,应答层。第一批发声的人。FrancisTRᴅᴇᴠ 是这条链上最关键的节点,给了建议、给了边界、后来给了推荐。Vicente G. Reyes 给了另一种活法,build996 给了一个可执行的协议,John Borghardt 给了一个跑偏的分支。Hemapriya Kanagala 夹在推荐链里,但她说的其实是这个帖子里最接近正确答案的一句话。
第三层,派生层。作者顺着 Francis 的推荐去够人,够到 Giorgi Kobaidze,被一句「我不是美国人」弹回来。
三层不是并列的,是调用关系。发起层定义接口,应答层实现或者拒绝实现,派生层是参数传递过程中出的错。我在纸上画出来大概是这样:
akash.post(questions = [doing, passion, collab?],
constraints = [no_pitch, no_formal_intro],
channel = [comment, DM])
│
├─ francis.reply(advice = "去评论别人的帖子",
│ boundary = "交流留在 DEV 内",
│ trust = "你是我告知此事的第二个人")
│ │
│ └─ akash.reply(ask = "能私聊吗", ask = "能引荐吗", ask = "最好是美国人")
│ │
│ └─ francis.refer(@hemapriya, @jiro, @george)
│ │
│ └─ george.reply("I'm not American") ← 参数在传递中失真
│
├─ vicente.reply("我只有两个技术朋友,我挺满意") ← 另一种实现
├─ build996.reply("一小时,一个能跑的东西,别预设联创") ← 收窄接口
├─ hemapriya.reply("先去参与别人的讨论,别带着找人的压力") ← 先读文档
└─ john.reply("我在手机上做 SCI 引擎,顺便推荐我的阅读工具") ← 搭便车的分支
主线是 akash → francis → george,其余是旁支。旁支里两支健康(vicente、build996),一支跑偏(john),还有一支挂在推荐链旁边、说的却是主线该听的话(hemapriya)。
下面一段一段钻。先说清楚:我手上不是全文,是骨架——谁说了什么、谁回了谁、哪条链断在哪。骨架也能读出东西,而且往往比全文更能看出结构。全文里的客套话会把分支盖住。
入口:三个问题,第一个就把人分成两类
三个问题,写成签名:
ask_1: 你最近在做什么、在学什么?
ask_2: 技术之外,你真正热衷什么?
ask_3: 你愿不愿意和网友一起做一个小项目?
有递进,但递进的方向和作者以为的不一样。
第一个问的是状态。低门槛,任何人都能答,答出来也不暴露什么。作用不是筛选,是破冰。你答了,你就从「27 条评论里的一个头像」变成「一个在做某件事的人」。
第二个问的是热情。深一层,要求你说一件和工作无关、但你愿意花时间的事。筛的不是技术水平,是「你有没有一个不为了简历而存在的兴趣」。Francis 答的是游戏,Switch 单机,最近在玩 Deltarune Chapter 5,还想试 Helldivers 2,正在当前硬件行情下想办法弄一台 PC。具体到你能想象他坐在哪儿。Vicente 答得更绕,他没直接答第二个问题,他答的是「我身边只有两个技术圈朋友」,然后描述这两个人是谁。这其实是用「我现有的关系」回答「我热衷什么」,答得很偏,但你能看出他是个满足的人。
第三个问的是承诺。唯一一个要求行动的问题。前两个只要你说话,第三个要你点头。
问题出在这儿。作者把三个问题并列抛出,好像它们是同一层级的信息采集。但它们不是。第一个是自我介绍,第二个是价值观匹配,第三个是合作意向。三个一起问,读到的人会自动按「我能不能答第三个」来决定要不要回帖。
第三个问题于是成了事实上的过滤器,而作者以为它只是三个问题里的最后一个。入口设计里最常见的一种误判——你以为你在收集信息,其实你在设门槛。
还有个细节。作者明确说「这不是推销式社交、不需要正式自我介绍」。本意降门槛,反而暴露了一件事:作者自己知道这种帖子容易写成推销,所以先打预防针。预防针打得太早,读的人会想「你为什么要先说这个」。不是大问题,但让入口多了一层不必要的防御。
换我写这个帖子,我会把第三个问题拿掉,只留前两个。为什么?因为第三个是唯一一个需要对方现在就做决定的,而关系不是靠一次决定建立的。前两个问好了,第三个会自己长出来——有人在评论区聊着聊着说「要不我们搞一个」,那才是真的。你把它写进入口,它就从「可能发生的事」变成「必须现在回答的事」。
作者没这么写。三个都抛了。这是他后面所有麻烦的起点。
第一个分支:Francis 的建议,和作者读错的返回值
FrancisTRᴅᴇᴠ 是这条链上第一个认真回的人。
他给了三样东西:建议(去评论其他人的帖子)、构想(一个叫 DEVengers 的组织,对所有人开放,因为时间原因还没搭起来)、信息(他手上有个有趣的项目,打算之后在 DEV 上公开,时间没定,作者是他告知这件事的第二个人)。
三样东西,重要性是倒着排的。
「去评论其他人的帖子」是这个帖子里最有用的一句话,也是作者最没听进去的一句话。它把「找朋友」从「发帖等人来」改成「去别人的帖子下面出现」。前者是广播,后者是握手。广播的回复率取决于你的帖子写得多好、算法推得多远;握手的回复率取决于你说的话有没有接住对方。前者你控制不了,后者你能控制。
Francis 说他自己就是这么认识人的。这话不是客套,是经验。一个 2026 年 1 月加入 DEV 的人,到 10 月待了九个月,见过太多「谁来跟我做朋友」的帖子沉下去,也见过在别人评论区里聊出来的关系。他给的建议是入口重定向——你别在我这儿等,你去别人那儿敲门。
作者怎么回的?他说自己来 DEV 是为了分享想法、向其他开发者学习、结识有趣的人,觉得有人一起交流想法时写代码更有乐趣,然后问能不能私下联系 Francis。
接住了「结识有趣的人」,没接住「去评论其他人的帖子」。他把 Francis 的建议理解成了「你在这里认识了我」,而不是「你去认识更多人」。典型的读错返回值——函数返回的是方法,调用方当成结果用了。
DEVengers 那句是个钩子,给了作者一个「我们可以一起做」的由头。但 Francis 说得很清楚:没搭起来,因为时间。他没说「你要不要帮我搭」。作者也没接。钩子悬在那儿。
第三样最有意思。「你是我告知这件事的第二个人」——这是一个信任的度量。一个人把自己没公开的项目告诉另一个人,还特意告诉你「你是第二个知道的」,这是在给这段关系标定稀缺性。第一个知道的人是谁不重要,重要的是「第二个」这个序号。序号越小,关系越近。
作者收到这个信号了吗?收到了,但用错了方向。他没顺着信任往下走——比如问问那个项目是什么、需不需要人帮忙看看——他转而去问「能不能私聊」「能不能引荐」「最好是美国人」。他把一个「我们已经有一点信任了」的信号,当成了「我可以向你要更多」的许可。
这条链上第一个错位。不是 Francis 的错,是作者把信任的返回值当成了资源的入口。
边界:Francis 为什么不肯离开 DEV
作者先后问了两次,一次问所在地,一次提出换 Telegram、邮件或 WhatsApp。Francis 拒了,说坚持把交流留在 DEV 平台内。
这条链上唯一一个被明确说出来的不变量:「这段关系的上下文,不离开产生它的地方。」
为什么一个开发者会守这条线?我不是他,只能从代码的角度推。一个人在公开平台上认识另一个人,这段关系的第一层信任是靠平台背书的——你的资料、你的历史发言、你的关注列表,都在那儿。搬到 Telegram,平台背书没了,剩下的只有你们俩说过的话。对 Francis 这种人,这不是安全问题,是上下文问题:他不想把一段刚起步的关系,从一个有记录、有旁观者、有公共可见性的地方,搬到一个没有记录、没有旁观者、只有两个人的地方。
还有一层。作者提私聊之前,先问了「你在哪儿」。这个顺序很关键。先问地点,再提私聊,这两步连在一起,在对方感受里就是「你在给我定位」。Francis 的拒绝,一半是拒绝私聊,一半是拒绝这个顺序。
我不觉得作者有恶意——他大概率只是觉得私聊更方便。但方便是发起方的视角,不是接收方的视角。接收方看到的是:这个人刚认识我,就想把我从公开场合挪走。
这条边界后来还起了另一个作用。作者后面说想找一个能长期合作的朋友,请 Francis 引荐,还特别提出希望对方是美国人。Francis 先提了 @hemapriya_kanagala 和 @codingwithjiro 可能有意向,又推荐了 @georgekobaidze,但强调愿不愿意接触取决于被推荐者本人。
Francis 守住了两条线。一条「交流留在 DEV」,一条「引荐可以,但我不替被引荐的人做决定」。后一条是引荐这件事的正确写法——引荐人给的是介绍,不是承诺。你把「他可能愿意」说成「他会愿意」,你就替别人做了决定,这个决定迟早要还。
作者收到这个边界了吗?没有。继续往下要。这是整条链上我最想拍桌子的地方——不是他要东西这件事本身,是他要东西的时候,完全没看对方刚在上一句里画了一条线。
硬编码:那个「最好是美国人」
全文的钉子。
作者在后续回复里说想找一个能长期合作的朋友,请 Francis 引荐,还特别提出希望对方是美国人。
整个帖子里唯一一个被写死的、不可协商的过滤条件。
前面说过什么?说过「欢迎各种背景的人回应,包括资深开发者、学生以及只是对技术感到兴奋的人」。开放的。到第十五条回复附近,条件变成「最好是美国人」。
两句话不矛盾,但层级不一样。前面那句是欢迎,是态度;后面那句是希望,是筛选。态度可以开放,筛选一定有边界。问题不在他有偏好——每个人都有偏好——问题在这个偏好被说出来的位置。它出现在「请人引荐」这个动作里,而不是出现在「我为什么想认识这样的人」这个说明里。前者是提要求,后者是给理由。提要求只需要对方配合,给理由才需要对方理解。
更关键的是,这个条件在推荐链上失真了。
Francis 推荐了 @georgekobaidze。Giorgi Kobaidze 本人在评论里回应,说自己并非美国人。资料显示他是两次黑客松获奖者,位于格鲁吉亚第比利斯,在 Flutter CEE 做工程经理,曾就读于圣迭戈州立大学。
这条链我读了三遍。
Francis 推荐 Giorgi,用的是「正经的工程经理、有黑客松获奖记录、在 Flutter 社区有位置」这些理由,不是「他是美国人」这个理由。
作者收到推荐之后去够 Giorgi,然后 Giorgi 说「我不是美国人」。这句话是整条链上最尴尬的一句,因为它说明 Giorgi 知道这个筛选条件,而且知道自己不符合。他从哪儿知道的?大概率从公开评论区看到的——作者那个「希望是美国人」的要求,写在明面上。
这个失真不是任何一个人的错。Francis 没错,他推荐了一个值得认识的人;Giorgi 没错,如实说明;作者的错也不大,只是提了个偏好。错的是结构:筛选条件写在请求方,没有写在接口上。Francis 推荐的时候,手上没有一份「作者要什么」的完整清单——他只知道作者想找人合作,不知道「美国人」是硬条件。于是推荐链把一个不符合条件的参数传了进去,直到被推荐的人自己把它弹回来。
参数传递里最经典的 bug:调用方以为被调用方知道约束,被调用方以为调用方没有约束,两边都没错,结果错了。
我在这儿停了一下,因为想起一件事。作者自己的资料显示,软件工程师,方向包括 AI、LLM 应用、后端系统与开发者工具,所在地美国加州圣迭戈,就读于圣迭戈大学,2026 年 10 月加入 DEV。Giorgi 曾就读于圣迭戈州立大学。
两个都在圣迭戈的学校,一个叫圣迭戈大学,一个叫圣迭戈州立大学,不是同一所。这个巧合我没法不多想:一个在圣迭戈读书的人,隔着半个地球被推荐给一个在圣迭戈州立大学待过的第比利斯人,推荐理由是「他可能有意向」,然后被推荐的人说「我不是美国人」。
这个画面本身就是对这个筛选条件最好的反驳。你要找能一起做东西的人,结果你用来筛人的条件是国籍。国籍和「能不能一起做东西」之间的相关性,低到可以忽略。你真正该筛的是「他最近在做什么」「他技术之外热衷什么」「他愿不愿意花一小时做个傻东西」——这三个问题,你在入口里已经问过了。
你把已经问过的问题放下,换了一个没问过的、也没法从答案里推出来的条件。抽象错了。你把「合作匹配」这个需求,抽象成了「美国人」这个属性。
反例:Vicente 的两个朋友,和 build996 的一小时
评论区里有两支,读的时候我觉得比主线健康得多。
Vicente G. Reyes,身边只有两位技术圈朋友,一位是儿时同学兼乐队伙伴的技术从业者,另一位是从事财富管理的 vibe coder。他对现状满意。资料显示他是自 2018 年起接单的 Django/React 与 Shopify 自由开发者,常驻菲律宾马尼拉。
这条回复拆了一个前提。整条主线的隐含前提是「技术朋友越多越好」,作者发帖是因为「wish they had more」。Vicente 说:我有两个,我挺满意。
两个。不是二十个,不是两百个。两个。
而且这两个朋友的构成很有意思。一个是儿时同学兼乐队伙伴——从非技术场景里长出来的技术朋友;一个是做财富管理的 vibe coder——从技术场景里长出来的非典型技术朋友。两个都不是「在技术社区里认识的技术人」。他的技术朋友圈不是从技术社区里捞的,是从生活里长出来的。
不是说发帖找人不对。是说「朋友」这个词在这个语境里被用得太宽了。作者说的「developer friends」,Vicente 理解的「技术圈朋友」,Francis 实践的「在平台上认识不错的人」,build996 建议的「一起做一小时东西的人」——四种不同的关系,被同一个词盖住了。混在一起谈,你就会用数量去衡量一件没法用数量衡量的事。
build996 的建议最短,也最可执行:把第一次协作限定在一小时内,只完成一个能跑起来的小东西,不预设之后要成为联合创始人。切入点可以是纯文本游戏,或者故意做得很傻的 CLI 工具。初次交流留在公开评论区,这样更内向的人也能参与。
逐句读。
「限定在一小时内」——给协作设了一个超时。第一次协作最大的风险不是做不出来,是做得太久。两个人第一次配合,做上三天,中间一定会有一个人觉得「这人不合适」,然后不好意思说,然后拖着,然后这段关系就死了。一小时是个安全阀:做不完也没关系,反正就一小时;做完了更好,你们有了一个共同的成果。
「只完成一个能跑起来的小东西」——给成果设了一个下限。能跑起来,比做得漂亮重要。一个能跑的 CLI 工具,哪怕傻,也是「我们做成了一件事」的证据。这个证据比任何自我介绍都管用。
「不预设之后要成为联合创始人」——给关系设了一个上限。别一上来就谈长期合作。长期合作是结果,不是起点。你把它写进入口,它就从结果变成了压力。
「纯文本游戏或故意做得很傻的 CLI 工具」——给题材设了一个低门槛。为什么要是傻的?因为傻的东西不涉及品味之争。你做一个正经的 SaaS,两个人会在技术选型上吵架;你做一个猜数字游戏,谁都不会觉得自己的架构被冒犯了。
「初次交流留在公开评论区」——和 Francis 的边界是同一个东西。公开场合有旁观者,旁观者会让对话变得克制,克制是好事。
五条合起来,一份最小可行协议。把「交朋友」这个模糊的、没法执行的需求,拆成五个可以执行的动作。你把这份协议和作者的三个问题放在一起看,差距就出来了:作者问的是「你愿不愿意一起做项目」,build996 问的是「你愿不愿意花一小时和我做一个傻东西」。前者要一个承诺,后者只要一小时。
后者才能落地。因为一小时的门槛低到没人会拒绝,而承诺的门槛高到大部分人会在心里先算一遍「我跟他熟吗」。
跑偏的那一支:John 和搭便车
有一条我读的时候皱了眉。John Borghardt 介绍自己正在研究所谓潜认知系统与 SCI 引擎,几乎全部开发、写作和测试都在手机上完成,然后借机推广一个可去除 AI 生成内容和文本水印干扰的自制阅读工具。资料显示他是专注低延迟 C++ 引擎与嵌入式硬件的系统架构师。
我不怪他。一个系统架构师,在手机上做引擎,顺手提一句自己的工具,放在任何一个技术社区都不算过分。而且他前半段的自我介绍货真价实——低延迟 C++ 引擎、嵌入式硬件、手机上开发,信息量比评论区里大部分人都大。
但这条回复出现在这个帖子里,是错位的。
这个帖子的契约是「回答三个问题,或者回应别人的回答」。John 的回复只做了第一件事的一半——说了自己在做什么(第一个问题),没提技术之外热衷什么(第二个问题),没说愿不愿意合作(第三个问题),然后把话题转向自己的工具。这不是回答,是借位。
搭便车不是坏事,社区里很多有价值的分享都是搭便车搭出来的。但它有一个代价:它会把主线的注意力分走。一个正在找朋友的人,读到一条「我在手机上做 SCI 引擎,顺便推荐我的工具」,他的注意力会从「这个人能不能一起做东西」转到「这个工具要不要试试」。主线就断了。
这条分支我不多讲。任何一个开放的入口,都会有人从旁边进来。你写「欢迎各种背景的人」,你就会收到各种背景的回复,包括那些不打算回答你问题、只想借你人流量的人。不是他们的错,是开放入口的固有成本。你要开放,你就得接受这个成本。
设计意图与代价
读到这儿,把整条链收一下。
作者的显性需求是「认识更多开发者朋友」。隐性需求是什么?我猜。只能猜,因为帖子没写。
从那条推荐链看,隐性需求更像「找一个能长期合作的、最好是美国的朋友」。两个需求不一样。前者广撒网,后者精准猎。他用了前者的写法(开放、欢迎各种背景、三个问题),去要后者的结果(引荐、长期、美国人)。写法和目标不匹配,这是他所有麻烦的根。
广撒网的写法会吸引来广撒网的人,而广撒网的人不会给你精准的结果。Francis 给了他建议(去评论别人)、给了他信任(你是第二个知道的人)、给了他推荐(三个人),这三样没有一样是「长期合作」。Francis 自己在守边界,没有承诺任何长期的东西。
代价列一下。不列全,列我能看见的。
入口太宽,筛选太晚。三个问题一起问,第三个成了事实上的门槛,但它藏在最后,读到的人要读到末尾才知道「哦,还要合作」。你把筛选条件放在入口,会劝退一部分人;放在末尾,会让一部分人读到一半发现不合适,白读。两种都不理想,但后一种更浪费别人的时间。
条件写在请求方,推荐链必然失真。「最好是美国人」这个条件没有进入任何一次引荐的接口。Francis 推荐 Giorgi 的时候不知道,Giorgi 回应的时候才知道。这个失真是结构性的,不是偶然的。你要么把条件写进请求里让每个推荐人都看见,要么就别提这个条件。
把公开关系往私域搬,触发对方的防御。先问地点,再提 Telegram/邮件/WhatsApp,这个顺序在对方读来是「定位 + 拉走」。Francis 的拒绝是健康的,他守住了一个不变量。作者没读懂,后面继续要,要得更急。
第四个最大。把关系当成一个可以一次请求拿到的接口。关系不是接口,它没有签名,没有返回值,没有超时。你没法写一个 getFriend(american=True, longterm=True) 然后等结果。你只能一次做一件小事,做完看对方还愿不愿意做下一件。
前三条是操作层面的,可以改;第四条是认知层面的,改起来难。
我写到这儿有点犹豫。一个交友帖,被我拆成入口、边界、参数传递、不变量,这有点像拿读内核的姿势读一封情书。我承认这个错位。但你让我读完 27 条评论什么都不说,我做不到,因为这个帖子里出问题的地方,和我见过的太多代码出问题的地方,是同一类:接口定义得含糊,约束写在错误的一侧,然后在传递中失真,最后被最不该弹回来的那一方弹回来。
那三个问题,没人真正回答
回到开头。我打开这个帖子,是想看有没有人认真回答那三个问题。
读完了。27 条顶层评论,认真回答第一个问题的有几个,认真回答第二个问题的有两三个,认真回答第三个问题的——几乎没有。
这不是评论区的失败。这是三个问题本身的问题。
第三个问题要的是一个承诺,而承诺是没法在评论区里给的。你能在评论区里给的是「我愿意花一小时试试」,不是「我愿意一起做项目」。build996 看懂了这一点,所以他给的建议全是一小时的、傻的、能跑起来的东西。作者没看懂,所以他把第三个问题原样抛出来,收获了一堆「听起来不错」「有机会聊聊」和一条「我不是美国人」。
Vicente 也没回答第三个问题。他回答的是「我已经有两个朋友了,我挺满意」——他其实在说,这个问题我不需要回答,因为我已经有答案了。
Francis 回答了,但他答的是「你别问我,你去问别人」——他把问题退回了。
Hemapriya 的回应夹在推荐链里,但她说的是这个帖子里最接近正确答案的一句话:先参与 DEV 的欢迎帖和其他讨论,通过对话了解他人兴趣,和工作方向相近的人建立联系,不带立刻找合作者的压力地去认识人,更容易形成真实连接。资料显示她在 DEV 上每周五连载 Dev Opportunity Radar 系列——一个每周固定输出的人,说「先去参与讨论」,这话有分量,因为她自己就是靠持续输出被人认识的。
她说的其实就是 Francis 说的,也是 build996 说的:别把「找朋友」当成一个可以一次完成的任务。它是一个副作用。你做别的事,它顺便发生。你专门去做它,它反而不发生。
下一站
读完这一篇,如果你也想发一个这样的帖子,我给你三条明天就能做的事。
第一,把第三个问题删掉,只留前两个。「你最近在做什么」「技术之外你热衷什么」——这两个够了。第三个问题会自己长出来,长不出来的,你问了也长不出来。
第二,把「我希望对方是某某样」的条件,从请求里挪到理由里。别写「希望是美国人」,写「我为什么想找一个能长期合作的人」——把你自己的处境说清楚,让读的人自己对号入座。条件是筛子,理由是灯。筛子把人挡在外面,灯把人引过来。
第三,找一个人,花一小时,做一个傻东西。不用发帖,不用等回复,不用凑够 27 条评论。你在评论区里找一个说过「我最近在学 X」的人,回他一句「我用 Y 做过类似的东西,要不要一起花一小时做个更傻的」,然后做。做完你就知道这条路通不通,比读一百条「找朋友」的帖子都管用。
至于那个「美国人」——我最后说一句。你要找的是能一起做东西的人。这个条件,国籍不回答,学校不回答,在哪个平台加入的不回答。回答它的是那一小时里,你们俩谁先忍不住说「这个地方我们可以换个写法」。
那一小时,比 27 条评论都长。
