我们如何在仍然忠于敏捷的同时避免技术债务,即:避免违反YAGNI和避免BDUF?
通过马丁·福勒,通过史蒂夫·麦康奈尔获得技术债务
通过维基百科的YAGNI(我们将不需要它)
BDUF(前期大设计),通过维基百科
更新:为了澄清这个问题,我想我也可以这样说并保持我的意思:
"作为敏捷实践者,我们如何在每次迭代中的"快速和肮脏"(试图遵守YAGNI时无意冒技术债务风险)和过度设计(BDUF)之间找到正确的平衡?
解决方案
回答
我发现罗伯特·马丁(Robert Martin)的测试驱动开发
(TDD)方法有助于解决这些问题。
为什么?
- 我们只需要编写足够的代码即可通过下一个测试。
- 我认为可测试的代码更干净。
- 设计必须接受测试,以帮助保持设计的重点。
- 当我们确实需要更改(重构)时,我们就有可以依靠的测试
无论何时编写测试(之前或者之后),我都会写作
该测试可做出切实可行的决策。例如,我们选择设计A或者B是因为
A更具可测试性。
回答
这就是为什么编写轻松的"学术论文"总是比较容易的,这些论文谈论敏捷开发的优点,"最佳实践"等等。
这就是为什么我们会发现许多组成新软件工程技术的"合适的工程师"的原因。
流程很重要,保持最佳实践很酷,但在其他方面,常识可以推动设计流程。软件是人们开发的,因此YAGNI实际上应该是:
我可能不需要,但也许会,因为在我的具体业务/公司/部门中确实发生了此事,或者我将需要它,但是我只是没有时间,没有那么快又肮脏的技巧来赚钱并保持工作,否则我可能会需要它,而稍后进行重构将是一个痛苦,而这比现在从头开始做它要花费十倍的花费,现在我有时间了。
因此,请使用常识,信任它或者信任为我们工作的人们的常识。不要将每份学术论文都当作事实来证明,经验是最好的老师,并且公司应该根据自己的经验和时间来改进自己的方式或者做事。
编辑:顺便说一句,TDD与我们正在构建测试的YAGNI相反,甚至不知道我们是否需要它们。认真地,不要听学者的话!!没有神奇的方式来生产软件。
回答
XP的"传统"答案是重构与自动单元测试相结合。
但这从哲学上来说是一个非常有趣的问题。我认为我们无需避免技术债务,只需将其保持在可管理的水平即可。史蒂夫·麦康奈尔(Steve McConnell)的文章在这种平衡上比较好,因为类比起作用的原因是,只要我们接受成本和风险,并且技术债务也可以,那么在公司中建立金融债务是正常且可以接受的。
也许答案本身也在于YAGNI的原理。我们将不需要偿还技术债务,直到我们这样做为止,那时我们就是在进行重构。当我们在带有技术债务的系统区域中进行大量工作时,请看一下重新设计对短期差异有多大影响。如果足够使它值得,就还清它。麦康奈尔提出的维持债务清单的建议将知道何时进行此考虑。
我不认为对此有绝对的答案,就像许多事情一样,这是根据我们在每种情况下的经验,直觉和分析所做出的判断。
回答
当然,对于任何给定的项目,敏捷都会使TD降低吗?
我们正在实施客户想要的内容(即得到他们的反馈),这使TD保持在最低水平,
回答
几个星期前,根据我们在HanselMinutes上完成的定义,对技术债务进行了有趣的讨论。该节目的基本原理是,如果我们重新定义"完成"以提高感知的速度,那么我们将积累技术债务。必然的结果是,如果我们对"完成"的定义不正确,那么很可能会获得一份需要发布的项目清单,而与设计方法无关。
回答
看来,如果我们坚持"计划,做,调整,计划,做,调整"敏捷思想(迭代,迭代评论),则默认情况下会避免这些事情。 BDUF与敏捷评估和计划的思想恰好相反,以至于如果我们真的很敏捷,我们将不会自动成为BDUF。
发布和迭代计划会议的目的是确保我们在该迭代中为项目添加了最有价值的功能。如果我们牢记这一点,则可以免费避免使用YAGNI。
我会极力推荐有关敏捷规划的Mike Cohn书籍:
- 用户故事已应用
- 敏捷评估与规划
更新:在我们澄清了在一次迭代中避免使用YAGNI和BDUF之后...
BDUF ...如果在开始进行这项工作之前,我觉得没有明确定义某个功能,那么我将创建一个小的"功能"或者故事来说明所需工作的设计类型部分。因此,较小的故事的故事点估计值可能为1,而不是真实特征的故事点估计值5. 这样,设计便随时间进入了较小的故事中,我们将被迫着手进行特征本身的开发。
为了避免违反YAGNI,我将努力弄清楚客户对迭代中某个功能的期望。只做与客户期望相对应的工作。如果我们认为应该添加一些额外的功能,请为其创建一个新功能,然后将其添加到待完成的工作积压中。然后,我们会说服客户看到它的好处;就像客户会要求在某个特定时间点完成某项功能一样。
回答
我们似乎在说" YAGNI"意味着"快速而肮脏"。我没有看到。
作为一名敏捷程序员,我练习测试驱动的开发,代码审查和持续集成。
- 作为一个过程,测试驱动开发(TDD)是避免YAGNI的好方法。只是"可能有用"的代码往往未经测试且难以测试。
- TDD在很大程度上也消除了对BDUF的强迫:当过程是从坐下来开始做真正能带来价值的事情时,我们就不能沉迷于BDUF。
- TDD,作为一种设计实践,意味着大型设计将随着我们对问题的经验积累而出现,并重构实际代码。
- 持续集成意味着我们可以设计过程,以便可以随时随地发布产品。这意味着我们有一个集成的质量流程,该流程试图防止主线质量下降。
以我的经验,技术债务的主要形式是:
- 自动化测试套件未涵盖的代码。除了非常难以测试的非常本地化的组件外,不要允许这种情况发生。未经测试的代码是损坏的代码。
- 违反编码标准的丑陋代码。不允许这种情况发生。这就是为什么需要在持续集成过程中进行代码审查的原因之一。
- 气味和需要重构的代码和测试可以更轻松地进行修改或者理解。这是技术债务的良性形式。利用经验来知道何时积累和何时还款。
不知道这是否回答了问题,但是我很高兴写了它。
Troy DeMonbreun commented: No, that wasn't my point... "quick and dirty" = (unintentionally risking Technical Debt while attempting to adhere to YAGNI"). That does not mean YAGNI is only quick and dirty. The phrase "quick and dirty" is what I used to quote Martin Fowler in his description of Technical Debt
避免使用YAGNI是说吻的另一种方式。 YAGNI增加了技术债务。在避免使用YAGNI和保持较低的技术债务之间没有张力。
我想我可能仍会遗漏问题。
回答
只需做最简单的工作即可。我同意Ayende所说的敏捷性的关键是"经常运送它"。像这样的定期发布周期将意味着BDUF没有时间,并且还将阻止开发人员违反YAGNI。
回答
在我工作的地方,我相信我们避免债务的方法是快速循环整个周期,即向最终用户展示功能并获得表明应该推动测试的信号,或者拒绝说出问题所在给出更新的要求。通过在迭代中重复执行此操作,可以通过尝试这种方式找到有关用户所需内容的许多更改。
关键是要尝试做用户想要做的事情,因为做更多的事情违反了YAGNI并引入了BDUF,而一遍又一遍地完善需求的想法是敏捷的核心。