我的工作,我的任务是提高代码的质量。为了履行这一职责,我经常将程序与开发人员配对,并就设计原则和设计模式进行讨论。一位开发人员说,他要么违反了单一责任原则,要么违反了YAGNI,我对此感到惊讶。
单一责任原则规定,每个类或模块都应该有一个改变的理由。为了清楚地重申这一点。一个模块应该对一个角色负责,并且只对一个参与者负责。
根据我的理解,我们遵循单一责任原则的原因是:如果一个类对两个参与者负责,而如果一个角色驱动该类中的更改,则有可能无意中更改另一个角色的要求。
你的首字母缩写不需要它。极限编程原则指出,做最简单的事情,可能是可行的。我经常依靠YAGNI,通过消除不必要的模块化,使我的代码更简单。
SRP和YAGNI之间的冲突:我们在系统中实现了一个工作流。还需要收集关于工作流程使用情况的数据。我们需要了解工作流中使用的参数的百分比分布。我解释说,数据收集必须在另一个类中(我们可以使用观察者或修饰器模式),而不是在工作流实现的类中,因为这两个需求都是由系统中的不同参与者驱动的。工作流程为最终用户服务,数据采集服务于产品管理。
我的同事想直接从实现工作流的类中记录参数。他告诉我,这是最简单的一件事,让它发挥作用。
我几乎可以肯定,在这个场景中,我必须在这里遵循SRP。我遵循SRP (在两个类中实现),因为如果工作流程发生变化,意外修改数据收集的概率很低。当数据收集发生变化时,意外修改工作流的概率也很低。但当我解释工作流程或数据收集可能发生的变化时,他告诉我“你不需要它”。
对于如何解释这件事,有什么建议吗?
发布于 2019-11-29 10:52:13
YAGNI的意思是避免将精力投入到可能稍后到达的假设需求的代码更改上,而是将注意力集中在现在的需求上。但是,这并不局限于功能需求--只要不创建“一次性使用,然后丢弃”软件,始终存在保持代码可读性、可理解性和可进化性的非功能性需求。分离责任是实现这一目标的主要工具之一。
因此,在这种情况下,我将YAGNI原则解释为一项建议,即在SRP的好处变得可见之前,不要将责任分开,这实际上是在代码变得复杂之后立即进行的。当一个人试图在一个类中实现不同的业务需求时,这种情况通常会很快发生。
如果我必须对“实现工作流的类”进行两三次小扩展以添加此日志要求,我将容忍这种情况。但是,我的痛苦程度可能会达到,我会开始思考“见鬼,我们能不能重构这个日志机制,或者至少可以将数据从工作流类中收集到一个更好的地方”。
所以不要告诉你的开发人员:
告诉他们:
这应该是我们需要应用SRP的理由,而不是将来某些未知的需求,而是现在保持代码可理解的要求。
当然,代码被认为是复杂的,以及何时可以应用SRP来修复这一点的阈值可能因开发而异,但这是团队必须找到的平衡,以及只有代码评审才能提供帮助。的位置。
发布于 2019-11-29 17:05:20
不应严格遵守
他们在那里是为了说明通过经验获得的知识。他们的目标是洞察软件开发的不同方面。不足为奇的是,他们有时会互相对抗。
我非常喜欢呈现以下金字塔的这篇媒体文章:

金字塔背后的想法是,你不应该破坏低层而牺牲更高层。
首先,不要认为这个形象是绝对的。不应该盲目地去做。但它基本上表明,某些原则比其他原则更重要是合理的--也许,让您的解决方案发挥作用应该是最高优先事项。
在你的SRP和YAGNI问题的镜头里,我想问自己:
有一个红宝石中的实用面向对象设计“一书的作者Sandi Metz说得很好触及了一个非常好的点:
复制比错误的抽象要便宜得多。
也许现在开发一个抽象可能会导致您以错误的方式抽象它。
最后,考虑到应用程序的上下文,必须应用原则。事实上,SRP可能是你的情况的正确指南。或者..。SRP可能会导致你现在过度设计它,使用YAGNI会更合适。
主要的解决办法也许应该是:是的,如果宗教信仰的话,原则相互矛盾是很常见的,这不是一个问题。百事大吉。
如果有的话,最好首先实现一个工作解决方案(即,选择其中一个解决方案并与其一起执行),并适应由此产生的影响,有机地构建软件。
发布于 2019-11-29 11:24:01
单一责任原则规定,每个类或模块都应该有一个改变的理由。为了清楚地重申这一点。一个模块应该对一个角色负责,并且只对一个参与者负责。
我不同意这个说法,也就是说,我不认为这是一条好的规则。我知道鲍勃叔叔说了一些非常相似的话,甚至是同样的话。
让我们考虑一下这个问题。假设我有一个简单的Amount类,它包含add()和subtract()。如果一个“演员”只需要add()而另一个subtract()呢?我该分这门课吗?这会使代码更易于维护吗?我不认为你会这么说。
在你说这一切都取决于你,并且你应该总是做出判断之前,我不认为规则是一个好的规则,即使它不适用于简单的情况。
对于您的问题:您是正确的,如果可能的话,我也会尝试将数据收集与实际的工作流实现分开。例如,如果Workflow是一个接口,并且数据收集的所有数据都可以通过参数获得,那么我将创建一个收集数据并委托调用的实现。
但是,如果工作流中有需要收集的内部数据,而这些数据不能通过公共参数获得,那么将数据收集放入实现本身就没有问题,因为在这种情况下,我实际上对实际实现的行为感兴趣。
所以,你也没有说服我:)
https://softwareengineering.stackexchange.com/questions/401797
复制相似问题