为什么强制执行YAGNI这么难?

时间:2009-09-16 14:33:22

标签: design-patterns yagni

我发现自己一直在打破这种模式。

  

YAGNI - 你不需要它

我只是一名初级开发人员,但我发现即使是高级开发人员也在做同样的事情。

  

“好吧,这个系统可能会使用它,而这个,所以让我们为它设计。”

有时,我会抓住自己,但大多数时候我会狂奔。有没有人有任何关于坚持YAGNI的技巧,或者我在设计和编码时能做些什么来更好地执行这种设计模式?

15 个答案:

答案 0 :(得分:24)

设计某物

...与

完全不同

设计一些东西。

设计某些东西意味着您正在构建应用程序以便将来扩展,以备需要编写代码时(这很好......这意味着您可以使您的软件可扩展且易于维护)。

设计一些东西意味着你现在正在写整篇文章......你是否认为任何人实际上都会使用它。这不一定是坏事,但这可能是浪费时间。

小心你正在做哪一个。

答案 1 :(得分:8)

这与完美主义有关。让它变得完美,让我们为所有可能的未来场景做好准备。

在决定需要的机会时,务实和清醒是有帮助的:然后回答“是”或“否”。也许是不是。

除非有明确的证据证明它是需要的(它已经在议程上,它已被客户要求),并且您认为最好考虑当前设计中的未来功能,暂时不予考虑。

答案 2 :(得分:6)

只需使用TDD !!!

很少你会发现自己正在编写一个你不需要的功能测试...

答案 3 :(得分:6)

因为YAGNI是一个原则,而不是灵丹妙药
软件开发总是在平衡许多要求。这不是要让一件事情做对,而是要让一件事情都不对。单凭YAGNII不会保存你的屁股。

从这个意义上说,YAGNI可以避免以下陷阱:

  • 当您需要编译器时,请创建编译器 - 而不是自编译编译器框架 (我们的力量 - 解决一般问题 - 也是我们的弱点)
  • 不要低估实施工作。
  • 不要高估申请的生命周期和要求的稳定性

平衡竞争要求很难。但这就是为什么 - 正如McConnell尖锐地指出的那样 - 软件开发就是工程学。

因为其他原则也是人,
其他原则原则 - 更基本的IMO - 是原则的最小意外复杂性的封装:实体的公共接口/契约应该比它的实现更简单 - 否则,为了正确地调用一个函数,我必须知道比我自己需要做的更多。有时,这意味着您的实施需要完成。

一个例子(也许不是很好):

/// Estimates the time required to comlete the batch.
/// If the time cannot be estimated reliably, the return value is -1
/// \returns [double] estimated time in seconds
double EstimateDuration(Batch & batch);

是一份简单的合同。 OTOH,

/// Estimates the time required to comlete the batch.
/// If the time cannot be estimated reliably, the return value is -1.
/// This function does not support looping batches (right now, looping
/// batches only run under a servicve account with no UI, so it's not needed).
/// Also, when the moon is full, the return value is -1, but an estimate 
/// is found in batch.JeffsEstimate. This value is used only by Jeff's core 
/// build script which runs roughly once a month.
/// \returns [double] estimated time in seconds
double EstimateDuration(Batch & batch);

合同,它是对实施的描述。 (有人可能会争辩说,问题是由于过度热心的YAGNI还是仅仅是糟糕的设计 - 但也许这是因为你YAGNI完全设计了)

设计没有伤害
敏捷的出现,“设计阶段”会有什么不好的名字。然而,要比没有计划更糟糕,你的计划确实是灾难性的。最大的危险不是真正糟糕的计划,而是试图预测每一个问题并改变要求。 YAGNI在这里非常宝贵。


毕竟他们是高级的 我不知道他们 - 他们的倾向可能是由于老派瀑布的灌输和对改变的恐惧。或者也许他们是老年人,因为他们知道自己的工作 - 他们已经了解了你现在比以后做的更多的部分,以及可以可以牺牲哪些部分来应对未来的不确定性。

答案 4 :(得分:5)

强制执行YAGNI是如此困难,因为我认为我们大多数人都被相反的问题所困扰,即找到一个过于复杂或脆弱的系统来重构我们想做的事情,但这可能是更加深谋远虑。找到中间地带可能很难。

一般来说,如果你发现自己在想“它可能需要[xyz]”,那么它应该明确地在你编码的内容中发挥作用。即使你不编码支持xyz,那么你应该以这样的方式进行编码,即重构xyz支持是可行的。然而,有时候这可能意味着制作比它严格需要的更通用的东西。知道在该路径上停留的位置可能只是与经验相结合的特定领域信息可以告诉您。

答案 5 :(得分:3)

“回归基础”和“简单就是好”是一些短语,提醒我只是继续完成手头的任务,并意识到为什么我要建立这个功能或增强,而不是进入过度工程或计划对于可能不会发生的一百万件事情。在我工作的地方,我的名字通常被用来描述过度工程或过于复杂的东西,例如。 “你JBed如何建立那个页面。”我试图更多地检查这一点,因为它有时候很有用,但不足以使它成为我的惯常做法。

以非技术术语写出要求有时也会有所帮助。这让我知道最后要展示的内容,而不是担心细节,例如系统的用户不太可能阅读我的源代码并模拟我使用的任何命名约定。他们关心它的工作原理并做他们需要的事情,并希望它能做到。

另一个要问的问题是,“他们真的要求这个吗?”并尽量减少人们对功能的假设。如果它不在列表中,则将其保留,但询问是否需要它。

答案 6 :(得分:1)

YAGNI真是个问题。作为高级开发人员,我们一直违反YAGNI。这真的是一个“需要”的问题。你需要它吗?定义“需要”。我已经看到了使用YAGNI教条开发的可怕的泥球。

不是说我认为YAGNI没有用......总是值得问“我需要这个吗。”

答案 7 :(得分:1)

如果您正在构建库/工具包/平台/框架,YAGNI具有不同的含义。

您无法确定其他开发人员将如何使用您的工具,有时设计灵活性更有意义,因此您的产品可用于更广泛的场景。向前兼容性也是一个重要的考虑因素。

YAGNI仍然适用,但“它”往往处于元功能级别,而不是功能级别。

答案 8 :(得分:1)

提醒自己您要实施的目标,而不是做更多。您可以使用

执行此操作
  • 明确写好的用户故事/要求。如果清楚地概述了您工作的“验收标准”,则可以更容易地判断某些内容是否存在。
  • 某人(也许是你自己)希望你能迅速完成任务。这迫使你确保你不会偏离轨道。
  • TDD
  • 结对编程,或接近它的东西
  • 每日站立(或更频繁),以确保你不会进入杂草

答案 9 :(得分:1)

好吧,昨天我遇到了同样的事情,和一位高级开发人员发生了激烈争执。我总是尝试设计“如果有人称之为,如果这会改变tomm等等怎么样?”他是另一个极端。 “只要让它工作和快速!”

答案就在他和我的方法之间。我们如何走到中间地带?在尝试制作一个人们会欣赏的“完美”设计之间,或者如果他们将来必须改变某些东西就会讨厌。

恕我直言,答案,至少在设计模块时,归结为面向对象编程的基本原则,比如定义清晰的界面。 接口应符合客户的要求。模块的主要接口不应该有任何“解决”任何东西,除了要求中的什么。至少某种程度的“褶边”由于“如果这种情况发生变化,明天需要它们等等”而被添加。

你计划放置的任何东西,因为你认为明天可能被其他人使用等等,必须争论几个小时!你应该有充分的理由为那些甚至没有名字的SOMEONE添加“免费赠品”!

我仍然需要这个问题的明确答案。也许来自一些设计了大型应用并且面对这种情况的建筑师100次:)

答案 10 :(得分:0)

以一种使未来功能更容易实现的方式设计应用程序是很好的 - 但在您需要之前不要实际实现这些功能。如何做到这完全取决于你正在进行的项目。

答案 11 :(得分:0)

我发现同行评论和同行编程有助于此。另一组质疑你的推理的眼睛很快就会发现你认为你需要的东西,但事实并非如此。

答案 12 :(得分:0)

如果您正在关注敏捷,那么您可以处理重要的事情,直到找到您不需要的东西。当你到达YAGNI的东西时,你应该有一个非常成品。然后由业务部门告诉你停止开发。

答案 13 :(得分:0)

YAGNI通常是事后的事。当“YAGNI”变得明显时,请确保你足够敏捷以移除“我”。

答案 14 :(得分:0)

我们公司有一条经验法则:当我们讨论设计新功能时,首先要回答的问题是“谁真的想要这个?”如果客户支持它,那么我们会尝试了解他真正想要的是什么,以及是否有其他方法可以解决他的问题(而不是添加新功能)。如果团队成员要求这个新功能他应该有充分的理由为了那个原因。性能问题和营销问题是其中之一,在我们向代码库添加一些新功能之前,我们再次尝试完全理解请求并讨论所有可能的替代方案。