DRY是一个折衷方案

2020-12-19 01:59:33

DRY或“不要重复自己”经常被吹捧为软件开发的原理。“复制粘贴”是对它的违背的嘲讽性术语,将复制代码和粘贴的概念归纳为软件开发不良做法(另请参见意大利面条代码)。

如此普遍地受到谴责,以至于有人不应该违反DRY原则,实际上,有些短毛绒甚至检测到复制粘贴,因此它永远不会潜入代码中,但是复制粘贴不是漫画。书中的恶棍,而DRY并没有因为击败它而陷入困境。

值得一提的是为什么要开始使用DRY作为原则。特别是在某些现代软件开发实践中,违反DRY是正确的做法。

重复执行代码块的主要问题是,如果发现了一个错误,则有多个地方需要修复。在表面上,这似乎是一种合理的批评。所有代码都有错误,这些错误将被修复。固定,为什么不减少固定它们的成本?

复制粘贴代码的替代方法通常是将其放入函数(或过程,或子例程,具体取决于语言),然后调用它。这意味着在读取原始调用者时,不清楚代码是什么做。

在进行调试时,这意味着我们需要"进入"进入该功能时,检查原始变量并非易事。如果您正在执行“打印调试”,这意味着找到该功能的原始来源并在其中添加相关的打印语句。

特别是当指出DRY并且本能地反应时,该函数可能具有一些令人惊讶的语义。例如,对局部变量的内容进行修改在代码中是明智的。当将此代码移至函数中作为直接DRY重构的一部分时,这意味着现在函数正在更改其参数。

即使两个地方的代码最初都相同,也没有先验的保证会保持这种方式。例如,可能经常调用其​​中一个地方,因此希望避免记录太多细节。其他地方很少被提及,这些细节对于解决常见问题是必不可少的。

现在,重构的函数必须支持一个额外的参数:是否记录这些详细信息(此参数可能是布尔值,日志记录级别,甚至是已设置正确级别的日志记录对象。 )

由于通常没有机构内存来取消DRY重构,因此该功能可能会增加越来越多的情况,最终几乎是两个功能合而为一。范围更广,可能导致广泛的过度概括:每个地方都需要稍微不同的功能变化。

现在,对公用功能的每次修改都需要测试其所有调用者。在某些情况下,这可能是微不足道的。

例如,如果重复是在不同的存储库中进行的,则现在的更新意味着更新库的版本。进行更改的人员甚至可能不知道所有调用者。调用者仅会发现何时在其代码中使用了新的库版本。

当重复每个代码段时,所有权和责任微不足道。谁拥有周围的代码,谁也拥有重复的段。

现在,代码已移至其他位置,通常可以混淆所有权。当发现错误时,应该由谁来解决?已经被其他用途所依赖?

尤其是在使用反应式DRY重构的情况下,几乎没有花精力指定通用代码的预期语义。可能会有一些测试,但是测试无法捕获的行为可能会有所不同。