【改善软件组迭代】针对当前迭代问题的解决方案(核心结论部分)

前情提要:
这是在我 7 月又一次遇到一个很可能延期,并且没有依据的目标后
开始整合以前对一些独立问题的看法, 尝试从整体层面系统分析问题的过程
(之前试图解决的具体问题“开发流程规范”\“测试方式”\“协作开发”,避免不了整体上的恶性循环)
旨在将我们在最终节点才集中暴露各种的问题,以及不断的延期, 这种让人焦躁的开发过程
转换为规划内, 按部就班完成目标过程

这里不尝试用完美解决方案, 解决不同场景所有事情
我们面对的很多问题, 并假设了一些”理想情况”
我目的是, 趋近其中可以达到的部分, 只解决部分问题, 改善境况, 并且不带来明显副作用
所以, 这里不预设特殊的场景, 也不默认适用所有问题, 各组情况各有不同
我刻意忽略了资源限制,这是没啥好谈的客观因素。但要理解,下面指出问题时,意不在归责。
以下谈到的”产品”,”开发”, “测试” 不对应人员, 而是当前制度, 该角色所对应的职责

因为原文太长,这里减少了例子和推导过程, 单独把核心部分摘到最前. 如要细致的了解前因后果和分析过程, 可以在下面找到原文.

一. 以 干 -> 枝 -> 叶 的方式迭代软件

目前的问题

项目 A 正式开始于 xx 年 xx 月, 最早目标 xx 年 xx 月, 之后推到 xx 月、 xx 月、 xx 月.
项目 B 在 A 的基础上, 开始于 xx 年 xx 月, 之后推到 xx 月、 xx 月、xx 月、 xx月.

我们会有一个目标, 然后无法达成, 不断延期.

原因

  • 客观:
    软件涉及不同组不同领域 (CE,CS,Tracker,OA,FC,Gimbal,Captain,MediaServer,APP,Web…)
    不同组内又有细分模块
  • 整体上: 初期无目标和规划, 由开发自行发挥, 然后在软件大致达到某个程度后, 制定一个最终节点.
  • 各组开发实现上: 每组自行划分内部模块, 开发单位是一个个细分模块, 在较完整的完成某个模块后继续下一个模块.
    最终节点前, 都没有以完整产品方式, 整合支撑产品的主干部分

假设在画人, 只有几根线条的火柴人是简陋但完整的产品.
各组采取的方式, 是自行各画各的
APP 组画手掌. 当时的迭代方式, 手上别说五指, 皮肤纹理都快画出来了. . 但与其他组整合后, 却非常不协调
(连接模块, 我们做了 WiFi + RC 10 个左右的引导页面和其他各辅助功能, 实际核心只有”判断飞机是否连接, 提供入口”)

前者导致我们耗费巨量时间, 沉浸于不以产品化为目的的功能实现中(锦上添花做太多, 核心却不完善, 最后砍功能保发布时间)
后者导致我们各组各模块整合后, 以整个产品为视角, 臃肿且错漏百出(每个模块遗留的零星问题, 整合后是花两个月才勉强跑通的飞机基础功能)

方案

以: 干 -> 枝 -> 叶 的方式, 阶段小目标, 快速迭代 | 代替: 模块A -> 模块 B -> 模块 C, 只有一个最终发布目标, 长周期迭代
(比如连接模块, “实现连接” 是主干, “用户引导”为其中一枝, “友好的交互”与 “精美的UI” 是枝上的叶)
(主干完成后, 每个小版本都是可以上线的完整产品, 区别在于功能丰富度)

第一个目标, 画完整但简陋的火柴人,验收
第二个目标, 给手上加手指, 脸上画五官轮廓,验收
第三个目标, 手上加纹路, 描个睫毛,验收

发布前: 添加一些修饰

ps. 实际上就是目前有 1.0 后, 定期更新产品功能的迭代方式

实现:

  • 一月一周期: 目标 -> 需求 -> 开发 -> 测试 -> 修改 -> 验收 -> 根据验收结果和整体情况提出下一期需求
  • 需求提出 & 目标定义:
    • 由: 某功能块的完整需求;                改为: 这个月末 能实现 的需求 (一个功能块需求拆分多个阶段, 只计划能实现的部分)
    • 由: 不同组 自定的完成某块功能;    改为: 这个月末 软件整体 要达到的目标
  • 以上线的标准迭代(各模块结合): 每月开始前定下目标和需求, 2~3 周开发, 1 周测试及修改. 每月发布版本
  • 验收 整理上一阶段的产品成果, 结合整体进度, 修正 调整 后 作为下一周期的目标提出

优势:

  • 每次面对的事情体量小 + 周期短:
    复杂度低(很多问题的原因在于复杂度太高), 包袱小(灵活应对需求变更, 外部变更)
    及时反馈(达成目标的正反馈 及 产品复视), 及时调整(开发功能紧贴主干)

  • 初期迭代后, 永远有上一个稳定版本 backup
    适应 demo, 发版, 生产. 不会被外界临时需求打乱节奏, 各功能开发能有基础稳定的平台

  • 完成进度明确
    各组纸面上的完成进度落实为实际产品进度

可预想的缺陷:

  • 理论上耗时
    理论上增加时间为每个节点以产品标准验收的时间(验,测, 改)
    实际上, 我们功能需要的开发时间, 远比实际用的少.
    多出来的时间在各种无规划的来回折腾, 各组联调, 被砍的功能等.
    好的迭代可以 更早 的拿到一个 可能 简陋, 但可用/发布的版本.

  • 规划要求高:
    我们团队不具备拥有各组知识, 能细致定义阶段目标从而导向最终目标的人才
    拆大节点能胜任, 但拆成一月一节点, 将一件事情分成几个阶段. 每个节点间逐步 递进 而非 相互影响/冲突, 并且各组 协调统一

二. 有依据的软件目标

存在的问题

项目 A : xx月 -> xx月 -> xx月 -> xx月 -> xx月底 -> xx月 -> xx月 -> xx月 的延期情况
项目 B : xx月 -> xx月 -> xx月 -> xx月 -> xx月 的延期情况

上下脱节
制定者脱离 “实际情况”,
开发者会做不切实际的承诺(比如 xx 年 xx 月), 并且无法理清”实际情况”

实际情况: 当时环境, 当时团队, 当时制度下,较为趋近的应有产出

原因

目标制定角度:

  • 什么时间节点, 发布带什么功能的产品由外部因素决定(市场机会, 投资方要求等) 达不成目的的产出, 用再多时间, 做得再好没意义
  • 一个急迫的节点, 用于激发员工主动性

前者, 从最后结果来看, 有弹性空间, 结合前面迭代带来的中间版本及”实际情况”, 可以有更合理的节点.
(ps. “在事实上” 无法达成的节点, 不论目的是什么, 也没有意义)
后者, 长期多次达不成的目标带来的负反馈, 实际影响大于收益

开发角度:

  • 完成产品实际需要的产出, 与开发理解的职责不匹配

    开发倾向于理解的职责是 “做功能” (在承诺/安排的时间内, 把 我的 功能做出来. 只要一直在做, 没偷懒就”尽职”)


    实际要达成产品目的, 远不止于敲代码:

    • 一者, 开发”做”了很多东西, 是否都是当前阶段&达成目的的需要
      (目前没有”阶段”, 并且如上文连接模块, 早期真的做了很多非必要内容)
    • 二者, 各组资源需要统一(核心功能几乎都是跨组的), 整体有先后着重, 开发需要分析,验证,拆分提供参考信息
      但这在实操中, 相对于”写代码”是花时间且无直接产出的”不务正业”
      (对于 Leader, 有很现实的抉择, 投入时间做规划和管理、策动他人带来的效率, 可能不如用于开发带来的产出多)

方案

  • 制定的目标先明确是”手段”还是”目的” (长期达不成的目标有副作用)
    若是后者, 避免迎合式的承诺(定个日期问能不能做到), 得要求给出依据, 周期性”质疑”可行性(询问怎么保证完成, 当前进度, 需要完成的事情, 不确定的事情)(”质疑”在表达方式上有很大操作空间, 但目的是确保日期真的有依据)
    (即使是 APP 这种大部分只有业务复杂度,少有技术难度的, 也无法直接提供靠谱预估, 都得逐步细化才能确定.
    直接给出时间,多是简单想了一下, 迎合目标”尽力而为”)


  • 分离职责: 引入 产品/项目经理, 不同 产品/项目经理 分管一个/多个功能
    • 向上负责确保进度, 实时反馈进度作为外部决策参考, 帮助制定合理目标作为内部宏观节点
    • 向下负责协调各组资源, 获取信息, 更新进度, 做目标规划
    • 由这个经理将开发的”写代码,做功能”引导到实际产品产出上, 并协助上层确保制定可行的目标及做好进度管理, 输出《进度报告》

      (当前,各组力不使一处, 等资源, 跨组联调是耗费时间的部分原因(甚至能超出开发时间的 2~3 倍),
      开发的东西过度细化, 不是阶段性主线需求是另一部分原因(当然,我们之前没有成功执行的阶段目标)
      我们所有主要功能, 都涉及多组多个模块
      开发比起”要资源”更愿”把涉及自己的部分做了”(可以要求, 但解决不了问题, 还容易产生”他组不配合”,”对方傻逼”的长期负因素))

  • 以前面周期迭代方式, 要求开发定期提供产出, 将纸面预估在短期落实,转成真实进度, 并及时修正, 保持功能紧贴主干

三. 让问题解决在发生之前

我要讲述的最中心的点, 包括上述的 迭代, 目标 都旨在将堆积于发货前的问题往前推
避免发货前, 爆出大量问题, 不断延期的情况.

一个小抱怨

每次发版前期, 随着时间不断逼近, 问题大量爆发和需求不断修改. 会让人极焦虑和烦躁, 是感觉一切都不在掌握的时刻.
而这之后还会伴随不断向后延期的负反馈.

例如这次, 为了避免需求修改, 提前两月要求产品审视需求. 为了避免预料之外 bug, 提前一月半准备好要求测试验收代码.
但问题依旧, 发布前一月提出要加入 vip 功能, 前一周还在修改需求细节. 前一月验收出的严重问题,没有发布前一周多.
正如之前(某个事情)突然要提供的 APP; xxx月发版, 前一周还没进过验证的xxx; xxx发版, xxx突然决定再加个功能.

分析

结合上述 迭代目标, 我尝试将视角往上放到 ”问题/变化” 本身
引起 “变化” (意料之外问题_需求_事情) 的因素:

  • 外界相关:
    • 市场要求:
      • xx年xx月也许是面向市场最好的时机
      • xx年是直播的风口, 而我们刚好做了直播的项目,所以要加入直播
    • 投资要求: 某个时间节点发布的 Demo/产品 可以获得很好的融资机会 …
  • 行为相关: 在最后一刻发现的软件问题或新增的定义
    • 发货前有人开始使用产品了, 因此发现了产品的种种不足之处
    • 发货前需要验收产品了, 所以找到了很多问题
    • 某个用户反馈 bug, 所以我们需要在这版临时加入

前者属于客观限制, 略
后者属于因为某个行为触发,而发现的问题, 那么我们是否能让这些行为提前?如果这些事情发生在宽裕的时间下?或者都在预料之中呢

为什么难以应付(压力,焦虑)这些变化:

  • 负担重: 我们背负了从开发开始, 到发版以来所有功能. 这是为什么要优化 迭代
  • 不在预料之中: 面临的事情超出计划, 已经紧张的目标日期新增要解决的问题, 这是上述的目标

怎么解决”变化”本身: ↓

方案

  • 对于”行为相关”带来的问题:
    1. 以“短周期,多次迭代” 方式, 让影响产品需求, 发现问题的事情提前发生
    2. 增加每个阶段目标后的评审复盘

1+2: 迭代 对产品, 开发, 测试的另一层目的:

  1. 让直接负责项目的各角色(产品, 开发, 测试), 更早的以产品上线角度审视产品, 发现问题.
  2. 约束各角色, 让其职责直接对应发布结果

我们会在发布前才提出新需求, 被发现功能缺陷. 是因为产品和开发只对中间过程负责
(比如产品在功能做完后, 可以一直不审视做出来的功能(因为没有节点, 没人要求)直到发布前被发现问题, 并且随时可以根据需要修改, 而不考虑发布时间, 因为这个角色不直接面对发布时点)

我们愿意在发布前, 改需求, 换实现, 不限时间的测问题, 并将产品不断延期, 是因为我们只有 **一次机会(最后期限,要发货了,必须加)**, 无法推却.
(一款已经到上线时点, 并且还存在对用户而言难以接受问题的软件, 我们只能匆忙做修改)

所以, 人为, 先制造 ”下一次” -> 然后做约束:
本次版本: 不允许产品提出规划外的需求, 不允许开发上线不通过/不在预期的功能, 约束内容复杂度, 并要求规定时间系统的测完.
然后复盘评审版本结果(哪部分没做到位)
以此约束, 促进需求提前完善和审视, 让开发功能贴紧主干
结合 二.目标, 解决”变化”, 将结果由无人直接负责的延期, 改为与各组职责挂钩.

  • 对于外界因素导致的变化. 只做期望, 不提方案
    提前两月预估外界变化
    对于市场变化和投资情况, 我无从把握. 只能想象期望有个”大规划师”, 提前两月洞察外界环境, 及时作出战略变动.
    但我们能做的: 比如知道有 CES, 预规划版本; 要小批发货, 提前增加”限定版”需求. 这是遇到事情, 向后看容易做到的规划.

  • 剩余的”变化”, 在我们包袱很小的的情况下有能力很好的应付


整个软件组角色、流程捋下来, 很有意思

产品做好了需求定义, 但不直接负责工程周期, 会在发布前一周,几天,还聚焦需求优化.
开发做出需求的功能, 但少和他组协同完成目标, 也不以整体软件为直接目的. 少有促进整体软件效率的”额外工作”, 没动力维护进度.
测试反复一遍一遍的测试问题, 但没有系统化测试&分析工具及全面的用例, 新老问题总会不断出现.
没有人逐级拆解目标, 协调各组资源, 做整体规划

结果是,
产品经理能定义出交互优秀,用户满意的复杂需求. 但产品出不来
开发可以做出细致,代码设计合理稳定的独立功能. 但产品出不来
测试会不辞辛苦, 反复测试问题,配合开发排查 .   但产品出不来
目标可以很准确, 抓住市场和公司发展的时点.   但产品出不来

不同角色有各自定义的”职责”, 每个人在做好 ”自己理解的职责“
但这些”职责”组合起来, 不达成最终目标
(部分偏离,部分缺)

这里面存在 职位&职责设计达成产品需要的产出 不对等问题