【问题标题】:Agile Scenario, which is correct? [closed]敏捷场景,哪个是正确的? [关闭]
【发布时间】:2009-07-15 16:14:54
【问题描述】:

假设您有需要实现方法的用户故事 1:

public static void MyMethod(string paramA);

几个类将使用此方法,而 MyMethod 会完成完成用户故事 1 所需的一切,但仅此而已。

您很确定在未来的迭代中会出现另一个故事(用户故事 2),这需要方法变为:

public static void MyMethod(string paramA, int paramB);

之前对 MyMethod 的调用需要重构,并且需要添加一些对 MyMethod 的新调用以满足用户故事 2 的要求(注意在故事 2 之后,仅使用 paramA 调用 MyMethod 是没有意义的)。

在处理用户故事 1 时敏捷思考:

1) 只实现:public void MyMethod(string paramA);

2) 实现:public void MyMethod(string paramA, int paramB); - 但现在不要对第二个参数做任何事情。此时调用将 0 传递给第二个参数。

3) 实现:public void MyMethod(string paramA, int paramB); - 但现在不要对第二个参数做任何事情。调用传入正确的值(根据用户故事 2 的预期)

4) 实现:public void MyMethod(string paramA, int paramB); - 所有电话都完全涵盖用户故事 1 和 2

【问题讨论】:

    标签: agile scrum


    【解决方案1】:

    只做1。

    重构很容易,但预测未来并不容易。

    项目可能已经完成,新的更重要的故事可能会出现,这意味着故事 2 永远不需要,当您到达故事 2 时,您可能会更好地理解问题并需要重构所有内容。您可能不需要它的原因有很多。

    【讨论】:

    • +1。雅尼。这是一个极端的例子,但原理是完全正确的。如果故事 2 中可能需要重构 10 种方法怎么办?
    【解决方案2】:

    一方面是敏捷纯粹主义者,他们坚持认为一切都可以通过以后重构来完成。另一端是老派的 Big-Design-Up-Front 人群,他们认为您应该首先构建一个完整的架构,然后将功能添加到它上面。你的问题是完美的,因为如果你盲目地遵循它们的过程,它就会暴露出两种哲学的缺陷。您想要的是最高效率。所以你需要分析你的情况是什么故事1和故事2。您的软件是否可以在没有 S2 的情况下交付,或者您是否只是拆分故事以帮助进行估算和规划?如果 S1 是“添加到购物车”而 S2 是“结帐”,那么不构建支持 S2 的接口是愚蠢的,因为没有它,您的软件将一文不值。在每个项目中,都有一组已知的“必备”功能,它们使您的软件甚至值得发布。如果您的两个故事都来自该系列,那么我会说现在构建界面以支持两者,并且以后不要浪费时间进行重构(#3)。

    通常,如果 S1 和 S2 都在必备集合中,它们将在 Backlog 上靠得很近。如果不是这种情况,那么您要么拥有大量必备品,而且您的项目不会使用敏捷技术获得那么多优势,或者 S2 真的不是必备品。因此,如果您期望在对 S1 和 S2 的承诺之间传递大量时间(几个月?),那么我将使用 1 参数接口。时间总是造成不确定性的巨大因素。

    【讨论】:

    • 我很喜欢你的回答。我唯一想说的是,S1 处于迭代 1 中,而 S2 处于迭代 2 中。我相信在每次迭代结束时都应该始终拥有可交付的产品。现在:经过一次迭代后,企业不太可能乐意交付产品,但它肯定可以进行 QA 并经过良好测试。那么,您的目标是提高效率并现在就去做(但由于需求和/或设计可能发生变化,您可能会出错),还是只做第 1 次迭代所需的事情?
    • 另请注意,我不相信在迭代 1 中做任何“错误”的事情。例如当故事 2 出现时,实施必须完全重新设计的东西是没有意义的。如果你知道接下来会发生什么,那就太疯狂了。但是您是否应该在 S1 中加倍努力,以便在 S2 出现时做最少的工作?还是你偏爱专注,也知道:“预测很困难,尤其是关于未来。” - Niels Bohr(丹麦物理学家)。
    • 我不会考虑向 S1 中未使用的方法添加参数来创建无法发货的产品。您可能会称它为不必要的臃肿,但肯定仍然有效。 Shippable 只是意味着 Done-Done;经过测试、记录、可构建和可安装。
    【解决方案3】:

    纯粹主义者会说选项 1,但我会听从常识,如果您绝对 100% 确信这是一项要求,那么我会将其纳入您的设计中。

    然而,敏捷也很大程度上基于重构,所以只要您不公开发布此接口,那么如果更改它不会影响我的设计,我实际上会选择选项 1。

    【讨论】:

    • 因此,如果这是一个不应该更改的公共 API,那么为故事 2(或 3、4...)实现是否有意义?
    • 是的,我个人会这样做。一旦发布了公共 API 就对其进行更新将是一个痛苦的世界。当然,你必须问自己为什么要向公众发布 API,因为它仍然会发生变化......
    【解决方案4】:

    “这取决于。”您如何回答很大程度上取决于您的团队的纪律性。

    您所描述的情况会导致越过这条线向滑坡迈出一小步,这会导致代码膨胀。台阶很小,以至于您不会注意到坡度。安全吗?可能,因为这是一个微不足道的例子。许多“继续下去没有意义……”案件更大。步骤越大,尤其是跨过 sprint 边界时,您猜错的机会就越大,最终导致工作浪费和额外未使用的代码。在包含大量死代码或未使用代码的系统中工作很糟糕。

    如果您的团队遇到代码膨胀问题,我会“将预期旋钮设置为零”一段时间,直到人们对在没有预期设计的情况下以小块构建系统的感觉有所了解。看到系统干净利落地发展是许多开发人员从未见过的。然后重新审视这个决定。与我共事的最有效率的团队将旋钮设置为零并保持多年。

    【讨论】:

      【解决方案5】:

      使用现代开发工具,将方法重构为具有第二个参数的成本非常低。因此,实施第一个故事似乎最有意义,然后在涉及到后面的故事时重新审视该方法。

      但是...就像所有好的问题一样,答案实际上是“视情况而定”。在某些方面,你的例子太微不足道了,无法公正地讨论。如果故事 A 是“更新客户名称”并且故事 B 添加了某种事务功能(也许 paramB 是 TX 上下文)怎么办。在这种情况下,您的故事可能需要一些工作。如果没有 B,A 是否有意义? A今天上午实施,B今天下午实施,还是B在下个月工作?

      【讨论】:

      • 或者 B 是一个可选参数,可能有一个默认值。
      • 是的,我不明白为什么它不是一个选项。这是为什么默认参数出现在函数末尾的一个完美示例,用于无影响扩展。然而,不想咬掉关于它的 Java/C# 与 C++ 的争论:)
      • 在这种情况下绝对不是可选参数。必须正确获取并设置此值以满足用户故事 2。也不希望这是关于语言使用的讨论,更高级的敏捷思维,但我同意你的观点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多