一个评论功能的诞生:不是技术问题,是决策问题

实验室主理人 ·

上周我给自己的博客加了一个评论功能。这篇文章不是技术教程——GitHub 上能找到一百篇。我想写的是那些技术教程不教的东西:在写第一行代码之前,那些耗时最长的讨论

起点

我的博客叫 AI 成长实验室(AIGrowLab),一个 Astro 6 静态站点。之前只有一个 Python 写的页面计数器 API。加评论功能看起来很简单:不是有现成的 Disqus 吗?或者 Giscus?为什么不自建?

我有三个理由不想用第三方:

  1. 一个中文个人站——Disqus 加载慢、有广告、破坏暗色主题。Giscus 和 Utterances 需要 GitHub 登录,我的读者不一定有
  2. 我要数据——评论是优质内容,我不想交给第三方
  3. 项目已经有自建 API 的架构——零依赖 Python + SQLite,加个端点而已

好,自建。那该讨论什么了?

第一个问题:用什么语言写?

项目是 Node.js 的(Astro),但后端 API 是 Python 的。我的 AI 助手问:要不要统一成 Node.js?

这是典型的”架构洁癖”问题——统一当然”更干净”,但代价是什么?

分析下来发现:

  • 统一到 Node.js 的好处:一个运行时、一个语言
  • 停留 Python 的好处:现有代码已在生产运行、smtplib 零依赖、部署不需要 npm install
  • 关键差异在部署:Python 文件复制到服务器就能跑;Node.js 方案需要服务器编译 better-sqlite3 原生模块

最后结论:评论功能先用 Python 上,后续有空再考虑统一。这就是典型的”不要为了未来可能需要的整洁,牺牲今天的交付速度”。

第二个问题:要不要用户身份?

这是耗时最长的讨论。一圈一圈地递进:

第一轮:不要身份,匿名评论。

太简单了?没安全感。作者重名了怎么办?填了邮箱下次怎么找回自己的评论?有奖励活动怎么联系用户?

第二轮:轻量身份,Cookie + 可选邮箱。

Cookie 识别同设备,邮箱做跨设备锚点。但邮箱不验证的话,随便填一个就行,那锚点有什么意义?

第三轮:邮箱验证码。

填邮箱 → 发验证码 → 验证通过 → 评论发表。这确保了邮箱的真实性,但流程多了一步,用户可能会流失。

第四轮:两层并行。

  • 不填邮箱:游客身份。填名字 + 内容直接发表,Cookie 识别同设备下次自动预填
  • 填邮箱:用户身份。需要验证码验证,验证后 Cookie + 邮箱双识别

用户自己选择走哪条路。这是最终的方案。

第三个问题:跨设备合并需要验证吗?

设计初期有一个漏洞:如果用户 A 的邮箱 alice@b.com 已验证,用户 B 在另一台设备上随便填 alice@b.com——系统直接认为他是 A,不用验证。

原因是逻辑写成了”只看邮箱是否在数据库里已验证过”,而不是”看当前请求能否证明是本人”。

修复:把判断依据从 邮箱是否已验证 改为 Cookie 能否证明是同一人。跨设备即使填对了已验证的邮箱,也要重新验证。

这个讨论让我意识到:技术上的”简化”(少验证一次)恰好带来了安全上的”简化”(容易被冒充)。简化要找对方向。

十个提问,一行代码

整个过程中,我几乎没怎么写代码(至少 AI 助手写了大部分)。但决策过程花了超过 30 分钟——一个功能一个功能地确认、一个问题一个问题地追问。

这些讨论的顺序恰好是自外向内的:

  1. 用什么语言?→ 框架层面
  2. 要不要用户身份?→ 产品层面
  3. 要不要验证码?→ 体验层面
  4. 跨设备要不要验证?→ 安全层面

越往内层,越容易被忽略。但越往内层的决策,越影响用户的实际使用体验。

一些反思

  • 技术选型的真正成本不在开发,在部署。 Python 零依赖 vs Node.js 需要编译——这个差异决定了最终选择
  • 用户身份的设计本质是信任模型。 你信任什么来证明”你是你”?Cookie?邮箱?验证码?每种选择都有代价
  • 不填邮箱就发表评论,这个”偷懒”通道恰恰是最重要的设计。 它保证了评论功能的门槛足够低

如果你在为自己的项目设计评论功能,我的建议是:先想清楚你的用户是谁,再决定让他们付出多少验证成本。


附:整个评论功能的实现过程已经记录在项目的 git 历史中,包括所有被推翻的中间方案。

📖 本文已被阅读 --

评论

加载中...

支持 Markdown 语法