想象一下,你有一个用户故事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
答案 0 :(得分:12)
只做1。
重构很容易,预测未来不会。
项目可能是罐装的,可能会出现新的更重要的故事,这意味着故事2永远不需要,当你进入故事2时,你可以更好地理解问题并需要重构一切。你可能不需要它有无穷无尽的原因。
答案 1 :(得分:2)
一方面是敏捷纯粹主义者坚持认为一切都可以通过以后的重构来完成。另一方面是老式的Big-Design-Up-Front人群认为你应该首先构建一个完整的架构,然后将功能捕捉到它上面。你的问题是完美的,因为如果你盲目地遵循他们的过程,它会暴露两种哲学的失败。你想要的是最高效率。所以你需要分析你的情况中的故事1和故事2。您的软件是否可以在没有S2的情况下发送,或者您是否将这些故事分开以帮助进行估算和规划?如果S1是“添加到购物车”而S2是“结账”,那么建立支持S2的界面是愚蠢的,因为没有它你的软件就毫无价值。在每个项目中都有一组已知的“无与伦比”功能,使您的软件甚至值得发货。如果你的两个故事都来自那个故事,那么我会说现在建立界面来支持这两个故事并且不要在以后浪费时间重构(#3)。
通常如果S1和S2都在必备组中,它们将在Backlog上靠近。如果情况并非如此,那么你要么拥有大量必需品,而且你的项目不会使用敏捷技术获得那么多优势,或者S2真的不是必须的。因此,如果您期望在S1和S2的承诺之间传递大量时间(几个月?),那么我将使用1参数接口。时间永远是不确定性的重要因素。
答案 2 :(得分:1)
纯粹主义者会说选项1,但是我会听取常识,如果你完全100%确信这是一个要求,那么我会把它考虑在你的设计中。
然而,敏捷也严重依赖于重构,所以只要你没有公开发布这个界面,那么如果改变它不会影响我的设计,我实际上会选择选项1。
答案 3 :(得分:1)
“这取决于。”你的回答在很大程度上取决于你的团队的纪律性。
你所描述的情况会引发一条很小的跨越线路的滑坡,导致代码膨胀。这个步骤很小,你没有注意到斜率。安全吗?可能,因为这是一个微不足道的例子。许多“继续下去并没有意义......”案件更大。步骤越大,特别是如果它越过sprint边界,你猜错的可能性就越大,最终导致浪费的工作和额外的,未使用的代码。在具有大量死机或未使用代码的系统中工作很糟糕。
如果您的团队遇到代码膨胀的问题,我会将“预期旋钮设置为零”一段时间,直到人们感觉到建立一个没有预期设计的小块系统是什么感觉。看到系统干净利落是许多开发人员从未见过的东西。然后重新审视决定。我工作过的效率最高的团队将旋钮设置为零并保持这种状态多年。
答案 4 :(得分:0)
使用现代开发工具,重构方法以获得第二个参数的成本非常低。因此,实现第一个故事似乎最有意义,然后在后来的故事中重新审视该方法。
然而......像所有好问题一样,答案实际上是“它取决于”。在某些方面,你的例子太过微不足道,无法公正地讨论。如果故事A是“更新客户名称”而故事B添加了某种交易功能(也许paramB是TX上下文)。在这种情况下,您的故事可能需要一些工作。没有B,A是否真的有意义? A今天上午和B今天下午实施,还是下个月B工作?