本节摘要:面对没见过的问题,第一反应不是敲代码,而是上战术板——把问题分解成可独立验证的子任务,把需求抽象成明确的输入、输出与规则。本节讲分解的四步法和抽象的三个动作,用一个完整案例演示从模糊需求到可编码规格的全过程。
Boss 战开场。前四章的装备、经验、副本、补给,现在要在一个没有攻略的问题上验收。本节是战术板的第一块:拿到问题怎么下手。这也是招聘面试里"系统设计"与"现场编码"环节真正在考的东西。
新手面对新问题发呆,多数时候不是因为问题超出能力,而是因为问题还是模糊的一团。"做一个背单词工具"——数据从哪来?谁在用?复习计划怎么排?"统计文章里的高频词"——什么算词?大小写算不算同一个?"高频"取前几?每个未回答的问题都让大脑无法启动,表现出来的就是发呆。
职业开发者的第一步永远是把模糊变精确。两个工具:分解处理"太大",抽象处理"太糊"。
第一步,写一句目标。用一句话说清最终交付物,写不出就说明需求还没吃透,先回去问清楚(自己项目就自问自答写下来)。
第二步,按数据流切。沿着"输入→处理→输出"的主干切分子任务,每个子任务是一个动词短语:读取输入、解析格式、过滤无效项、统计计数、排序取前几、格式化输出。按数据流切的天然优势是子任务之间有明确的交接物,做完一个测一个。
第三步,给每个子任务定验收。一句话写清"给它什么、应该得到什么":"给一行文本,返回小写化后的词列表"。
第四步,按依赖排序。从最独立、最基础的做起——通常是输入解析。先打通一条最细的端到端通路(哪怕中间步骤都是简化版),再逐个替换成完整实现。这条"细通路"策略与 3.2 节的最小可用版本一脉相承:先让骨架跑通,再长肉。
分解解决规模,抽象解决噪音。三个动作:
抽象的产物就是一段"接口说明"。以高频词统计为例,把需求抽象成规格:
函数: top_words 输入: 一段文本 str, 取前几名 int 规则: 词 = 字母数字串, 大小写不敏感, 以空白与标点分隔 输出: [(词, 次数), ...] 按次数降序, 同次数按字典序, 长度为指定值 边界: 空文本返回空列表
规格一旦写成这样,编码环节几乎变成体力活——这正是抽象的威力:把思考前置,把编写降级。
背景:小郑想给第二章的词卡做一个配套背单词工具。初始需求只有一句话:"帮我每天背单词"。她对着这句话发呆了半小时,一个字代码都写不出来。
操作:上战术板。目标句写成"一个命令行工具,每天给我出十个间隔复习到期的词卡,答对升级间隔,答错重置"。按数据流分解,产出任务清单(每项带验收):
T1 读取词卡库 验收: 给定卡片数据, 能全部载入并打印总数 T2 筛选今日到期 验收: 构造三张不同到期日的卡, 只返回到期的 T3 出题与判分 验收: 答对返回 True, 答错返回 False 并显示答案 T4 更新间隔 验收: 对的卡间隔按 1-3-7-14 升级, 错的重置为 1 T5 循环十题并汇总 验收: 跑完输出对错统计
排序后从 T1 做起,半天打通 T1 到 T5 的细通路(T4 先用"答对固定加一天"的简化版)。核心的 T4 最终实现:
LADDER = [1, 3, 7, 14, 30] def next_interval(reviews, correct): if not correct: return 1 # 答错重置 if reviews >= len(LADDER) - 1: return LADDER[-1] # 已到顶, 保持 return LADDER[reviews + 1] print(next_interval(0, True), next_interval(2, True), next_interval(4, True), next_interval(3, False))
3 7 30 1
结果:从发呆到细通路跑通用了一天,一周内完整版替代了纸质卡片。有趣的是,T4 的间隔阶梯正是她第二章手算的复习排程——抽象后的问题直接命中了已有解。
解读:回头看,她之前发呆不是因为不会写代码,而是需求里藏着一堆未决问题(词库哪来、答错怎么办、每天多少题)。战术板的价值是把这些问题全部暴露并逐个落成决定——决定做完了,剩下的才是编程。
变式:更大的问题(比如"做一个博客站点")用同样的四步法,只是分解多一层:先切成"文章管理、展示、评论"几个模块,每个模块再走一遍数据流分解。抽象的动作在每个层级重复。
⚠️ 常见坑:分解时按"技术实现"切而不是按"数据流"切——一上来就分"数据库层、接口层、前端层"。这种切法让每个子任务都无法独立验收,进度无法度量。先用数据流切出可验收的端到端通路,技术分层是通路跑通之后的事。
战术板用不好时,问题通常出在四种反模式之一。对照自查:
反模式一,按技术分层切。3.2 节已警告过——"先做数据库、再做接口、最后做界面"的切法让每个子任务都无法独立验收。数据流切法(先通一条端到端细通路)永远优先于技术层切法。
反模式二,过早抠细节。分解阶段去争论"这个字段用什么类型"是浪费——细节留给实现阶段,分解阶段的产出只有任务清单与验收标准。一条经验:分解阶段写下的任何具体代码,之后大概率会被推翻。
反模式三,任务粒度不均。清单里混着"搭建整个存储"与"打印欢迎语"两个量级的任务,前者必然烂尾。发现某任务是其他的数倍时长时,当场对半再切。
反模式四,漏掉异常与边界任务。清单里全是"正常路径",没有"输入为空怎么办""文件不存在怎么办"。补法是给每份清单强制加最后一条:列出三种边界输入并为它们定行为。这条任务往往半小时,却挡住了上线后的多数救火。
四条反模式共同的根源是把分解当成"列愿望清单"。分解的产出是可执行、可验收、粒度均匀、含边界的任务序列——四个定语各对应一条反模式的解药。