在软件开发里,总有那么一类需求,没人会白纸黑字写出来,可你要是没考虑到,上线后一准儿会出事。

前几年,我印象最深的日常之一,就是 QA 同事满办公室追着开发报 bug。开发也委屈:“当初又没说要考虑这个啊!”很多时候,单元测试覆盖率明明到了 80%,QA 换个思路,照样能揪出问题。这些被漏掉的,往往就是“功能需求背后的需求”——BA 和 QA 觉得你理所当然会想周全,可偏偏就没写在验收标准里。

比如做一个 CMS 系统,需求里写着“新增文章”,但绝不会特意写上“防止表单二次提交”。这种藏在冰山下面的东西,只要没人提,就很容易被忽略,直到 QA 或者线上用户用一个 bug 告诉我们:这里还有坑。
这类藏在功能需求背后、默认开发应该考虑到的部分,通常被称为非功能性需求,有时也叫跨功能需求。下面就把工作中常见的几种梳理一下,顺便聊聊应对思路。
先说说互动体验里那些容易踩进去的坑。加载状态大概是我见过最容易被遗忘的需求之一。现在客户端的数据几乎都是异步加载的,如果没处理好 loading,网络好的时候页面会闪一下,网络差的时候就像卡死了一样,用户只会觉得这程序不太行。通常可以在前端网络请求库里加一个统一的 loading 拦截器,但要注意多个请求并发时,得用计数器来防止 loading 图标反复闪烁,不然体验反而更糟。
表单二次提交是另一个经典问题。QA 常会用极端手法,比如对着提交按钮一顿猛点,如果页面没做防护,后端就会收到多条重复请求。就算有成功或失败的提示,连着弹好几个,用户也跟着懵。解决思路无非几种:用满屏 loading 蒙层直接阻断操作;在按钮点击事件里加一个请求状态锁;或者由后端生成一次性表单令牌,既防重复提交,也防 CSRF。
输出格式化也经常被漏掉。需求告诉你展示数据,但怎么展示却不说清楚。数字要不要加千分位?字符串太长怎么截断?时间显示成“3小时前”还是具体日期?封面图是居中裁剪还是拉伸?这些细节不提前定好,QA 随便一测就是 bug。
请求用户确认和提示,专业一些的 BA 会拉上 UX 一起设计,但落到实现上需要对齐的地方还有很多。比如用户点了取消,界面应该回到什么状态?编辑到一半退出,数据是保留还是清空?提示是自动消失还是手动关闭?成功或失败后是跳回原页面,还是原地展示?这些交互细节全凭开发自己猜的话,不同模块的体验就会割裂,而统一性恰恰是 QA 最容易抓到不一致的地方。
安全更是一条不能碰的底线。权限校验是命门。修改 URL 里的资源 ID 或者 userId,就能看到甚至修改别人的数据,这种漏洞在遗留系统里并不少见。早年我甚至见过运营商因为权限没控好,被人薅走大量付费业务。只要系统设计了权限模块,每个新功能上线前,都得跟 BA 确认要不要纳入权限管理。
表单验证,前端和后端谁来做?为了体验,前端要有;为了安全,后端必须做。这点没什么好妥协的,所有用户输入必须经过后端二次校验,边界条件、类型、长度,一个都不能少。

SQL 注入近几年因为 ORM 框架的普及少了很多,但 XSS 仍然常见。核心原则就是一条:不要信任任何用户输入,包括 URL 参数。很多人只盯着表单,却忘了请求地址里的参数也照样能被构造。
文件上传背后其实是一连串的隐藏需求:允许什么类型、多大尺寸、能不能批量传、要不要预览、上传后怎么命名、图片视频要不要压缩……安全方面,必须拒绝可执行文件,并且要通过文件头判断真实类型,而不是傻傻相信后缀名。还有一个大坑:千万别用用户上传时的原始文件名直接存文件,应该用系统生成的唯一标识,再通过数据库记录下原始名称,否则后患无穷。
性能是另一把隐形的标尺。响应时间从来都是一笔糊涂账,需求文档里很少会写“这个功能必须在 500 毫秒内返回”,但真慢了,QA 和用户绝对不答应。需求分析时,至少得想清楚三件事:一是常规技术上的性能优化,比如 SQL 调优、静态资源压缩;二是这个操作到底适不适合同步做,像批量处理任务,就该让服务器异步执行,再通知用户去拿结果,而不是让客户端干等;三是跟第三方系统集成时,要避免循环调用的低效方式,尽量用批量接口,或者用非阻塞的请求框架。
实时消息通知也容易产生理解偏差。BA 和 QA 觉得消息数量和红点就该实时更新,可开发可能认为页面刷新一下看到就行。一旦真要实时,就得引入轮询、长连接或者 WebSocket,工作量完全不一样,需要提前说清楚。
游离数据是服务端开发的老问题。新建文章时,用户可能先上传了封面图,但最后放弃操作,图片就成了无人认领的垃圾。删除数据时,如果只删主表,关联数据留着,既占空间又影响统计。解决办法可以是:用户一进入编辑页就生成草稿,把上传的素材关联上去;或者设计回收站机制,先标记删除,确认后再彻底清理。

分布式系统里的延迟也很难完全消除。主从同步、静态资源 CDN 刷新,都有时间差。如果项目对文案要求严格,可能需要在界面上提示“信息可能存在延迟”,或者在前端加上重试和兜底策略。我经历过一个项目,图片上传成功返回 URL 后,前端要等 2 秒才能正常打开,最后不得不增加 onload 和 onerror 的重试机制。
还有一些容易被忽略的“其他”项。兼容性永远是前端头疼的事,现在讨论的不是 IE6,而是微信内置浏览器、各种安卓 WebView 的版本差异。哪些浏览器内核需要支持?能不能接受降级?比如老安卓机上 CSS3 动画跑不动,能不能只显示静态效果?这些得跟 BA 明确。
服务器端同样逃不掉兼容性。APP 发版不同步,API 一改,老客户端立刻就跪了。比较好的做法是 API 路径里带版本号,比如 /v1/your-api/{id},同时加上契约测试,保证改动不破坏老逻辑。
本地化和国际化,在跨国项目里是大事。多语言、时区、日期格式、货币符号、单位甚至标点,都得在项目初期定好方案,否则后面改起来成本巨大。
用户行为埋点现在也几乎成了标配。Google Analytics、Dynatrace 这类工具会在系统里埋点,侵入性不小。新功能上线前,得跟 BA 和数据分析师确认好需要采集哪些事件、用什么标签,提前规划进去。
最后想说,写这些,是因为自己在开发过程中踩过太多“我以为你知道”的坑。细节想得越周全,业务逻辑就越严密,返工也就越少。在敏捷团队里,很少有大而全的需求文档,很多隐性需求如果没在卡上写清楚,或者没体现在 AC 里,就得反复找 BA、UX 确认,沟通成本会一直往上飙。有时候跟 BA 对齐了,忘了同步给 QA,或者故事卡没及时更新,问题又会冒出来。
把这些非功能性需求从暗处拉到明处,对所有人都好。
立即登录