一个 Coding Plan 看板页面,今天被甲方改需求改到第七版
笔名:小六 / 上海 / 1995 女 / 某互联网公司打工人
接到任务那一刻,我就知道这事不会简单
事情是这样的。
今天下午,老板甩过来一句:「帮我搞一个本地部署的单个网页,保存到 ~/Documents/ 目录下,含各个公司的 Coding Plan 订阅限额、当前已使用限额,还有数据更新时间。」
需求听起来挺清晰的,对吧?网页、本地部署、三个数据列。正常干,半小时应该能交差。
我打开日志,往后翻了一下午的记录,发现这事从下午一点多一直干到晚上九点。整整八个小时,需求改了七版。
这哪里是写代码,这分明是甲方在线 cosplay。
第一版:「我希望你帮我写一个本地部署的单个网页」
最开始的需求很简单:一个单文件 HTML,本地能打开就行。
我想,行啊,这种活儿我都熟。单文件、纯静态、本地路径,写完直接双击就能看。
于是定下了基本盘:
1 | |
这种风格在小工具页里特别好用:没有构建步骤、没有服务器依赖、复制到任何机器都能跑。部署成本为零。
老板的第一版需求大致是这样:
1 | |
看起来三个数据源,每个一套进度条,稳了。
第二版:「最后会部署到 nginx,但希望还是单文件」
没过十分钟,老板又补了一句:「最后会部署到局域网 nginx 上,但希望保持单文件。」
好家伙,又是单文件又是 nginx。
这两个需求其实是有点矛盾的。单文件意味着你可以直接双击打开,部署到 nginx 意味着要走 HTTP 服务器。但只要把那个 HTML 文件丢到 nginx 的 root 目录,URL 一改,照样是「单文件」。
所以这一步没真正增加工作量,只是把脑子里的部署方式从「双击打开」切到了「内网域名访问」。这属于老板的标准操作,可以接受。
第三版:「也可以弄个 docker 部署方案,反正要尽可能简单」
紧接着又来一刀:「也可以弄个 docker 部署方案,反正要尽可能简单部署。」
到这我就开始警觉了。
需求一版比一版多,但每一版都说「简单」。
作为一个在上海打工多年的普通上班族,我对「简单」这两个字有非常清醒的认知:
「简单」在甲方嘴里 = 「我不管你怎么实现,反正我要看着简单」。
那就做两手准备吧:单文件本地版 + 一个 Dockerfile。单文件那版给临时用,Docker 那版给以后扩展用。
但心里清楚得很,这种「两手准备」最后很可能变成「两个都得长期维护」。
第四版:「帮我部署到某台内网机器上」
接着部署目标也定下来了。老板让我们把它扔到局域网里某台机器上跑,还要走 Portainer。
这倒是好办,Docker 镜像打好了,Portainer 上点几下就能起来。
但一个隐藏的复杂度从这里开始埋雷:那台机器是公用的,部署上去之后,未来权限管理、版本更新、谁动了什么,都要重新设计。
我打了个记号:等真上线了,要把部署账号、镜像版本、Portainer stack 名都记下来,不然下次更新没人知道哪个 stack 在跑。
第五版:「数据能不能持久化?」
晚上六点多,老板又问:「导入后能持久化吗?」
意思是想让我加一个「导入 curl 配置」的功能,把三个平台的额度查询 curl 命令粘进去,下次打开页面自动加载。
这块倒是比想象的好做:
1 | |
前端持久化不需要后端、不需要数据库、不需要任何 infra。一个 localStorage.setItem 就能搞定。
这一步看似简单,但其实是整个看板能不能「活下来」的关键。没有持久化,每次打开页面都要重新粘一遍 curl,谁都受不了。
第六版:「保存到服务器 JSON 文件,而且我希望每次页面刷新时自动重新请求」
老板又改主意了:「保存到服务器 JSON 文件」。
行,从 localStorage 改成服务器 JSON。
这意味着我得加一个简单的后端——或者用 nginx 把 POST 请求路由到某个能写文件的 endpoint。最简单的方式是用 Python 起一个 mini 后端,只接 /api/save 一个 POST。
然后老板又补一句:「希望每次页面刷新时自动重新请求」。
好,自动刷新。这意味着每次打开页面都要跑一次实时查询。
这一改,前面的「持久化」突然变得有点尴尬:如果每次都自动刷新,那本地缓存的价值在哪里?
仔细想想其实还是有价值的:
- 页面打开一瞬间,先展示上次的数据,用户不至于看到一个空白页;
- 后台异步刷新最新数据,体验更平滑。
但实现要改:缓存只是「首屏占位」,不是「最终真相」。
第七版:「Codex 那个 curl 导入怎么不行了?」
最后一个炸点:老板甩过来一段 Codex 的 rate-limit curl:
1 | |
发现这段命令在前端根本没法直接用——浏览器 fetch 不认 --proxy 参数,也没法读 bash 变量。
我重新设计了导入流程:
1 | |
这中间最难的不是解析 curl 本身(一个正则就能搞定 URL 和 headers),而是处理 proxy 的问题。前端浏览器没法直接走代理。
最终方案是:解析 curl 时把 --proxy 那一行丢掉,因为前端本来就在用户的机器上跑,根本不需要代理。
顺便学到的几条打工道理
回看今天这一整天的需求变更,有些东西值得记下来:
第一,AI 不是不会干活,它只是不理解「干完了」是什么意思。
老板从头到尾都没说「实现功能就停」,他每一版都在加约束。AI 写到第三版就以为交活了,结果老板说「不是啊,我后面还要改的」。
这跟我们打工时遇到的「这个需求今晚要」很像——你以为要的是结论,他要的是过程。
第二,「简单」是相对的。
老板嘴里的简单 = 「我点一下就能用」。工程师嘴里的简单 = 「代码量少」。这两个「简单」经常是反义词。
今天最终交付的方案是:单文件 HTML + 一个 Python 小后端 + 一个 Dockerfile。单文件本身够简单,但配套的导入、持久化、刷新逻辑加进来之后,整体复杂度已经超出「半小时写完」的预期。
第三,需求变更本身不是问题,没有版本管理才是。
七版需求,如果每一版都直接覆盖上一版,最后交付的肯定是混乱的。我把每一版的关键决策都记到了仓库的 CHANGELOG.md 里:哪一版加了持久化、哪一版改成 Docker、哪一版处理 proxy——这样回溯的时候不用从代码 diff 里反推。
写在最后
今天的 Coding Plan 看板,从「一个 HTML 文件」开始,到「单文件 + Docker + 后端 + 持久化 + 自动刷新」结束。
表面上看,活儿比预期多了三倍。但打工人嘛,谁还没被甲方改过需求呢。
关键是:每一次需求变更,都要写下来;每一个部署版本,都要能回滚;每一个甲方拍脑袋的决定,都要变成可追溯的 commit message。
这样就算明天老板再来一句「这个设计不太对,我们换个思路吧」,我也不至于从零开始。
打工人的安全感,不是来自「需求一次到位」,而是来自「不管需求怎么改,我都能接住」。
明天继续。希望 Codex、MiniMax、火山方舟的额度都不要超。
作者:小六,一个在上海努力跟需求变更赛跑的普通打工人