我是一个长期的开发人员(我是49岁),但对面向对象的开发而言是新的。自Bertrand Meyer的Eiffel以来,我一直在阅读有关OO的信息,但确实做了很少的OO编程。

关键是OO设计上的每一本书都以船,汽车或我们经常使用的任何常见对象的示例开始,它们开始添加属性和方法,并解释它们如何建模对象的状态以及可以做什么它。

因此,它们通常会像“模型越好,它代表应用程序中的对象越好,并且它越好。”

到目前为止一切都很好,但是,另一方面,我找到了几位作者,这些作者提供了诸如“班级应该仅适合一页”之类的食谱(我会添加“在什么监视器上?”,现在我们不尝试不尝试打印代码!)。

以一个 PurchaseOrder 班级,具有控制其行为的有限状态机,并集合 PurchaseOrderItem, ,工作中的一个论点之一是我们应该使用 PurchaseOrder 简单类,有一些方法(仅仅是数据类),并且有一个 PurchaseOrderFSM 处理有限状态机的“专家类” PurchaseOrder.

我要说的是杰夫·阿特伍德(Jeff Atwood 代码气味 关于编码恐怖的帖子。我只是称之为常识。如果我可以发行,批准或取消我的真实采购订单,那么 PurchaseOrder 课应该有 issuePO, approvePOcancelPO 方法。

这是否与“最大化的凝聚力”和“最小化耦合”的古老原则是我理解为OO基石的古老原则吗?

此外,这是否有助于班级的可维护性?

有帮助吗?

解决方案

班级应使用单一责任原则。我见过的大多数非常大的课程都对许多事情做了,这就是为什么它们太大的原因。查看每个方法和代码确定应该在此类中或单独的,重复代码是一个提示。您可能有一个ISSUEPO方法,但是它是否包含10行数据访问代码?该代码可能不应该在那里。

其他提示

我认为,只要变量,函数和方法与所讨论的类有关,班级规模就无关紧要。

大型课程的最大问题是测试这些课程或与其他类别的互动。班级大小本身并不是问题,但是像所有气味一样,它表明 潜在的 问题。一般而言,当课堂很大时,这表明该类的做得超过单个班级。

对于您的车类比,如果课堂 car 太大了,这可能表明它需要分为课堂 engine, , 班级 doorS和班级 windshieldS,等

我认为没有一个特定的定义对班级太大。但是,我将使用以下准则来确定我应该重构课程还是重新定义课程范围:

  1. 是否有许多彼此独立的变量? (在大多数情况下,我的个人容忍度约为10至20)
  2. 有许多用于角案例的方法吗? (我的个人宽容是...好吧,这很大程度上取决于我的心情)

关于1,想象一下您定义挡风玻璃尺寸,车轮尺寸,尾灯灯泡型号以及班级其他100个细节 car 。尽管它们都与汽车“相关”,但很难追踪此类班级的行为 car. 。而且,当您有一天您的同事意外(或在某些情况下是故意的)根据尾灯泡模型改变挡风玻璃的大小时,它将需要您永远找出为什么挡风玻璃不再适合您的汽车。

关于2,想象一下您试图定义汽车在班上可能具有的所有行为 car, , 但 car::open_roof() 仅适用于敞篷车, car::open_rear_door() 不适用于那些2门汽车。尽管根据定义,敞篷车和2门汽车是“汽车”,但在课堂上实施它们 car 使班级复杂化。班级变得更难使用,更难维护。

除了这两个准则外,我还建议对班级范围进行明确的定义。定义范围后,严格根据定义实现类。在大多数情况下,人们因范围的定义差而获得了“太大”的班级,或者由于添加了班级的任意功能

说出300行中的需要

注意:此经验法则假设您正在遵循“每个文件一级”方法,这本身就是一个很好的可维护性想法

这不是绝对的规则,但是如果我在一个班级中看到超过200行代码,我会怀疑。 300条线和警告铃响了。当我打开别人的代码并找到2000行时,我知道这是重构时间,甚至没有阅读第一页。

通常,这取决于可维护性。如果您反对如此复杂,以至于无法以300行的方式表达其行为,那么别人很难理解。

我发现我在模型 - > viewModel->查看世界中为UI页面创建一个“行为对象”的世界,因为它通常需要300多行来描述上完整的行为系列页面。但是,我仍然是这个编程模型的新手,并找到了在页面/ViewModels之间进行重构/重复使用行为的好方法,这正在逐渐减少我的ViewModels的大小。

让我们向后抓住它:

这是否与“最大化的凝聚力”和“最小化耦合”的古老原则是我理解为OO基石的古老原则吗?

实际上,它是编程的基石,OO只是一个范式。

我让 Antoine de Saint-Exupéry 回答您的问题(因为我很懒;):):

实现了完美,而不是当无需添加时,而是当没有什么可带走的时候。

班级越简单,您的信心就越正确,就越容易 完全 测试它。

我在功能羡慕分类的OP上。没有什么比在其他班级的内部班级上使用一系列方法的一堆课程更刺激了我了。 OO建议您对数据和该数据的操作进行建模。这并不意味着您将操作与数据不同!它试图让您放置数据和这些方法 一起.

carperson 模型如此普遍,就像将电气连接甚至旋转到启动器中的代码一样 person 班级。我希望这会 显然是错误的 给任何经验丰富的程序员。

我真的没有理想的类或方法大小,但是我更喜欢将我的方法和功能保持在一个屏幕上,以便我可以在一个地方看到它们的整体。 (我已经配置为打开一个60线窗口,恰好在印刷页面上的线路数。)在某些地方,这没有很多意义,但对我有用。我喜欢遵循相同的准则定义指南,并尝试将文件保留在几个“页面”下。超过300条的400行开始感到笨拙(主要是因为班级开始承担过多的直接职责)。

当类定义具有几百种方法时,它太大了。

我完全同意使用 单一责任原则 对于课堂,如果遵循的话并导致大型课程,那就这样吧。真正的重点应该是单个方法和属性不太大, 循环复杂性 应该是那里的指南和之后,可能会导致许多私人方法,以增加整体班级的规模,但可以使其可读并且可以测试到颗粒状水平。如果代码保持可读性,则大小无关紧要。

发行采购订单通常是一个复杂的过程,不仅涉及采购订单。在这种情况下,将业务逻辑保留在单独的类中,并使采购订单更简单可能是正确的选择。不过,总的来说,您是对的 - 您不需要“数据结构”类。例如,您的“ Pomanager”商务舱 issue() 方法可能应该调用PO issue() 方法。然后,PO可以将其状态设置为“已发行”并注意发行日期,而Pomanager则可以将通知发送给应付帐款的通知,以便让他们知道发票,并向库存发送另一个通知,以便他们知道有些东西会进来,并且预期日期。

任何针对方法/班级规模推动“规则”的人显然都没有在现实世界中花费足够的时间。正如其他人提到的那样,这通常是一个重构指标,但有时(尤其是在“数据处理”型工作中)您确实需要用单个方法编写跨500多行的方法。不要挂在上面。

我找到了几位作者,这些作者提供了诸如“课堂只能在一个页面中适合”之类的食谱

就课堂的身体大小而言,看到大班级是代码气味的指示,但并不一定意味着总是有气味。 (虽然他们通常是)正如加勒比海盗中的海盗所说的那样,这是您所说的“准则”,而不是实际规则。我严格遵循一次“班级中不超过一百个LOC”的尝试,结果是很多不必要的过度工程。

因此,它们通常会像“模型越好,它代表应用程序中的对象越好,并且它越好。”

我通常从此开始设计。这个班级在现实世界中做什么?我的班级应该如何反映其要求中所述的这个对象?我们在这里添加一些状态,一个字段,一种在这些字段上使用的方法,添加一些和瞧!我们有一个工人阶级。现在,用适当的实现来填写签名,我们可以考虑,或者您认为。现在,我们拥有所需的所有功能,我们将获得了不错的大型课程。但是,这样做的问题是,它并没有考虑到现实世界的运作方式。因此,我的意思是没有考虑到“更改”。

最好将类分为较小的部分的原因是,以后很难更改大型类,而不会影响现有的逻辑或无意间引入一个新的错误,或者只是使一切都难以重复使用。在这里,重构,设计模式,固体等要进行游戏,最终结果通常是在其他较小,更详细的子类中工作的小班级。

另外,在您的示例中,添加issuepo,批准和取消po在购买订单类中似乎是不合逻辑的。采购订单不会发出,批准或取消自己。如果PO应该有方法,那么这些方法应该在其状态下不在整个课程上。它们确实只是其他类工作的数据/记录类。

足够大,可以包含所有必要的逻辑来执行其工作。

足够小,可以维护并遵循 单一责任原则.

许可以下: CC-BY-SA归因
scroll top