代码之家  ›  专栏  ›  技术社区  ›  bitbonk

固体对亚格尼[关闭]

  •  62
  • bitbonk  · 技术社区  · 14 年前

    我听到的最常见的争论之一就是不遵守 SOLID 面向对象设计的原则是 YAGNI (尽管论述者通常不这么说):

    “我可以把功能X和功能Y放在同一个类中。很简单,为什么还要添加一个新类(即复杂性)。”

    “是的,我可以把我所有的业务逻辑直接放到GUI代码中,这样做更加简单快捷。这将始终是唯一的图形用户界面,而且极不可能出现重大的新需求。”

    你反对这种做法的最有说服力的理由是什么?我怎么能真的 显示 这是一个昂贵的实践,特别是对于那些没有太多软件开发经验的人。

    10 回复  |  直到 8 年前
        1
  •  47
  •   Roger Pate Roger Pate    14 年前

    设计是管理和平衡的权衡。 雅格尼和索里达并不矛盾:前者说 什么时候 怎样, 但它们都指导着设计过程。下面,我对你们每一个具体引语的回答都使用了雅格尼和索里达的原则。

    1. 构建可重用组件的难度是一次性使用的三倍 组件。
    2. 一个可重用的组件应该在三个不同的 在应用程序足够通用以接受重用之前 图书馆。

    -罗伯特·格拉斯 Rules of Three , Facts and Fallacies of Software Engineering

    重构成可重用的组件的关键是首先在多个地方找到相同的目的,并且 然后 移动它。在这种情况下,YAGNI通过在需要的地方内联该用途来应用,而不必担心可能的重复,而是添加泛型或可重用的特性(类和函数)。

    在最初的设计中,最好的方法是确定具体的需求,以显示YAGNI何时不适用。换句话说, 表明重复不仅是可能的,而且已经存在:这证明了额外的努力是正当的。


    是的,我可以把我所有的业务逻辑直接放到GUI代码中,这样更容易、更快。这将始终是唯一的图形用户界面,而且极不可能出现重要的新需求。

    它真的是唯一的用户界面吗?是否计划了后台批处理模式?会有网络界面吗?

    你的测试计划是什么,你会在没有GUI的情况下测试后端功能吗?什么会使GUI易于测试,因为您通常不想在外部代码(如平台通用GUI控件)进行测试,而是集中精力于您的项目。

    x * x squared(x)

    如果在不太可能出现新需求的情况下,我的代码变得过于混乱,我仍然可以为新需求进行重构。所以你的“如果你以后需要怎么办…”的论点不算数。

    这里的问题是“不太可能”的假设。你同意这不太可能吗?如果是,你同意这个人。如果不是,你对设计的想法与这个人的想法不一致,解决这个矛盾就能解决问题,或者至少告诉你下一步该怎么做。:)

        2
  •  8
  •   wrschneider    7 年前

    https://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php

    在我看来,GUI中的业务逻辑是半途而废的。除非您的系统是微不足道的,否则如果您的业务逻辑和GUI还没有独立地进行几次更改,我会感到惊讶。因此,您应该遵循SRP(“S”在SOLID中)和refactor-YAGNI不适用,因为您已经需要它了。

        3
  •  7
  •   EricBoersma    14 年前

    听起来你好像在和砖墙争论。我是雅格尼的忠实粉丝,但同时,我也希望我的代码 至少在两个地方使用:应用程序和测试。这就是为什么像UI代码中的业务逻辑这样的东西不起作用;在这种情况下,不能单独测试UI代码中的业务逻辑。

    然而,从你所描述的反应来看,听起来这个人只是对更好的工作不感兴趣。在这一点上,没有任何原则能够帮助他们;他们只想尽可能做到最低限度。我甚至可以说,不是雅格尼在推动他们的行动,而是懒惰,只有你一个人无法战胜懒惰(几乎什么都做不到,除了一个有威胁的经理或失业)。

        4
  •  3
  •   Eric Grange    7 年前

    尝试与一个缺乏经验的团队或者一个交付目标非常严格的团队合作,可以保证你最终会得到一堆昂贵的、过度设计的代码。。。这将不是坚实的,只是过度设计(又名欢迎来到现实世界)。

    试着去YAGNI做一个长期的项目,希望你能在以后的重构中只起到一定的作用(也就是说,欢迎来到现实世界)。雅格尼擅长证明概念和示范,获得市场/合同,然后能够投资于更坚实的东西。

        5
  •  2
  •   knitti freethinker    14 年前

    这些原则的正确应用往往不是很明显,很大程度上取决于经验。如果你不是自己做的很难得到。每一个程序员都应该有做错事的后果的经验,但当然,它应该总是“不是我的”项目。

        6
  •  2
  •   sleske    14 年前

    以我的经验,这总是一个判断的要求。是的,您不应该担心实现的每一个细节,有时将方法粘贴到现有类中是一个可以接受的,尽管是一个丑陋的解决方案。

    确实,您可以稍后重构。重要的一点是 . 所以我相信真正的问题不是偶然的设计妥协,而是一旦问题变得明显,就推迟重构。事实上,经历这一切是很困难的(就像生活中的许多事情一样…)。

    至于你的个人观点:

    我可以把两个功能都放在X上 类(即复杂性)。

    更复杂 (因为方法之间的关系更亲密,也更难理解)。有许多小类并不复杂。如果你觉得清单越来越长,就把它们打包,这样你就没事了。就我个人而言,我发现只要将一个类分成两个或三个类,就可以帮助提高可读性,而无需做任何进一步的更改。

    是的,我可以把我所有的商业逻辑 更容易,更快。这将永远 是唯一的图形用户界面 不太可能是新的 需求将永远到来。

    如果有人能直截了当地说“重要的新要求不太可能出现”,我相信那个人真的, 真正地

    如果在不太可能的情况下 我的代码也得到了 新要求。所以你的“如果你 计数

        7
  •  2
  •   Preet Sangha    14 年前

    • “重要的新要求不太可能出现。”

    这真的是真的吗?

    在发展的各种费用方面,经验是无法替代的。对很多从业者来说,我认为用糟糕、难以维护的方式做事从来不会给他们带来麻烦(嘿!工作保障)。从一个产品的长期来看,我认为这些费用已经很清楚了,但是提前解决这些问题是别人的工作。

        8
  •  2
  •   Jon Hanna    14 年前

    可理解的、灵活的、能够修复和改进的总是你 会需要的。事实上,YAGNI假设你可以回来添加新的特性,当它们被证明是必要的时候,相对容易,因为没有人会做一些疯狂的事情,比如在一个类中破坏不相关的功能(YAGNI在那个类中!)或者将业务逻辑推送到UI逻辑。

    有时候,现在看起来疯狂的事情在过去是合理的——有时候,UI与业务的边界线,或者应该在不同类中的不同职责集之间的边界线并没有那么清晰,甚至没有移动。有时在2小时内工作3小时是绝对必要的。有时候人们只是打错了电话。由于这些原因,这方面偶尔会出现中断,但它们会妨碍使用雅格尼原理,而不是原因。

        9
  •  2
  •   Greg Trevellick    8 年前

    质量单元测试,我的意思是单元测试而不是集成测试,需要遵循SOLID的代码。不一定100%,事实上很少,但在您的示例中,将两个特性塞进一个类将使单元测试更加困难,打破单一责任原则,并使团队新手的代码维护更加困难(因为这很难理解)。

    有了单元测试(假设代码覆盖率很高),您将能够安全地重构功能1,您不会破坏功能2,但是没有单元测试和同一类中的功能(在您的示例中只是懒散),重构充其量是危险的,充其量是灾难性的。

    底线:遵循KIS原则(保持简单),或者对于知识分子来说,遵循KIS原则(愚蠢)。根据每个案例的优点,没有全局答案,但是总是考虑其他代码编写者是否需要在将来阅读/维护代码,以及每个场景中单元测试的好处。

        10
  •  1
  •   Ajeet Ganga    10 年前

    tldr;

    SOLID假设,您理解(至少有点理解),代码的未来更改,wrt SRP。我要说的是对预测能力的乐观。 另一方面,雅格尼假设大多数时候你不知道未来的变化方向,这对预测能力是悲观的。

    因此,SOLID/SRP要求您为代码形成类,这样它就只有一个更改的原因。E、 g.一个小的GUI更改或服务调用更改。

    YAGNI说(如果您想在这个场景中强制应用它),因为您不知道将要更改什么,如果一个GUI更改将导致GUI+ServiceCall更改(类似于导致GUI+ServiceCall更改的后端更改),只需将所有代码放在一个类中。

    长答案:

    阅读《敏捷软件开发、原则、模式和实践》一书

    我把它的简短摘录放在SOLID/SRP上: “如果,[……]申请的变化不会导致这两项责任在不同时间发生变化,则无需将它们分开。事实上,把它们分开会有不必要的复杂性。

    这里有腐蚀物。只有当变化发生时,变化轴才是变化轴。应用SRPor任何其他原则都是不明智的,因为matterif没有症状。”

    推荐文章