SOLID 与 YAGNI

发布于 2024-09-27 02:24:46 字数 1431 浏览 2 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

千柳 2024-10-04 02:24:46

设计是权衡的管理和平衡。YAGNI 和 SOLID 并不冲突:前者说何时添加功能,后者说如何< /em> 但它们都指导设计过程。下面,我对您的每个具体报价的回复都使用了 YAGNI 和 SOLID 的原则。

  1. 构建可重用组件的难度是一次性组件的三倍
    组件。
  2. 可重用组件应该在三种不同的环境中进行尝试
    在它足够通用以接受重用之前的应用程序
    图书馆。

— 罗伯特·格拉斯的三法则软件工程的事实与谬误

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

在初始设计中,显示 YAGNI 何时不适用的最佳方法是确定具体要求。换句话说,在编写代码之前进行一些重构,以表明重复不仅是可能的,而且已经存在:这证明了额外的努力是值得的。


是的,我可以将所有业务逻辑直接放入 GUI 代码中,这样更容易、更快捷。这将永远是唯一的 GUI,并且不太可能出现重大的新需求。

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

您的测试计划是什么?您是否会在没有 GUI 的情况下测试后端功能?什么将使 GUI 易于测试,因为您通常不想测试外部代码(例如平台通用 GUI 控件),而是专注于您的项目。

我可以将特征 X 和特征 Y 放入同一个类中。这么简单为什么要费心添加一个新类(即复杂性)。

您能指出一个需要避免的常见错误吗?有些事情很简单,例如对一个数字进行平方(x * xsquared(x))作为一个过于简单的示例,但如果你能指出一个具体的例子某人犯的错误(尤其是在您的项目中或您团队中的错误)您可以展示公共类或函数将来如何避免这种情况。

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

这里的问题是“不太可能”的假设。你同意这不太可能吗?如果是这样,那么您同意这个人的观点。如果不是,那么你的设计理念与此人的设计理念不一致——解决差异就能解决问题,或者至少告诉你下一步该去哪里。 :)

Design is the management and balance of trade-offs. YAGNI and SOLID aren't conflicting: the former says when to add features, the latter says how, but they both guide the design process. My responses, below, to each of your specific quotes use principles from both YAGNI and SOLID.

  1. It is three times as difficult to build reusable components as single use
    components.
  2. A reusable component should be tried out in three different
    applications before it will be sufficiently general to accept into a reuse
    library.

  — Robert Glass' Rules of Three, Facts and Fallacies of Software Engineering

Refactoring into reusable components has the key element of first finding the same purpose in multiple places, and then moving it. In this context, YAGNI applies by inlining that purpose where needed, without worrying about possible duplication, instead of adding generic or reusable features (classes and functions).

The best way, in the initial design, to show when YAGNI doesn't apply is to identify concrete requirements. In other words, do some refactoring before writing code to show that duplication is not merely possible, but already exists: this justifies the extra effort.


Yes, I can put all my business logic directly into the GUI code it is much easier and quicker. This will always be the only GUI and it is highly unlikely that signifcant new requirements will ever come in.

Is it really the only user interface? Is there a background batch mode planned? Will there ever be a web interface?

What is your testing plan, and will you be testing back-end functionality without a GUI? What will make the GUI easy for you to test, since you usually don't want to be testing outside code (such as platform-generic GUI controls) and instead concentrate on your project.

It is OK that I put both feature X and feature Y into the same class. It is so simple why bother adding a new class (i.e. complexity).

Can you point out a common mistake that needs to be avoided? Some things are simple enough, such as squaring a number (x * x vs squared(x)) for an overly-simple example, but if you can point out a concrete mistake someone made—especially in your project or by those on your team—you can show how a common class or function will avoid that in the future.

If, in the unlikely case of new requirements, my code gets too cluttered I still can refactor for the new requirement. So your "What if you later need to..." argument doesn't count.

The problem here is the assumption of "unlikely". Do you agree it's unlikely? If so, you're in agreement with this person. If not, your idea of the design doesn't agree with this person's—resolving that discrepancy will solve the problem, or at least show you where to go next. :)

横笛休吹塞上声 2024-10-04 02:24:46

我喜欢用“一半,而不是半途而废”来思考 YAGNI,借用 37signals 的这句话 ( https://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php)。这是为了限制你的范围,这样你就可以专注于做好最重要的事情。这不是马虎的借口。

GUI 中的业务逻辑对我来说是半途而废的。除非您的系统很简单,否则如果您的业务逻辑和 GUI 尚未独立多次更改,我会感到惊讶。因此,您应该遵循 SRP(SOLID 中的“S”)并重构 - YAGNI 不适用,因为您已经需要它。

如果您今天正在做额外的工作来满足假设的未来需求,那么关于 YAGNI 和不必要的复杂性的争论绝对适用。当那些“如果以后我们需要……怎么办”的场景未能实现时,您就会因抽象而承受更高的维护成本,而这些抽象现在会妨碍您实际进行的更改。在这种情况下,我们讨论的是通过限制范围来简化设计——做一半,而不是半途而废。

I like to think about YAGNI in terms of "half, not half-assed", to borrow the phrase from 37signals (https://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php). It's about limiting your scope so you can focus on doing the most important things well. It's not an excuse to get sloppy.

Business logic in the GUI feels half-assed to me. Unless your system is trivial, I'd be surprised if your business logic and GUI haven't already changed independently, several times over. So you should follow the SRP ("S" in SOLID) and refactor - YAGNI doesn't apply, because you already need it.

The argument about YAGNI and unnecessary complexity absolutely applies if you're doing extra work today to accommodate hypothetical future requirements. When those "what if later we need to..." scenarios fail to materialize, you're stuck with higher maintenance costs from the abstractions that now get in the way of the changes you actually have. In this case, we're talking about simplifying the design by limiting scope -- doing half, rather than being half-assed.

煮酒 2024-10-04 02:24:46

听起来你好像在和一堵砖墙争论。我是 YAGNI 的忠实粉丝,但同时,我也希望我的代码始终至少在两个地方使用:应用程序和测试。这就是为什么 UI 代码中的业务逻辑之类的东西不起作用;在这种情况下,您无法独立于 UI 代码来测试业务逻辑。

然而,从您所描述的回答来看,这个人似乎对做得更好并不感兴趣。到那时,任何原则都无法帮助他们;他们只想做尽可能少的事情。我什至可以说,他们的行为并不是亚格尼驱动的,而是懒惰,而你自己无法战胜懒惰(几乎没有什么可以,除了威胁经理或失去工作)。

It sounds like you're arguing with a brick wall. I'm a big fan of YAGNI, but at the same time, I also expect that my code will always be used in at least two places: the application, and the tests. That's why things like business logic in UI code don't work; you can't test business logic separate of UI code in that circumstance.

However, from the responses you're describing, it sounds like the person is simply uninterested in doing better work. At that point, no principle is going to help them; they only want to do the minimum possible. I'd go so far as to say that it's not YAGNI driving their actions, but rather laziness, and you alone aren't going to beat laziness (almost nothing can, except a threatening manager or the loss of a job).

夏尔 2024-10-04 02:24:46

没有答案,或者更确切地说,有一个你和你的对话者都可能不喜欢的答案:YAGNI 和 SOLID 都可能是错误的方法。

尝试与缺乏经验的团队或具有严格交付目标的团队一起追求 SOLID 几乎可以保证您最终会得到一堆昂贵的、过度设计的代码......这不会是 SOLID,只是过度设计的(又名欢迎)到现实世界)。

尝试使用 YAGNI 进行长期项目并希望以后能够进行重构只能在一定程度上起作用(也就是欢迎来到现实世界)。 YAGNI 擅长概念验证和演示,获得市场/合同,然后能够投资于更可靠的东西。

您在不同的时间点都需要两者。

There is no answer, or rather, there is an answer neither you nor your interlocutor might like: both YAGNI and SOLID can be wrong approaches.

Attempting to go for SOLID with an inexperienced team, or a team with tight delivery objectives pretty much guarantees you will end up with an expensive, over-engineered bunch of code... that will NOT be SOLID, just over-engineered (aka welcome to the real-world).

Attempting to go YAGNI for a long term project and hope you can refactor later only works to an extent (aka welcome to the real-world). YAGNI excels at proof-of-concepts and demonstrators, getting the market/contract and then be able to invest into something more SOLID.

You need both, at different points in time.

源来凯始玺欢你 2024-10-04 02:24:46

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

向他们解释问题是什么,如果他们不听,而你又无法让他们听,就让他们犯错误。如果你经常需要解决问题,那么你应该润色你的简历。

The correct application of these principles is often not very obvious and depends very much on experience. Which is hard to obtain if you didn't do it yourself. Every programmer should have had experiences of the consequences of doing it wrong, but of course it always should be "not my" project.

Explain to them what the problem is, if they don't listen and you're not in a position to make them listen, let them do the mistakes. If you're too often the one having to fix the problem, you should polish your resume.

樱花坊 2024-10-04 02:24:46

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

确实,以后可以重构。重要的一点是实际进行重构。所以我相信真正的问题不是偶尔的设计妥协,而是一旦发现问题就推迟重构。实际上经历它是困难的部分(就像生活中的许多事情一样......)。

至于你个人的观点:

我把两个功能都放在X上是可以的
并将 Y 归入同一类。它
如此简单何必添加新的
类(即复杂性)。

我想指出的是,将所有内容都放在一个类中更加复杂(因为方法之间的关系更加密切,并且更难理解)。开设许多小班并不复杂。如果您觉得列表太长,只需将它们组织成包,就可以了:-)。就我个人而言,我发现只需将一个类分成两个或三个类即可对可读性有很大帮助,而无需任何进一步的更改。

不要害怕小班,他们不会咬人;-)。

是的,我可以把我所有的业务逻辑
直接进入GUI代码就多了
更容易、更快捷。这永远都会
是唯一的 GUI 并且它是高度
不太可能出现重大新变化
需求永远都会出现。

如果有人可以说“重大的新需求不太可能出现” 板着脸,我相信这个人真的,真的需要现实检查。说话要直率,但要温柔……

如果在不太可能的情况下出现新的
我的代码也有要求
混乱我仍然可以重构
新要求。所以你的‘如果你
稍后需要......'的论点并不
计数

有一些优点,但前提是他们稍后确实进行了重构。所以接受它,并让他们信守承诺:-)。

In my experience, it's always a judgment call. Yes, you should not worry about every little detail of your implementation, and sometimes sticking a method into an existing class is an acceptable, though ugly solution.

It's true that you can refactor later. The important point is to actually do the refactoring. So I believe the real problem is not the occasional design compromise, but putting off refactoring once it becomes clear there's a problem. Actually going through with it is the hard part (just like with many things in life... ).

As to your individual points:

It is OK that I put both feature X
and feature Y into the same class. It
is so simple why bother adding a new
class (i.e. complexity).

I would point out that having everything in one class is more complex (because the relationship between the methods is more intimate, and harder to understand). Having many small classes is not complex. If you feel the list is getting to long, just organize them into packages, and you'll be fine :-). Personally, I have found that just splitting a class into two or three classes can help a lot with readability, without any further change.

Don't be afraid of small classes, they don't bite ;-).

Yes, I can put all my business logic
directly into the GUI code it is much
easier and quicker. This will always
be the only GUI and it is highly
unlikely that signifcant new
requirements will ever come in.

If someone can say "it is highly unlikely that signifcant new requirements will ever come in." with a straight face, I believe that person really, really needs a reality check. Be blunt, but gentle...

If in the unlikely case of new
requirements my code gets too
cluttered I still can refactor for the
new requirement. So your 'What if you
later need to ...' argument doesn't
count

That has some merit, but only if they actually do refactor later. So accept it, and hold them to their promise :-).

等待圉鍢 2024-10-04 02:24:46

SOLID 原则允许软件适应变化 - 在需求和技术变化(新组件等)方面,您的两个论点是支持不变的需求:

  • “不太可能出现重大的新需求。”
  • “如果在不太可能的情况下提出新要求”

这真的是真的吗?

当谈到开发的各种费用时,经验是无可替代的。对于许多从业者来说,我认为以糟糕的、难以维护的方式做事从来不会给他们带来问题(嘿!工作保障)。从产品的长期来看,我认为这些费用会变得清晰,但提前采取措施是其他人的工作。

这里还有一些其他很好的答案。

SOLID principles allow software to adapt to change - in both requirements and techical changes (new components, etc), two of your arguments are for unchanging requirements:

  • "it is highly unlikely that signifcant new requirements will ever come in."
  • "If in the unlikely case of new requirements"

Could this really be true?

There is no substitute for experience when it comes to the various expenses of development. For many practitioners I think doing things in the lousy, difficult to maintain way has never resulted in problems for them (hey! job security). Over the long term of a product I think these expenses become clear, but doing something about them ahead of time is someone else's job.

There are some other great answers here.

思慕 2024-10-04 02:24:46

易于理解、灵活以及能够修复和改进始终是您所需要的。事实上,YAGNI 假设您可以在需要时相对轻松地返回并添加新功能,因为没有人会做一些疯狂的事情,例如在类中添加不相关的功能(YAGNI 在该类中!)或将业务逻辑推向 UI 逻辑。

有时,现在看起来疯狂的事情在过去却是合理的——有时 UI 与业务之间的界限,或者应该属于不同类的不同职责之间的界限并不那么清晰,甚至不那么清晰。有时,2 小时内的工作 3 小时是绝对必要的。有时人们只是没有做出正确的决定。由于这些原因,这方面偶尔会发生中断,但它们会妨碍 YAGNI 原则的使用,而不是造成它的原因。

Understandable, flexible and capable of fixes and improvements are always things that you are going to need. Indeed, YAGNI assumes that you can come back and add new features when they prove necessary with relative ease, because nobody is going to do something crazy like bunging irrelevant functionality in a class (YAGNI in that class!) or pushing business logic to UI logic.

There can be times when what seems crazy now was reasonable in the past - sometimes the boundary lines of UI vs business or between different sets of responsibilities that should be in a different class aren't that clear, or even move. There can be times when 3hours of work is absolutely necessary in 2hours time. There are times when people just don't make the right call. For those reasons occasional breaks in this regard will happen, but they are going to get in the way of using the YAGNI principle, not be a cause of it.

请别遗忘我 2024-10-04 02:24:46

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

通过单元测试(假设良好的代码覆盖率),您将能够安全可靠地重构功能 1,并且不会破坏功能 2,但如果没有单元测试,并且使用同一类中的功能(只是为了在示例中偷懒)重构充其量是有风险的,充其量是灾难性的。

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

Quality unit tests, and I mean unit tests not integration tests, need code that adheres to SOLID. Not necessarily 100%, in fact rarely so, but in your example stuffing two features into one class will make unit testing harder, breaks the single responsibility principle, and makes code maintenance by team newbies much harder (as it is much harder to comprehend).

With the unit tests (assuming good code coverage) you'll be able to refactor feature 1 safe and secure you won't break feature 2, but without unit tests and with the features in same class (simply to be lazy in your example) refactoring is risky at best, disastrous at best.

Bottom line: follow the KIS principle (keep it simple), or for the intellectual the KISS principle (kis stupid). Take each case on merit, there's no global answer but always consider if other coders need to read / maintain the code in the future and the benefit of unit tests in each scenario.

荒人说梦 2024-10-04 02:24:46

太棒了;

SOLID 假设,您(至少在某种程度上)了解代码的未来更改(关于 SRP)。我想说的是对预测能力持乐观态度。
另一方面,YAGNI 假设大多数时候你不知道未来的变化方向,这对预测能力是悲观的。

因此,SOLID/SRP 要求您为代码形成类,以便它有单一的更改原因。例如,小的 GUI 更改或 ServiceCall 更改。

YAGNI 说(如果你想在这种情况下强制应用它),因为你不知道会发生什么变化,以及 GUI 更改是否会导致 GUI+ServiceCall 更改(类似地,后端更改会导致 GUI+SeviceCall 更改) ,只需将所有代码放在一个类中即可。

长答案:

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

我摘录了其中有关 SOLID/SRP 的简短摘录:
“如果应用程序的变化不会导致两个职责在不同时间发生变化,则无需将它们分开。事实上,将它们分开会带来不必要的复杂性。

这里有一个推论。只有当变化发生时,变化轴才是变化轴,如果没有任何症状,应用 SRP 或任何其他原则都是不明智的。”

tldr;

SOLID assumes, you understand (somewhat atleast), the future changes to the code, wrt SRP. I will say that is being optimistic about capability to predict.
YAGNI on the other hand, assumes most of the times you don't know future direction of change, which is pessimistic about capability to predict.

Hence it follows that SOLID/SRP asks you to form classes for the code such that it will have single reason for change. E.g. a small GUI change or ServiceCall change.

YAGNI says (if you want to force apply it in this scenario), since you don't know WHAT is going to change, and if a GUI change will cause a GUI+ServiceCall change (similarly A backend change causing GUI+SeviceCall change), just put all that code in single class.

Long answer :

Read the book 'Agile Software Development, Principles, Patterns, and Practices'

I am putting short excerpt from it about SOLID/SRP :
"If,[...]the application is not changing in ways that cause the two responsibilities to change at different times, there is no need to separate them. Indeed, separating them would smell of needless complexity.

There is a corrolary here. An axis of change is an axis of change only if the changes occur. It is not wise to apply SRP—or any other principle, for that matter—if there is no symptom."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文