在编写代码或进行设计时,您会尝试在一开始就将问题概括化,或者尝试解决非常具体的问题。
我之所以这样问,是因为试图概括问题会导致事情复杂化(可能没有必要),另一方面,如果需求发生变化,扩展特定解决方案将非常困难。
我猜解决方案是找到一条说起来容易做起来难的中间路径。您如何解决这类问题?如果您在什么时候开始对其进行泛化,您知道泛化足够了吗?
在编写代码或进行设计时,您会尝试在一开始就将问题概括化,或者尝试解决非常具体的问题。
我之所以这样问,是因为试图概括问题会导致事情复杂化(可能没有必要),另一方面,如果需求发生变化,扩展特定解决方案将非常困难。
我猜解决方案是找到一条说起来容易做起来难的中间路径。您如何解决这类问题?如果您在什么时候开始对其进行泛化,您知道泛化足够了吗?
Answers:
当您尝试为未来进行设计时,常常会发现您对未来需求的预测是错误的。通常,当您真正了解需求的变化时重构比第一天就过度设计系统要好。同时,也不要用脚射击自己。当然有中间立场,并且知道哪里比艺术更重要。
归结为一个经验法则:少即是多。
您熟悉敏捷吗?YAGNI是敏捷的一大原则。我发现这是处理事情的最佳方法。
“您将不需要它” ……是极限编程(XP)的原则,该原则规定程序员在认为必要之前不应添加功能。罗恩·杰弗里斯(Ron Jeffries)写道:“始终在真正需要它们时执行事情,而永远不会仅仅在预见到需要它们时就执行。”
... YAGNI是XP实践“做可能可行的最简单的事情”(DTSTTCPW)背后的原则。它旨在与其他几种实践结合使用,例如连续重构,连续自动化单元测试和连续集成。在不进行连续重构的情况下使用它可能会导致代码混乱和大量返工。连续重构又依赖于自动化的单元测试作为安全网(以检测不可预见的错误)和连续集成以防止更广泛的集成问题。
即使结合支持实践,YAGNI也不被普遍接受为有效原则。XP最初定义的一部分就是需要将其与支持实践相结合,而不是单独使用。
我花了一些时间对设计的总体方向进行前瞻性思考-并不是太多,但足以基本勾勒出高层次的概述。然后,我遵循一种基于故事的敏捷方法,该方法使用TDD为各个故事开发解决方案。当我通过TDD进行实施时,我会牢记高级概述,或者(a)指导我的特定实现遵循高级概述,或者(b)根据(基于)重构(并改进)高级理解/指导我在测试/实施过程中学到的东西。
我认为不做任何预先计划是一个错误,但是做太多事情可能是一个更大的错误。我想让我尽可能多地从整体上指导我,然后让设计按照我在应用程序开发方面的想法一直有机地发展。通过使用TDD,我发现设计本身被迫遵循更好的设计原则(去耦,单一职责等),并且与变更相比,如果我尝试预先构想整体并使开发适合其中,则更具延展性。
好的设计可以适应未来的变化,因此绝对值得。考虑UNIX操作系统及其“一切都是文件原理”。做出该设计决定不是为了满足当前的需求,而是为了将来的需求。人们不禁思索基于“敏捷”设计的操作系统的外观。
设计为“现在+1”。这意味着,解决眼前的问题,并构建足够的功能,以便下次他们要求更改时,您已经完成了一半(或更多),并且可以选择a)立即解决它,然后稍后进行重构,或b)再次解决“现在+ 1”(“现在”完成一半)
这确实取决于项目,简而言之,经验将教您“ +1”是什么。
YAGNI的理念,“您将不再需要它”可以用(从本文中)总结:
那些主张使用YAGNI方法的人认为,目前暂时没有必要但将来可能会编写代码的诱惑有以下缺点:
- 花在添加,测试或改进必要功能上的时间。
- 必须调试,记录和支持新功能。
- 任何新功能都会限制将来的操作,因此现在不必要的功能可能会阻止以后实现必要的功能。
- 在实际需要该功能之前,很难完全定义其功能并对其进行测试。如果未正确定义和测试新功能,即使最终需要它,也可能无法正常工作。
- 它导致代码膨胀;该软件变得越来越大,越来越复杂。
- 除非有规范和某种版本控制,否则使用该功能的程序员可能不知道该功能。
- 添加新功能可能会建议其他新功能。如果还实施了这些新功能,则可能会导致滚雪球效应的滚雪球效应。
我坚信要为眼前的问题进行设计,而不是通过试图猜测所有需要满足的情况来夸大您的设计,因为“总有一天我们可能会需要它”。
基本上,给出特定要求的列表,然后针对该要求进行设计,但这并不意味着您不应该:
设计“可能的期货”的主要问题是您总是在猜测。可能会进行有根据的猜测,但是“当推到推挤时”仍然只是一系列猜测。
通过这样做,您也很可能会挤压您的解决方案以适合一般情况,而不是解决您的已知要求所定义的特定问题。
那是什么意思 “当你只有锤子时,一切都开始看起来像钉子。”
我希望每次听到有人说:“但是这种解决方案更适合我们将来可能遇到的一般情况,所以我为此付出了一定的代价。”