过多的抽象会不好吗?


46

作为程序员,我觉得我们的目标是在给定的域模型和业务逻辑上提供良好的抽象。但是这种抽象应该在哪里停止呢?如何在抽象及其所有优点(灵活性,易于更改等)以及易于理解代码及其所有优点之间进行权衡。

我相信我倾向于写过于抽象的代码,但我不知道它有多好。我经常倾向于将其编写为某种微型框架,包括两部分:

  1. 连接在微框架中的微模块:这些模块易于理解,开发和维护为单个单元。这段代码基本上代表了实际执行功能的代码,如需求所述。
  2. 连接代码;现在我相信这里是问题所在。该代码趋于复杂,因为它有时非常抽象,一开始很难理解。之所以会出现这种情况,是因为这仅仅是纯粹的抽象,实际上基础和业务逻辑是在所提供的代码1中执行的;因此,该代码一旦经过测试就不会更改。

这是编程的好方法吗?难道说,变更代码在许多模块中非常分散,并且很容易理解,而变更代码与抽象POV相比却非常复杂?如果所有代码都统一地复杂(即代码1更复杂和相互链接,而代码2更简单),以使通过它的任何人都可以在合理的时间内理解它,但是更改很昂贵,或者上述解决方案是好的, “更改代码”非常容易理解,调试,更改,“链接代码”有点困难。

注意:这与代码的可读性无关!1和2处的代码都是可读的,但2处的代码具有更复杂的抽象,而代码1则具有简单的抽象。


3
发明了注释和清晰的名称以加快理解复杂代码所需的时间。下层代码更复杂是完全可以的。在某种程度上,您几乎肯定会称其为更复杂和更低的级别。
DougM 2013年

25
按照定义,“太多”是不好的。
乔恩·普迪

@JimmyHoffa:一定要保留这些类型。不要嫉妒,我不要写Haskell的所有日子。实际上主要是PHP,JavaScript和OCaml。
乔恩·普迪

Answers:


78

TC ++ PL4的第一句话:

计算机科学中的所有问题都可以通过另一层间接解决,除非存在太多的间接层。–戴维·J·惠勒

(大卫·惠勒(David Wheeler)是我的论文顾问。有时没有重要的最后一行的引用有时被称为“计算机科学的第一定律”。)


6
以及如何知道何时有太多的间接级别?我倾向于说这是有经验的,但是经验丰富的程序员可以轻松地理解更多的间接性,因此不会发现层次过多的问题。
m3th0dman

2
@ m3th0dman-当将来容易进行更改时,您具有正确的抽象级别。当然,您也可以问自己如何知道什么时候发生,只是以不同的方式重复问题循环。


1
这个问题就像程序员级别的依赖..您将拥有复杂的程序员,他们将了解您疯狂的8层体系结构并发现它很棒,而其他简单但流畅的编码人员将发现它可笑并争论您疯狂的8层分层的项目..这是文件的回报,不仅使您可以记录代码,而且可以保护它
Ryan

1
原谅我的无知,但我不理解“ TC ++ PL4”
LastTribunal

30

当然是。问题是,没有抽象是完美的。放在上面的抽象层的所有细节都是有原因的,它可以简化很多事情,但是如果在某些时候不需要那种复杂性,那么它可能根本就不会存在。这意味着在某个时候,每个抽象都会以某种方式泄漏。

这就是真正的问题所在。当抽象失败时,您在编写的代码和实际发生的事情之间分层使用的代码越多,找出问题并加以解决的难度就越大,因为可能存在更多的问题。而且层数越多,您必须了解的越多,以便对其进行追踪。


1
“这意味着在某个时候,每个抽象都将以某种方式泄漏。”:正确。更好的抽象是泄漏较少的抽象。
Giorgio 2013年

11
根据Bjarne的回答(并参考David Wheeler的wiki页面),也许您可​​以更改报价来源?:)
congusbongus

2
@CongXu:顺便说一句,我从另一端出发:谷歌搜索“ Bjarne Stroustrup引号”,还没有找到Bjarne说出“添加另一层间接”这一短语的唯一参考...当然不是结论,但是确实使他极不可能第一个说出来。
Marjan Venema 2013年

1
更多的抽象层意味着简单的抽象,因此每个抽象的泄漏更少。因此,在数学公式化中(当然,没有任何证据),抽象泄漏的总和可能随抽象级别数的变化而恒定。
m3th0dman

2
我曾经天真地接受了大四学生的建议,在不需要的地方添加了抽象。一开始我从未想过使用它。
Cees Timmerman

15

是的,一点没错。

我喜欢用来解释编程的类比是裁缝。制作西服时,好的裁缝师总是会在服装内的重要位置留下少量织物,以使服装可以进出,而无需改变其整体形状或结构。

好的裁缝不要在每个接缝处留下大量的织物,以防万一您碰巧长出第三只手臂或怀孕了。在错误的地方放置过多的材料会造成不合适的合身性,以及穿着不良的衣服,多余的织物只会妨碍正常使用。对于很少的织物,衣服容易流泪,将无法进行更改以适应穿着者体形的微小变化,从而影响衣服的坐姿。

也许有一天,我们的“好裁缝”将被要求做一件如此紧的衣服,以致不得不缝制衣服。也许我们的Good Tailor被要求制作孕妇装,其风格和合身性仅次于舒适性和可扩展性。但是在从事这两项特殊工作之前,优秀的裁缝将足够明智,以使每个人都意识到为实现这些目标而做出的妥协。

有时,这些妥协是采取的正确方法,人们愿意接受其后果。但是,在大多数情况下,在最重要的地方多花一点钱的方法会胜过任何可感知的收益。

因此,将其与抽象联系起来。它绝对可能有太多的抽象层,就像它可能有太多的方法一样。像我们的裁缝朋友一样,程序员的真正艺术是将最重要的地方留一点。

回到正题。

代码的问题通常不是抽象,而是依赖关系。正如您所指出的,连接离散对象的代码是一个问题,因为它们之间存在隐式依赖性。在某些时候,事物之间的交流只需要具体,但是判断该点通常需要一些猜测。

所谓“微”的东西通常表示您已经过度细化了对象布局,并且可能正在使用Type作为应为Data的同义词。拥有更少的东西也意味着更少的相互依赖关系。

因此,我非常喜欢系统之间的异步消息传递。您最终得到了两个依赖于该消息的系统,而不是彼此依赖。使您的通信系统之间的耦合不那么紧密。在这一点上,如果需要在系统之间建立依赖关系,则需要考虑是否在正确的位置依赖了位。而且通常情况是您不这样做。

最后,复杂的代码将变得复杂。通常没有办法解决。但是比起依赖于各种外部状态的代码,具有更少依赖性的代码要容易理解。


2
+1表示“ Good Tailor's不要在每条接缝处留下大量的布料,以防万一您长出第三只手臂或怀孕”。可悲的是,我们经常倾向于以这种方式设计软件。
Kemoda

除了易于理解之外,将曲线弯曲成笔直的线条时,还可以发现抽象很有用。意味着您正在通过抽象降低复杂性和/或熵。也许像Curry类型的数据处理程序之类的东西,在以后您仍然可以剃掉脂肪。
科迪2014年

13

我觉得我们的目标是在给定的域模型和业务逻辑上提供良好的抽象。

我有不同的看法:我们的目标是解决业务问题。抽象只是组织解决方案的一种技术。另一个答案是使用裁缝制作衣服的类比。我还有一个想比喻的比喻:骨架。代码就像骨架,抽象是骨头之间的关节。如果您没有关节,那么您只剩下一条骨头,它根本无法移动并且毫无用处。但是,如果关节过多,就会出现一堆无法自立的草。诀窍是要找到合适的平衡点-足够的关节允许移动,但又不要太大,以至于没有实际定义的形状或结构。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.