Fat vs. Skinny Design

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

似乎面向对象编程(OOP)中的类型/类层级可以以两种极端方式设计:一种是考虑对数据进行完全封装;另一种是只有少数接口使原始数据可见,并让类来处理、解析并将其转化为较小的数据元素。也许你会感到惊讶,但我认为第二种选择更加优雅。在我看来,我们并没有失去面向对象特性,相反却获得了很多灵活性、可重用性、可测试性等。

请看一下这个(我们称之为fat,稍后我会解释为什么):

要获得作者的姓名,我们需要执行以下操作:

从视觉上看,这个设计可能像这样(在 UML 中):

允许混合 接口 文章 接口 标题 接口 作者 文章 o-> 标题 : “head()” 标题 o-> 作者 : “author()” 作者 : String name() 作者 : String email() 文章 <– PgArticle 标题 <– PgHead 作者 <– PgAuthor PgArticle o-> PgHead PgHead o-> PgAuthor 组件 PostgreSQL PgArticle ..> PostgreSQL PgHead ..> PostgreSQL PgAuthor ..> PostgreSQL

现在,让我们将其与另一种设计进行比较(这种设计比之前的设计要“瘦”得多,我甚至会称之为“纤细”):

在这里,为了获得作者的名字,我们需要将头部作为String进行提取,将作者作为String进行提取,然后将名字作为String进行提取。

在UML中,它的视觉效果如下:

allowmixing Interface Article TxtAuthor *- TxtHead TxtHead *- Article Article : String head() TxtHead : String author() TxtAuthor : String name() TxtAuthor : String email() Article <– SqlArticle component PostgreSQL SqlArticle ..> PostgreSQL

在第一个设计中有三个接口,而第二个设计只有一个接口和两个类。我将第一个称为“肥胖”,因为它返回实现我们所需功能的接口,我们不需要使用额外的装饰器或适配器来覆盖它们。它的三个接口的层次结构已经足够丰富,可以提供我们所需的一切。这就是为什么它是肥胖的原因。另一方面,第二个设计相当“纤瘦”,只有一个接口,它返回我们需要自己解析的纯文本数据。我们需要对它进行装饰。

基于一些原因,看起来纤瘦的设计更好:

  • 内聚。瘦设计明显更具内聚性,因为与管理PostgreSQL数据有关的所有内容都集中在一个类SqlArticle中。相反,臃肿的设计将功能分散在许多类中,因此使整个类集更难以维护。

  • 可重用性TxtAuthor 类可以在任何需要解析作者信息的地方使用,而 PgAuthor 类仅适用于一个特定情况:获取和解析与 PostgreSQL 相关的数据。

  • 可测试性。显然,瘦型设计更容易进行测试,因为模拟单个接口比模拟整个层次结构更简单。要测试TxtAuthor类,我们只需向其构造函数传递一些虚假的文本并检查其工作情况。要测试PgAuthor类,我们需要做更多的工作,包括运行一个虚假的PostgreSQL服务器实例。

上述的一切都适用于从PostgreSQL的数据检索和对PostgreSQL的数据操作,当然,操作可能需要许多方法存在于SqlArticle中,这将使得瘦身设计看起来很丑陋,并且很明显一些这些方法必须移动到较低级别的类/接口中。这只是证明了并不总是可能通过单个接口来实现瘦身设计,就像上面的例子一样。有时候,我们只好让它更加丰满。

然而,瘦身设计存在一个严重问题:它让原始裸露的数据跳出了SqlArticle,这与面向对象编程的理念背道而驰,正如我们所知。确实,如果我们让TxtHead进行解析,我们可能会丢失一些仅在SqlArticle内部可用的有关PostgreSQL的上下文信息。我们不希望复杂的数据解析发生在离数据产生的地方很远的地方。我们希望所有与数据相关的事情都发生在数据所在的地方:SqlArticle内部。

这是一个有效的关注点,但是让与PostgreSQL相关的信息(比如连接设置)从PgArticle移动到PgHead,然后再移动到PgAuthor,这会更加违反数据封装原则。

在现实生活中,当然不可能想象纯粹的单一接口瘦身设计。它们都会在一定程度上是丰满的。我的建议是尽量让设计变得更瘦身,让接口使用者可以按照自己的喜好进行装饰。这个建议与我之前关于智能类的说法非常接近,但这次原则更加广泛。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-18 at 05:00

sixnines availability badge   GitHub stars