【问题标题】:How much abstraction is too much?多少抽象太多了?
【发布时间】:2011-02-09 17:36:58
【问题描述】:

在面向对象的程序中:多少抽象才算太多?多少才合适?

我一直是个不折不扣的人。我理解高级封装和抽象背后的概念,但总本能地觉得添加太多只会混淆程序。

我总是试图寻找一些不留空类或层的抽象。如果有疑问,我不会在层次结构中添加新层,而是尝试在现有层中添加一些东西。

但是,最近我遇到了更多高度抽象的系统。在层次结构中稍后可能需要表示的所有内容都在前面得到一个的系统。这会导致很多空层,乍一看似乎是糟糕的设计。然而,再想一想,我开始意识到,留下这些空层可以让你在未来有更多的地方可以挂钩,而无需进行太多重构。它使您能够在旧功能的基础上添加新功能,而无需做太多工作来调整旧功能。

这样做的两个风险似乎是您可能会错误地获取所需的层。在这种情况下,最终仍然需要进行大量重构来扩展代码,并且仍然会有大量从未使用过的层。但取决于您花多少时间提出最初的抽象,搞砸的可能性,以及如果你做对了以后可以节省的时间 - 可能仍然值得一试。

我能想到的另一个风险是过度执行并且永远不需要所有额外层的风险。但这真的有那么糟糕吗?额外的类层真的如此昂贵,以至于如果它们从未使用过会造成很大的损失吗?这里最大的费用和损失将是前期损失的时间。但是当人们可以使用抽象代码而不是更底层的代码时,大部分时间仍然可以节省下来。

那么什么时候过分呢?什么时候空层和额外的“可能需要”抽象变得过大了?太少有多少?甜蜜点在哪里?

在您的职业生涯中,您是否发现了任何可靠的经验法则来帮助您判断所需的抽象量?

【问题讨论】:

  • 一根绳子有多长??? ;)
  • 应该是 CW 恕我直言,因为它没有 an 答案
  • 为什么 Java 应用与 C# 相比往往具有更多抽象?
  • @Goz 取决于语言,例如Pascal 说它确实有一个最大长度,但是聪明的 (c) 人们知道它没有。
  • 太多的抽象是死亡行军的东西。我正在处理一个非常抽象的大型遗留应用程序,以至于当在界面上单击按钮时,它实际上需要几个小时才能找到执行的代码。这个应用程序以一种非常有害的方式结合了 WPF、依赖注入和模拟。过多的抽象是维护代码库的障碍。这是一个重要的话题,应该讨论。过多的抽象实际上会使优秀的公司和组织陷入废墟。这一点也不夸张。

标签: language-agnostic oop abstraction


【解决方案1】:

抽象的意义在于从特定属性中分解出通用属性,例如在数学运算中:

ab + ac => a(b + c)

现在你用两个操作而不是三个来做同样的事情。这种因式分解使我们的表达式更简单。

一个典型的抽象例子是文件系统。例如,您希望您的程序能够写入多种存储设备:笔式驱动器、SD 卡、硬盘驱动器等...

如果我们没有文件系统,我们需要实现直接磁盘写入逻辑、笔驱动写入逻辑和 SD 卡写入逻辑。但是所有这些逻辑都有一些共同点:它们创建文件和目录,因此可以通过创建抽象层并为硬件供应商提供接口来完成特定工作,从而将这些共同的东西抽象掉。

越多的东西共享一个共同的属性。一个抽象可能更有益:

ab + ac + ad + ae + af

到:

a(b + c + d + e + f)

这会将 9 个操作减少到 5 个。

基本上每个好的抽象都会使系统的复杂性大致减半。

你总是需要至少两个东西共享一个公共属性才能使抽象有用。当然,你把一个东西拆开让它看起来像一个抽象,但这并不意味着它是有用的:

10 => 5 * 2

如果你只有一个实体,你就不能定义“普通”这个词。

所以回答你的问题。 如果它们使您的系统尽可能简单,那么您就有足够的抽象。

(在我的示例中,加法连接系统的各个部分,而乘法定义了抽象-具体的关系。)

【讨论】:

  • 这个答案描述了使用抽象来保持代码干燥,但它没有涉及抽象的其他重要/有意义的用途——例如SOLID 或 GRASP 模式,以及强制分离关注点或使用一致性的元编程合同。
  • 这完全不真实。如果您编写的代码不会在一行中重复,您将花费大约 1 年时间,而在您离职后将对其进行维护的人将花费半年时间来理解您的代码。因此,情况完全相反:您添加的每个抽象 -> 都会增加系统的复杂性。
【解决方案2】:

太少了?

当您在常规基础上继续使用“低级”元素时,您总是觉得自己不想这样做。把它们抽象出来。

那么什么时候过分呢?

当您无法定期制作一些代码部分的零碎并且必须将它们调试到上一层时。你觉得这个特定的层没有任何贡献,只是一个障碍。放下它。

甜蜜点在哪里?

我喜欢采用务实的方法。如果您认为需要抽象并了解它将如何改善您的生活,那就去做吧。如果您听说应该“正式”增加一层抽象,但您不清楚原因,请不要这样做,而是先进行研究。如果有人坚持要抽象一些东西,但不能清楚地解释如果会带来什么,请告诉他们走开。

【讨论】:

    【解决方案3】:

    那么什么时候太多了?在什么时候 做空层和额外的“可能 需要”抽象变得矫枉过正? 太少有多少?在哪儿 甜蜜点?

    我认为这些问题没有明确的答案。需要经验来培养“太多”和“太少”的感觉。也许使用一些度量或质量控制工具会有所帮助,但很难一概而论。这主要取决于每种情况。

    这里有一些链接可能会激发您寻求答案:

    开发就是要在任何软件工程工作中存在的各种紧张关系之间找到适当的平衡。

    【讨论】:

    【解决方案4】:

    理论上,应该是一个简单的数学问题,只使用三个(相当简单的)变量:

    • S = 使用节省
    • C = 额外抽象的成本
    • P = 使用概率

    如果 S * P > C ,那么代码是好的。如果 S * P

    不过,这纯粹是理论上的原因是,您通常无法猜测使用的可能性或使用它会获得的节省。更糟糕的是,您无法猜测或通常衡量它的存在成本。

    至少有人由此得出了结论。在 TDD 中,标准的口头禅是“你不需要它”(YAGNI)。简而言之,任何不直接对满足当前要求的代码做出贡献的东西都被认为是一件坏事。从本质上讲,他们得出的结论是,使用的可能性非常低,包含这样的额外代码是从不合理的。

    其中一些又回到了“自下而上”与“自上而下”的开发。我倾向于将自下而上的开发视为“库开发”——即您实际上不是在开发特定的应用程序,而是为应用程序中需要的各种东西开发库。我们的想法是,只要有足够好的库,您就可以相对轻松地开发几乎任何该通用类型的应用程序。

    很大程度上还取决于项目的规模。持续使用数十年的大型项目比被丢弃和更换得更快的小型项目证明了更多的长期投资。这在现实生活中也有明显的类似物。您不必担心不到一周就扔掉的一次性剃须刀的合身度、光洁度或做工,就像您在未来几年将要使用的新车之类的东西一样.

    【讨论】:

      【解决方案5】:

      简单来说,如果代码难以理解,那就是抽象太多了。

      现在这并不是说您应该对所有内容进行硬编码,因为这是最容易编写和阅读的代码。

      最简单的测试是要么把它放下几天,然后再拿起它,然后问自己,这是否有意义。更好的方法是将它交给其他人,看看他们是否能做出正面或反面。

      【讨论】:

      • “如果代码难以理解,抽象太多”谁来理解?我已经开始研究极其复杂的代码库,然后几个月/几年后就可以轻松找到我的方式。此外,我还处理过硬编码的东西,如果不插入一些有意义的抽象,就无法理解。
      • 我的意思是,如果代码因为抽象而困难,那就太多了。我并不是说没有抽象的代码很难阅读,但是您应该能够查看代码并说:“好吧,A 点到 B 点。这很有意义。”
      • 我同意凯文的观点。例如,有时我创建一个 shell 脚本来执行重复性工作,但后来我忘记了该脚本是如何工作的,所以最终只使用底层命令。例如,使用“du”脚本:执行脚本需要在哪个目录中?输出文件会放在当前目录吗?脚本是异步的还是阻塞的? (我拥有的确切脚本,称为 disk_usage 基本上是“nohup du > disk_usage_recursive.txt &”,但我最终只是在每种类型中都输入这个命令)。
      • 我同意。我见过创建具有 2 个函数和 2 个变量的抽象(类)的代码。这可以通过参数来完成,但不,开发人员用接口抽象了它,只是为了改变一些布尔值。
      【解决方案6】:

      现实情况是,这取决于您对未来的展望。您希望计划可以预见的更改,而不会创建太多额外的层。如果您有一个在系统之间传输数据的设计,请继续创建一个接口并使用计划的实现作为默认值。例如,您使用 FTP 来移动文件,但知道该标准明年将基于消息(或其他)。

      对于设计中的层,有时添加的层可以更容易地编写更小的类。如果这意味着具体类变得直截了当,则可以添加概念层。

      【讨论】:

        【解决方案7】:

        查看RFC 1925 中的(6a) 项并知道这确实是真的。唯一不能通过添加抽象层来解决的问题是由于抽象层太多而导致的问题。 (特别是,每一个抽象都让整个事情变得更难理解。)

        【讨论】:

          【解决方案8】:

          每个没有实际使用的抽象都太多了。一个系统越简单,就越容易改变。抽象层几乎总是使系统更加复杂。

          OTOH,当然可以在没有任何抽象的情况下编写一个复杂的、无法维护的混乱,有时,“标准化”抽象层可以帮助构建一个比大多数人自己能够做的更好的系统。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-12-01
            • 2011-07-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-26
            相关资源
            最近更新 更多