我们什么时候应该创建一个新方法?

时间:2009-11-17 15:02:21

标签: design-patterns oop

我试图找出是否就我们何时应该在代码中创建新方法达成共识。例如,如果我们要再次使用代码,那么我们应该只创建一个新的方法/函数(因此我们显然会减少使用的行),或者这样做是为了避免代码混乱。我已经编程很长一段时间但我真的只是进入并以相当随机的方式决定。

是否有任何设计模式或书籍可以解决这个问题?一个相关的问题是,我们是否应该只使用getter和setter方法在对象中设置参数。这会显然创建更多的代码,但会使事情更易于管理?对此有何共识?

19 个答案:

答案 0 :(得分:32)

我认为没有针对此的具体设计指南。但是一些设计原则确实讨论了方法创建。

DRY(不要重复自己)是方法创建的指导原则。您可以在一个方法中对类似的逻辑进行分组,这样您就不会在代码中复制它们,从而使维护成为一场噩梦。

Single Responsibility Principle是另一个。它说你的类或方法应该只做一个的事情。这是为了使方法尺寸变小。

答案 1 :(得分:24)

我认为编程是一门艺术。因此,当感觉正确分裂它们或者写一个新方法时,我会分割方法。

那就是说,有一些拇指规则(否决了我的直觉)。

  1. 如果您需要滚动屏幕以阅读一种方法,则需要将其拆分
  2. 如果你有似曾相识(你写的代码似乎很熟悉),你可能会重复自己,这意味着你应该使用现有的功能/方法而不是写一个新功能。

  3. 深度不超过两个

    有(...)   对于(...)     (...)BAD

  4. 连续不超过一个循环(一个接一个)。

  5. 如果您需要返回多于一种类型的数据(不是null / false版本),那么您需要拆分。
  6. 如果您在阅读方法时感到困惑 - 将其拆分
  7. 方法/功能应该负责一项任务。
  8. 最明显的 - 在编写新功能时: - )

答案 2 :(得分:14)

虽然与面向对象编程无关,但有趣的一点是用linux的编码风格guide制作:

  

第4章:功能

     

功能应该简短而且甜美,只做一件事。它们应该适合一两个屏幕文本(ISO / ANSI屏幕大小为80x24,我们都知道),做一件事并做得很好。

     

函数的最大长度与该函数的复杂度和缩进级别成反比。所以,如果你有一个概念上简单的函数,它只是一个很长(但很简单)的case语句,你需要为很多不同的情况做很多小事情,那么可以有更长的函数。

     

然而,如果你有一个复杂的功能,并且你怀疑一个不太优秀的一年级高中生可能甚至不了解这个功能的全部内容,你应该更加坚持最大限度密切。使用具有描述性名称的辅助函数(如果您认为它具有性能关键性,您可以要求编译器对它们进行内联,并且它可能会比您更好地完成它。)

     

该函数的另一个度量是局部变量的数量。他们不应该超过5-10,否则你做错了什么。重新考虑功能,并将其拆分成更小的部分。人类的大脑通常可以轻松地跟踪大约7种不同的东西,更多的东西,它会混淆。你知道你很聪明,但也许你想了解你从现在起2周后做了什么。

答案 3 :(得分:8)

如果你的方法很长,那么将它们重新分解成较小的块是有意义的,即使这些块在其他任何地方都没有使用过。这将提高可维护性和可测试性。此外,通过这种方法,您可以允许其他开发人员更轻松地扩展您的代码,以防他们想要更改方法的某些职责,例如通过重载它。

至于getter和setter,它在某种程度上取决于你使用的语言。在某些语言中,这可能非常冗长。就个人而言,我只为公共财产提供吸气剂和制定者和/或如果更改财产涉及的逻辑不仅仅是设置/获取财产。

答案 4 :(得分:4)

您可能希望在以下情况下提取方法:

  • 有一个块的注释块
  • 你可以命名一个块的意图

答案 5 :(得分:4)

除了优秀的answer by Graviton之外,我还建议您选择其他经验法则来决定何时创建新方法:

每当您倾向于为一段代码撰写评论时,请将该代码移到专用函数中。为函数指定一个描述性名称。

答案 6 :(得分:2)

我认为这是一个非常主观的问题,没有真正的答案。不同的情况需要不同的解决方案,并且不会有“何时创建新方法”的单一配方。这取决于。

答案 7 :(得分:2)

当你开始在代码块之间放置双重空格以表示不同的职责时。

答案 8 :(得分:1)

方法应该做一件事,做得好。它不应该比它的名字所暗示的更多或更少。 CustomerSave方法也不应该规范客户的地址。

方法应该只关注一个“级别”的功能。如果CustomerSave方法中出现以下各项的多行代码:打开数据库,记录更改,检查安全性等,则代码运行在错误的级别,并且应创建新的方法来处理这些东西是适当的粒度。

方法通常应该非常短。只有在特殊情况下,方法才会溢出多个屏幕。如果一个方法长达一百行,那么事情就非常非常错误。

代码不应重复。应将重复功能放在方法中。

应该设计方法,以便可以轻松地进行典型的更改。如果需要在几十个地方进行小的更改,那么就会发出应该放在一个方法中的重复代码。

答案 9 :(得分:1)

练习对代码进行单元测试,并对方法进行拆分,以便每次可以对一个任务进行单元测试。通过对每个任务进行单元测试的真正外部约束,这是一个很好的方法,可以使整个问题不那么主观。

答案 10 :(得分:1)

我曾经听过有人说如果方法/功能变得太大而无法在不滚动的情况下放在单个屏幕上那么它应该被重构为单独的方法。

它并不总是成立,并且对于重构的折射没有价值,但确实有助于保持透视。

答案 11 :(得分:1)

getter和setter OOP不是,并且通常不会只是代码大小的两倍而没有好处。

至于书籍:设计模式(Gamma,Vlissides,Johnson,Helm),Fowler的书籍(重构,企业应用程序架构模式),Beck的书籍(按示例进行测试驱动开发,实现模式)等。

答案 12 :(得分:1)

查看罗伯特·马丁的Clean Code,其中包含此内容(以及其他内容)

答案 13 :(得分:0)

创建一种方法来完成特定任务。 如果方法的大小增加,这意味着它有一些子任务,因此将子任务分离(重构)到新方法中。

答案 14 :(得分:0)

大多数方法应该完成一项任务。

答案 15 :(得分:0)

根据DRY原则(你和其他一些人已经提到过),你最终不想重复自己。它还取决于您使用的语言。许多面向对象的语言使得所有方法都是公共的(例如Objective-C),因此您只想创建旨在被其他对象调用的函数。另一方面,像Java这样的许多语言都提供了私有函数,这些函数支持将代码块分组为私有函数的概念,这些函数实际上并不是要在类本身之外使用。

答案 16 :(得分:0)

当你重复代码时,几乎总是创建一个新方法。

它会删除重复的代码,如果您选择一个好名字,它会自我记录。

在两个地方出现的同一行代码并不会太短,以至于除非该行是微不足道的,并且其意图非常明显。

答案 17 :(得分:0)

即使只调用一次以限制最大圈复杂度

,也会引入新方法

在我的脑海中,我可以列出很多提取方法的理由,如果有的话,很少有理由将它们组合起来。

  • 显而易见的一个, DRY, aka DIE 在它成长为酷的缩略词之前,我遵循了这一理念。我认为无论出于何种原因,我都不应该出于任何理由复制或复制并粘贴代码。如果你这样做,那你正在酝酿一场噩梦。
  • 限制 cyclomatic complexity 拥有3种可理解的方法比使用一种令人困惑的方法要好得多。即使新提取的方法仅被调用一次
  • ,此规则和其他规则也适用
  • 提取单元测试的功能单元
  • 在不滚动的情况下保持所有方法在编辑器中可见
顺便说一句,我可能会建议改变语言。 “创建新方法”听起来像是在代码中添加一些内容并使其更大更复杂。但是,“提取方法”是您重构一个有希望的优秀设计时真正发生的事情。无论如何,你必须拥有这个功能,那个方法总是在那里,它只是被埋在另一个......

答案 18 :(得分:0)

SLAP和DRY是很好的原则。请参阅此链接http://tv.devexpress.com/SLAPrule.movie Mr.Julian非常好的演讲。 [似乎视频网站已经停止了一段时间。请稍后查看]