设计是权衡取舍的管理。 YAGNI 和 SOLID 不冲突:前者说出什么时候添加功能,后者说出如何添加,但它们都指导着设计过程。我的回应如下,针对您引用的每个具体语录,使用了 YAGNI 和 SOLID 的原则。
- 构建可重用组件比构建单一使用组件难三倍。
- 在将可重用组件纳入重用库之前,应在三个不同的应用程序中尝试该组件。
— 罗伯特·格拉斯的 三法则, 软件工程的事实和谬误
重构成可重用组件的关键要素是首先在多个地方找到相同的目的,然后再移动它。在这种情况下,YAGNI 适用于内联所需的目的,而不必担心可能的重复,而是添加通用或可重用的功能(类和函数)。
在初始设计中展示 YAGNI 不适用的最佳方法是确定具体的需求。换句话说,在编写代码之前进行一些重构,以显示重复不仅可能存在,而且已经存在:这样可以证明额外的努力是有道理的。
是的,我可以直接将所有业务逻辑放入GUI代码中,这样做会更容易和更快。这将永远是唯一的GUI,并且极不可能有重大新要求。
真的是唯一的用户界面吗?是否计划了后台批处理模式?将来会有Web界面吗?
你的测试计划是什么?你是否会在没有GUI的情况下测试后端功能?GUI对你来说很容易测试,因为你通常不想测试外部代码(例如平台通用的GUI控件),而是专注于你的项目。
将特性X和特性Y放入同一个类中是可以的。它非常简单,为什么要添加一个新的类(即复杂性)。
你能指出需要避免的常见错误吗?有些事情非常简单,比如对一个数字进行平方运算(x * x
vs squared(x)
)这是一个过于简单的例子,但如果你能指出某个人犯过的具体错误 - 特别是在你的项目或你的团队中 - 你就可以展示一个常见的类或函数,以避免未来发生这种错误。
如果在不太可能出现新需求的情况下,我的代码变得太混乱,我仍然可以为新需求进行重构。所以你的“如果以后需要…”的论点无效。
问题在于“不太可能”的假设。你同意这是不太可能的吗?如果是,你就同意了这个人的观点。如果不是,你的设计想法与这个人的不一致 - 解决这个差异将解决问题,或者至少向你展示下一步该如何去做。 :)
我喜欢用“半个,不是半吊子”的方式来思考YAGNI,借用了37signals的这个短语 (https://gettingreal.37signals.com/ch05_Half_Not_Half_Assed.php)。它的含义是限制你的范围,这样你就可以专注于做好最重要的事情。它不是懈怠的借口。
对我来说,在GUI中处理业务逻辑感觉有些草率。除非你的系统非常简单,否则我会惊讶于你的业务逻辑和GUI已经独立变更了多次。所以你应该遵循SRP(SOLID中的"S")并进行重构-因为你已经需要了,所以YAGNI不适用。
如果你正在做额外的工作来适应假设的未来需求,那么关于YAGNI和不必要的复杂性的争论绝对适用。当那些“如果后来我们需要…”的场景未能发生时,你就会被高昂的维护成本困扰,因为现在那些抽象化的东西已经妨碍了你实际所做的更改。在这种情况下,我们谈论的是通过限制范围来简化设计-做一半,而不是草率地完成。
优质的单元测试,我指的是单元测试而不是集成测试,需要遵循SOLID原则的代码。并非必须完全遵守,实际上很少有这样的情况,但在你的例子中,将两个功能塞进一个类中会使单元测试更加困难,违反了单一职责原则,并且使新手团队维护代码变得更加困难(因为更难理解)。
通过单元测试(假设覆盖率良好),您将能够安全地重构功能1,并确保不会破坏功能2,但如果没有单元测试并且将功能放在同一个类中(仅仅是为了懒惰),那么重构最多是有风险的,最坏的情况是灾难性的。
SOLID原则允许软件适应变化-无论是需求变化还是技术变化(如新组件等),您的两个论点都是针对不变的需求:
这真的可能吗?
在开发的各种费用方面,经验是无可替代的。我认为,对于许多从业人员来说,以糟糕、难以维护的方式进行操作从未给他们带来问题(嘿!工作安全)。从长远来看,我认为这些开销变得清晰明了,但提前做出改变是别人的工作。
这里还有其他一些很好的答案。
tldr;
SOLID和YAGNI是关于代码设计的两种不同思想。SOLID假设你能够预测未来的变化并据此设计类,而YAGNI则认为你无法预测未来的变化,因此应该将所有相关代码放在一个类中。SOLID要求为代码设计单一职责的类,而YAGNI则认为这样做可能会增加不必要的复杂性。
详细解释:
阅读书籍“敏捷软件开发:原则、模式与实践”可以更好地理解SOLID/SRP。
SOLID要求设计类时应考虑到代码变化的单一原因,例如小的GUI变化或ServiceCall变化。如果应用程序不会以导致这两个职责在不同时间发生变化的方式发生变化,则没有必要将它们分开。相反,将它们分开会增加不必要的复杂性。
这里有一个相关性。只有发生变化,改变的轴才是改变的轴。如果没有症状,应用SRP或其他原则都不明智。