【问题标题】:Good Coding Practices: When to Create New Functions良好的编码实践:何时创建新函数
【发布时间】:2013-06-27 17:00:22
【问题描述】:

我有一个特定的函数使用相同的代码行(很少,2-5 取决于我如何更改它以适应未来可能的用途)代码行 4 次。

我查看了this question,但它对我来说不够具体,也不符合我的方向。

这里有一些

function myFunction() {
  if (something) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else if (somethingElse) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else if (anotherThing) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else if (theLastThing) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else {
  // Not previously used code
  }
}

复制/粘贴相同的 3 行代码(如果满足任何这些条件,则构造相同的对象)。创建一个可以将所有这些信息传递给它并在完成后返回必要信息的函数是一种好习惯吗?所有这些条件语句都在一个循环中,可以运行多达 1000 次左右。

我不确定通过跳转到另一个函数来准备 堆栈帧(?) 的成本是否比 1000 次迭代更昂贵,值得拥有约 15 行重复代码。显然,对其进行功能化会使其更具可读性,但是这是非常具体的功能,在其他任何地方都不会使用。我可以编写来消除复制/粘贴心态的函数类似于:

function myHelperFunction(someParameter, someOtherParameter) {
  // Code line 1
  // Code line 2
  // Code line 3
  return usefulInformation;
}

然后在所有这些条件语句中调用该函数作为每个条件语句 1 行:

myHelperFunction(myPassedParameter, myOtherPassedParameter);

基本上将这 12 行变成了 4 行。

所以问题 - 一般来说这是一个好习惯,为非常少量的代码创建一个新函数以节省一些空间和可读性吗?或者跳跃功能的成本是否影响太大而不值得?是否应该总是为将来可能复制/粘贴的任何代码创建一个新函数?

PS - 我知道如果这段代码要在不同的(类)或源文件中使用,将它变成一个函数以避免需要找到它被复制/粘贴的所有位置是合乎逻辑的为了做出改变。但我说的或多或少是一种两难的单文件/单类或函数内。 此外,如果我没有正确执行,请随时修复我的标签/标题。我不太确定如何正确命名/标记这篇文章。

【问题讨论】:

  • 许多编译器/解释器可以/将在可能的情况下内联函数,这意味着除非您的函数是递归的(有时即使如此,请参阅tail call),您可以毫无开销地调用它。
  • 我刚刚阅读了一些关于内联函数的内容 - 是 C/C++/C# 特定的吗?还是 Javascript 编译器也这样做?我没有指定任何我希望函数内联的标志,而且我不确定 JS 编译器是否会自动知道何时使函数内联。你有什么想法吗?
  • 我不确定 Google 的 JS 服务,但 IonMonkey(Firefox 使用的编译器)有函数内联。所以在JS中绝对可以做到。至于内联哪些函数,打开内联的编译器将内联每个他们认为“简单”到值得内联的函数。
  • 好的,我知道谷歌,我确信他们的 JS 服务就是这样做的!
  • 性能方面我只能说这取决于。许多环境(例如 .net 和 JVM)可能会为您内联它。我会这样做是为了提高可读性,然后检查它是否会对性能产生负面影响,但这不太可能。

标签: function language-agnostic code-readability


【解决方案1】:

任何不是算法/数据结构问题的优化问题的答案是:分析您的代码!仅优化显示为问题区域的内容。

这意味着您应该找出函数调用开销是否实际上是您正在编写的特定程序中的性能问题。如果是,则内联代码。如果不是,不要。就这么简单。

【讨论】:

  • 嗯...我实际上从未做过任何分析。这是通过 Google Apps Script 服务用 Javascript 编写的。除了设置计时器以查看执行时间有多大差异之外,我不确定如何做到这一点。我非常怀疑我是否能看到内存分配/使用情况,尽管在这种特殊情况下这可能并不重要,因为所有代码都在谷歌的后端 JS 服务上运行。但这也是未来编码的一个问题,因为我是新来的场景,并希望确保我使事情尽可能高效和可读。
【解决方案2】:

在我看来,你的做法是错误的。首先,你不应该使用多个(else)if,它们都执行相同的代码;将一个与复合或预计算(在这种情况下,由于所有可能的子条件,我建议预计算)条件一起使用。这样的事情可能会使代码的维护变得容易得多。

function myFunction() {
  bool condition = something ||
                   somethingElse ||
                   anotherThing ||
                   theLastThing;

  if (condition) {
    // Code line 1
    // Code line 2
    // Code line 3
  }
  else {
  // Not previously used code
  }
}

【讨论】:

  • 这些条件包含多个比较器,即if (x > y && y < z && b == b)。将其乘以 4,您就有 12 个条件。如果每个条件都有 2 次以上的比较,那么为所有这 4 个条件声明一个布尔值是否仍然有效? PS - 这是 Javascript,我不确定这是否是语言的语法限制,但请告诉我,因为这实际上会简化我的代码!也谢谢你:)
  • @ChrisCirefice 是的(当然,只要在重要的地方保留操作顺序)。由于布尔代数是一个定义明确的领域,您甚至可以像简化复杂的数学方程一样简化复合条件。 sandbox.mc.edu/~bennet/cs110/boolalg/simple.html(请注意,* = and+ = or,如果由于某种原因你还没有意识到这一点)
  • 我不知道这些运算符的相等性哈哈,但我实际上是在比较 Javascript Date 对象,所以我只使用<>=。我会看看重写我所有的比较,我不知道你可以像这样把它们都复合起来。当然,肯定会提高可读性!
  • PS - 我希望我能接受你的回答,因为它确实解决了我在代码中遇到的一个巨大问题,但它并不完全适用于我原来的问题。不过,我确实赞成您的回答,因为它绝对有帮助:)
  • @ChrisCirefice *=and, +=or 适用于布尔代数的表示,而不适用于实际的计算机代码。您需要像往常一样使用&& 来表示and|| 来表示or
【解决方案3】:

是的,创建一个函数,通常你应该遵循 DRY 原则。不要重复自己。

http://en.wikipedia.org/wiki/Don%27t_repeat_yourself

对于这样的事情,您的堆栈操作将是最小的。请参阅 Imre Kerr 对您的问题的评论。

这不仅仅是为了可读性。这么多原因。可维护性是巨大的。如果必须更改此代码,那么其他人出现并尝试找出更改它的每个地方都会很痛苦。只需要在一个地方更改代码要好得多。

【讨论】:

  • 没错,我一开始就是这么想的。我只是不知道开销(如果有的话)是否是把这么少的代码变成它自己的函数的问题,只是为了防止一点点复制/粘贴。但现在我知道了!感谢您的回复:)
【解决方案4】:

我不知道这是否适用于您提供的示例,但是分解代码不是编写函数的唯一原因,您也可以从测试的角度考虑

一个函数提供了一个可以单独测试的编程单元。

因此,您可能会将复杂的操作分解为几个更简单/更基本的单元,即使这些函数只被调用一次。

既然你问了几行代码的问题,你可以问自己:

  • 我可以合理地命名这个函数吗?
    (justDoThis 应该没问题,doThisAndThatAndThenAnotherThing 少)
  • 是否有合理数量的参数?
    (我会说两个或三个)
  • 是否值得将其作为一个单独的单元进行测试?
    (它是否简化了整体测试)
  • 使用这种函数调用代码是否更易读/易理解?
    (如果前两个问题的答案是否定的,则不一定很明显)

【讨论】:

  • 好吧,据我所知,Google 的 JS 引擎除了手动测试(我已经广泛完成)之外没有其他测试功能。但是这个答案很有帮助——当我今年夏天为我的非工作项目回到 Java 时,我一定会记住这一点!谢谢:)
【解决方案5】:

这是一个很好的问题,答案是:视情况而定。

我个人会创建一个函数来提高代码的可读性,但如果您正在寻找效率,也许您希望保留复制和粘贴的代码。

【讨论】:

  • 这正是我想看到性能堆栈帧/执行时间/内存使用等方面的差异的原因;虽然我不知道如何进行很多分析,但我想我会补充一点,以防万一熟悉该过程的人对性能有任何想法:P
猜你喜欢
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多