AHA Programming

2022-07-23 · 1,430 chars · 8 min read

原文地址:https://kentcdodds.com/blog/aha-programming

观看原作者的视频演讲: AHA Programming

DRY#

DRY(Don't Repeat Yourself 的首字母缩写),是一条古老的软件开发准则,维基百科总结如下:

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system

系统中的每一部分,都必须有一个单一的、明确的、权威的表述

通常,我赞同这是一种好做法(尽管不像定义里描述的那么教条主义)。我在 code duplication(代码重复,又称复制/粘贴,它基本上是 DRY 的对立面)中遇到的最大问题是,在一个地方发现一个错误,修复它,然后意识到同样的错误在其他地方也存在,并且必须在那里再修复一次。

有一次,我继承了一个大量使用重复代码的代码库,我必须一次在八个不同的地方,修复同一个错误!😱 聊起来很刺激!但是将该代码抽象为一个可以在任何需要的地方调用的函数,会大有帮助。

WET#

还有一个称为 WET(Write Everything Twice) 编程的概念,它代表“把所有东西都写两次”。这同样是教条的,而且过于规范。 Conlin Durbin 将其定义为

You can ask yourself "Haven't I written this before?" two times, but never three.

你可以问自己“我以前不是写过这个吗?”两次,但永远别问第三次。

在我上面提到的那个代码库里,有一些“过度抽象”,比“重复”更糟糕。它是 Angular JS 代码,有几个 Angular JS 的控制器,代码将 this 传递给一个函数,该函数会 monkey patch —— 将方法和属性修补到 this 上,以增强控制器实例的某些能力。我猜是一种伪继承。这非常让人困惑、难以理解,对代码库的这部分进行任何更改,都让我很害怕。

虽然代码在不止三个地方被重复使用了,但是如果抽象的很糟糕,我宁愿代码重复。

AHA#

AHA 是我从 Cher Scarlett 那里 拿来的缩写:

Avoid Hasty Abstractions

避免仓促的抽象

Sandi Metz 把这个原则解释的非常好:

prefer duplication over the wrong abstraction

宁愿重复,也不要错误的抽象

这是真的是金玉良言,我希望你再读一遍,然后阅读 Sandi 关于这个问题的博客:错误的抽象。写的非常精彩。

这里有另一个重要的相关原则,我想补充一下:

Optimize for change first

(有点难翻译)大意是:优先要考虑,更好的应对未来可能发生的变化

我认为,关键是我们不知道未来代码会发展成什么样子。我们可能会花几周的时间来优化代码的性能,或者为我们的新抽象提出最好的 API,但第二天却发现我们做了不正确的假设,API 需要完全重做,或者代码的某些功能完全废弃了。我们并不确定。我们所能确定的是,事情很可能会发生变化,如果它们永远不变,那么我们也不会去碰这些代码,所以谁会在乎它看起来像什么?

但不要误会我的意思,我不是建议大家放任不管、不作为。我只是建议大家应该注意到一个很现实的问题,就是我们并不知道未来我们的代码会面对什么样的需求。

所以我对代码的重复没有意见,直到你觉得很有信心,明确这些重复代码的应用场景。代码的哪些部分是不同的,你的函数应该支持什么样的参数?当你有几个地方在运行这些代码时,这些共同点就会向你发出“抽象的呼声”,你就会以正确的心态来完成这种抽象。

如果你过早的进行抽象封装,觉得这个函数或组件,对你当前的场景来说是完美的,你就会进一步调整代码来适应你的新用例。这种情况会持续好几次,直到抽象出来的东西基本上就是你整个应用程序的 if 语句和循环 😭

几年前,我受雇审查一家公司的代码库,我用一个叫 jsinspect 的工具来识别大块的复制/粘贴代码,向他们展示抽象的机会。他们有一堆重复的代码,从我的角度来看,很明显能知道应该抽象成什么样子。

我认为 "AHA Programming" 最大的收益是:你不应该教条地规定什么时候开始抽象,而应该在感觉正确的时候开始抽象封装,不要害怕重复代码。

结语#

我觉得对软件开发准则,应该采取一种有分寸的、务实的方法。这就是为什么我喜欢 AHA 而不是 DRYWETAHA的目的是帮助你注意你的抽象,而不给你硬性规定“什么时候”、“可以或不可以”把一些代码抽象成一个函数或模块。

我希望这对你有帮助。如果你发现自己陷入了不良抽象的泥潭,请注意!Sandi 给了你一些很好的步骤来解决这个问题。Sandi 给了你一些很好的步骤,告诉你如何摆脱这种困境!只要读读她的博文就可以了。Good Luck!

赞赏

微信