The “How” (续) - 研发团队如何运转一次良好的迭代Sprint
前情提要:
- 从灵光一闪到全球发布:构建产品创新的“价值环”框架
- The “What” - 从迷雾到蓝图,锻造产品的灵魂骨架
- 系统架构 从_WHAT_走向_HOW_的锻造之路
- The “How” - 如何敲定MVP
我非常理解从“蓝图”到“大厦”的这个阶段,对研发团队来说意味着什么。这既是一场精密的工程协作,也是一场充满创造力的艺术实践。
我们跟随产品经理王五和架构师张三,完成了从“Why”的价值探索到“What”的产品建模。
现在,王五已经准备好了一份清晰、经过优先级排序的待办列表(Backlog)。工作场景从会议室转向了研发团队的“引擎室”。
让我们继续这个故事,深入Phase 3: The “How” 的核心,看看张三领导的研发团队是如何将这些用户故事锻造成坚实、可靠的代码的。
Phase 3: The “How” (续) - 引擎室的交响曲:研发团队的Sprint航程
如果说产品经理王五是这艘产品大船的“领航员”,那么研发团队就是让这艘船乘风破浪的“引擎室船员”。他们的工作远不止“写代码”那么简单。这是一场围绕承诺、协作、工艺和自动化展开的、为期两周(一个Sprint)的交响乐。
一:校准航向 - 待办列表梳理会 (Backlog Refinement)
在Sprint正式开始前,研发团队需要和王五一起,对即将开发的任务进行一次“战前预演”。这绝不是PM的单向灌输,而是一场充满互动的技术沟通。
我们看过很多团队,都是单向输出,原因多种多样,有些是因为产品经理独断专行不接受意见与询问,也有研发团队在评审阶段不足够投入。
事实上,有问题的团队可能是大多数。
-
理论知识: Backlog Refinement(或称Backlog Grooming)是一个持续的活动,旨在确保待办列表中的事项(用户故事)是清晰、可理解、可估算的。它的目标是消除歧义,暴露风险。
-
实操建议:
- 刨根问底: 工程师的职责是扮演“魔鬼代言人”。不断追问“为什么”,挑战需求的模糊地带,思考各种边缘情况。当然这对于团队的要求是高的。
- 拆分与估算: 将大的用户故事拆分为更小的、可独立交付的技术任务。并使用相对估算(如故事点)来评估其复杂性,而不是承诺精确的时间。
- 定义“完成标准” (Definition of Done): 明确一个任务在什么情况下才算“真正完成”,例如:代码已提交、通过单元测试、经过Code Review、在测试环境部署验证。
-
常见错误做法:
- “照单全收”: 工程师完全不提问,PM说什么就是什么,导致开发中途发现需求理解有误,造成大量返工。
- “拍脑袋”估算: 在没完全理解需求的情况下,草率地给出不切实际的估算,导致Sprint无法完成承诺。
- 忽略非功能性需求: 只关注业务功能,忘记了性能、安全、可观测性等同样重要的需求。
-
互动小剧场 1: “这个按钮真的只是个按钮吗?”
- 场景: Sprint计划会议室,白板前。
- 角色: 王五 (PM), 张三 (Tech Lead), 熊大 (资深后端), 小美 (初级前端)。
王五: (指着原型图) “…所以,下一个核心故事是‘用户关键词搜索’。用户在这里输入文字,点击‘搜索’按钮,下方显示结果列表。故事点估8分,怎么样?”
熊大: (摸着下巴) “王五,我有个问题。搜索结果需要支持分页吗?首次加载多少条?排序逻辑是什么?按相关性还是按时间?”
小美: “从前端角度,如果用户输入时,我们需要有搜索建议(autocomplete)的下拉框吗?这个原型上没画。”
张三: (在白板上画着) “很好的问题。王五,听起来‘搜索’这个功能比一个按钮要复杂。我建议,咱们这个Sprint的MVP是实现核心的关键词匹配和按相关性排序,不支持分页,一次返回前20条。‘分页’和‘搜索建议’我们可以创建两个新的故事卡,放到下个Sprint的备选池里。这样我们可以把这个故事的复杂度降到5个点,更有把握完成。”
王五: “完全同意!清晰多了。是我考虑得不够细。那就这么定了,我立刻更新用户故事的验收标准。”
二:绘制施工图 - 技术分解与C3设计
当团队承诺了一个Sprint的目标后,张三会带领团队进行更深度的技术设计。这是将C2容器图“放大”,绘制出内部C3组件“施工图”的时刻。
-
理论知识: 这是“Just-in-time”的设计。我们不是在项目开始前设计好一切,而是在每个Sprint开始时,仅针对当前要做的功能进行详细设计。这既保证了设计的灵活性,又提供了足够的指导。
-
实操建议:
- 白板协作: 这是白板(或在线工具)大放异彩的时刻。团队共同勾勒出组件、类、函数签名以及它们之间的交互。
- 定义契约: 如果涉及前后端或服务间交互,优先定义API契约。使用OpenAPI/Swagger或gRPC的proto文件,将接口的请求/响应格式固定下来。
- 识别风险: 在设计中,主动识别潜在的技术难点、性能瓶颈或外部依赖的不确定性,并制定应对策略(如技术预研任务)。
-
常见错误做法:
- “单干户”架构师: Tech Lead一个人把所有东西都设计好,然后像发命令一样分配给组员,剥夺了团队成员的参与感和成长机会。
- “纸上谈兵”: 设计过于理想化,没有考虑现实世界中的网络延迟、错误处理和并发问题。
- 忽略可测试性: 设计出的模块紧紧耦合在一起,导致后续的单元测试难以进行。
-
互动小剧场 2: “API应该返回什么?”
- 场景: 研发团队的公共区域,一块大白板。
- 角色: 张三 (Tech Lead), 熊大 (资深后端), 小美 (初级前端)。
张三: “OK,关于
/search
这个API,我们已经确定了请求参数是{ query: string }
。现在讨论返回的数据结构。”熊大: “我后端可以直接把Elasticsearch返回的原始JSON对象透传出来,这样最快,里面信息也全。”
小美: (皱起了眉头) “别!千万别!Elasticsearch的返回结构太复杂了,嵌套很深,还有很多像
_score
、_index
这样前端完全用不到的元数据。我每次都要写一堆恶心的代码去解析它。我只想要一个简单的数组:[{ id, title, summary }]
。”张三: (赞同地点头) “小美说得对,这是API设计的核心原则:为消费者设计,而非为实现者。熊大,我们需要在后端创建一个专门的DTO(Data Transfer Object),做一个‘防腐层’。将ES的复杂结构转换成小美需要的最简结构再返回。这样,即使我们以后把搜索引擎从ES换成Solr,只要保证这个DTO不变,小美的前端代码就一行都不用改。”
熊大: “明白了,是我偷懒了。创建一个
SearchResultDTO
,我来搞定。”
三:精工细作 - 编码与代码评审 (Code Review)
这是将设计图纸变成一行行坚实代码的核心环节。但“能跑”和“好用”之间,隔着一条名为“代码工艺”的鸿沟。
-
理论知识: 代码评审(CR)是现代软件工程的基石。它的目的不仅仅是发现BUG,更是知识传递、标准对齐、保证代码长期健康度的关键活动。
-
实操建议:
- 小步提交 (Small PRs): 保证每个提交(Pull Request)都足够小,只专注于一件事。一个几百行代码的PR,评审者愿意花半小时仔细看;一个几千行的PR,大概率只会得到一句“LGTM”(Looks Good To Me)。
- 测试同行: 提交代码时必须附带相应的单元测试。没有测试的代码,就是“耍流氓”。
- 建设性的评审文化: 评审的语言应该是建议性的、非批判性的。“你这里写得不对”应该换成“如果我们在这里用XXX方式,是不是能让代码更清晰/更健壮?你觉得呢?”。
-
常见错误做法:
- “代码警察”: 在CR中纠结于空格、换行等代码风格问题(这些应该交给自动化工具Lint去做),而不是关注逻辑和设计。
- “自我为中心”: 固执地拒绝同事的合理建议,把代码评审当成一场辩论赛。
- “死循环评审”: 两个开发者在某个细节上争执不休,来回修改了十几个回合。此时应该立即进行线下沟通,而不是在PR评论区“吵架”。
-
互动小剧场 3: “一次‘有温度’的代码评审”
- 场景: Git的Pull Request页面。
- 角色: 熊大 (评审者), 小美 (代码作者)。
小美 提交了她写的
SearchService
实现代码。熊大 评论道:
[评论1]: “Hi 小美,这块逻辑写得很清晰,赞!有一个小建议,这里你直接拼接了用户输入的
query
字符串到ES的查询语句里,这可能会有注入风险。我们可以用ES的‘参数化查询’来避免这个问题,安全性会更高。可以参考一下这个文档:[链接]”[评论2]: “另外,我看到
handleSearchError
这个私有方法里处理了所有异常。我们能不能考虑把‘连接超时’和‘查询语法错误’这两种情况分开处理?这样将来排查问题时,日志会更明确。”小美 回复:
“天呐,注入风险我完全没想到!多谢熊大哥提醒,我马上去改!第二个建议也很好,我把异常处理再细化一下。感谢这么细致的Review!”
四:自动化流水线 - 持续集成与部署 (CI/CD)
当代码通过评审并合入主干后,魔法开始了。一条自动化的流水线会接管一切,确保每一次变更都能快速、可靠地交付到用户手中。
-
理论知识: CI/CD(Continuous Integration/Continuous Deployment)是一套通过自动化来频繁交付应用的实践。CI确保代码可以被自动构建和测试,CD则负责将通过测试的应用自动部署到不同环境。
-
实操建议:
- 流水线即代码 (Pipeline as Code): 使用
Jenkinsfile
或.gitlab-ci.yml
等文件来定义你的CI/CD流程,使其版本化、可复用。 - 快速失败: 让流水线尽早发现问题。单元测试应该在最前面运行,因为它最快。耗时较长的端到端测试可以放在后面。
- “谁弄坏,谁修复”: A broken build is the highest priority. 任何导致主干流水线变红的提交,提交者都有责任第一时间修复。
- 流水线即代码 (Pipeline as Code): 使用
-
常见错误做法:
- “仅用于集成的CI”: 只有一套CI流程,但部署仍然是纯手工操作,充满了风险和不确定性。
- “脆弱的测试”: 自动化测试经常因为环境问题或不稳定的外部依赖而随机失败,导致团队逐渐对它失去信任。
- “漫长的等待”: 一次完整的CI/CD流程需要一个多小时,严重影响开发反馈循环。
从代码到价值
至此,一个Sprint的航程接近尾声。
研发团队通过这一系列紧密协作的乐章,不仅仅是交付了代码,更是将王五代表的用户价值,转化为了可触摸、可感知的产品功能。
这个过程充满了挑战、沟通、妥协与创造,它既是工程师的日常,也是一家公司创新能力的核心体现。