纯粹出于美学原因创建嵌套函数?


16

我一直想知道其他程序员对创建纯美学功能的想法有何看法。

假设我有一个处理大量数据的函数:Function ProcessBigData。说我需要几个处理步骤,仅适用于数据:Step1Step2Step3

我在源代码中看到最多的普通方法是像这样编写注释:

Function ProcessBigData:
    # Does Step1
    Step1..
    Step1..

    #Does Step2
    Step2..
    Step2..

我通常做的是,但由于同伴缺乏这种编码风格,总是感到不对劲:

Function ProcessBigData:
    Function Step1:
        Step1..
        Step1..

    Function Step2:
        Step2..
        Step2..

    Step1() -> Step2()

我主要担心的是,这种样式在JavascriptPython中是否有缺点

我没有其他替代品吗?


3
我对Python没什么好说的,但是对于Javascript,嵌套函数会降低性能:大多数JavaScript引擎都使用类似链表的结构来表示变量作用域。因此,添加额外的功能层将迫使引擎在解析变量时可能搜索更长/更大的数据结构。另一方面,所有邪恶的根源当然是过早的优化。:)
Marco Marco

Answers:


4

这并不像您想的那样奇怪。例如,在Standard ML中,习惯上限制助手功能的范围。当然,SML的语法可以简化它:

local
    fun recursion_helper (iteration_variable, accumulator) =
        ... (* implementation goes here *)
in
    fun recursive_function (arg) = recursion_helper(arg, 0);
end

我会考虑这种良好的风格,因为1)较小的功能有助于对程序进行推理,2)它向读者发出信号,这些功能未在该范围之外使用。

我想每当调用外部函数时,创建内部函数都可能会有一些开销(我不知道JS还是Python是否优化了它),但是您知道它们对过早优化的看法。


11

只要有可能,这样做通常是一件好事,但是我喜欢将这类工作视为“步骤”,而不是子任务

子任务是可以完成的特定工作单元:它具有特定的责任,并定义了输入和输出(以SOLID的“ S” 为例)。子任务不需要可重复使用:有些人倾向于认为“我再也不必从其他任何地方调用它了,为什么还要将其编写为函数?” 但这是一个谬论。

我还将尝试概述其好处以及它如何应用于嵌套函数(闭包),而不是类中的另一个函数。一般来说,除非您特别需要使用闭包,否则建议您不要使用闭包(有很多用途,但是将代码分成逻辑块不是其中之一)。

可读性。

超过200行的程序代码(一个函数的主体)很难阅读。2-20行功能易于阅读。代码适用于人类。

无论是否嵌套,大多数情况下都会获得可读性的好处,除非您从父级作用域中使用了很多变量,在这种情况下,它就很难阅读。

极限变量范围

拥有另一个功能会迫使您限制变量范围,并明确传递所需的内容。

这通常也使您的代码结构更好,因为如果您需要早期“步骤”中的某种状态变量,则可能实际上发现实际上还有另一个子任务应该首先编写并执行才能获得该值。换句话说,这使得编写高度耦合的代码块变得更加困难。

具有嵌套函数可让您从嵌套函数内部访问父范围内的变量(关闭)。这可能非常有用,但也会导致细微,难以发现的错误,因为函数的执行可能不会按照编写方式发生。如果要在父作用域中修改变量,则情况更是如此(通常这是一个非常糟糕的主意)。

单元测试

实现一个功能(甚至是一个类)的每个子任务都是独立的,可测试的代码。单元测试TDD的好处已在其他地方得到了充分证明。

使用嵌套函数/闭包不允许进行单元测试。对我而言,这是一个破坏交易的原因,除非您特别需要关闭,否则您应该只是另一个功能。

团队合作/自上而下的设计

如果需要,子任务可以由不同的人独立编写。

即使是您自己,编写代码以简单地调用一些尚不存在的子任务,同时构建主要功能,并担心仅在知道它将在子菜单中获得所需结果后才真正实现子任务时,这很有用。有意义的方式。这也称为自顶向下设计/编程。

代码重用

好的,尽管我刚才说了,但有时确实确实是后来成为将子任务重用于其他用途的原因。我根本不是在提倡“架构宇航员”主义,而只是通过编写松散耦合的代码,您可能最终会从重用中受益。

通常,重用意味着某些重构,这是完全可以预期的,但是将输入参数重构为小的独立函数比编写后几个月从200多个行函数中提取出来要容易得多。

如果您使用嵌套函数,则重用它通常还是要重构为一个单独的函数,这又是为什么我认为嵌套不是解决之道的原因。


2
这些是总体上使用函数的一些真正有效的要点,但是如果您认为NESTED函数是一个好主意,我从您的答案中并未得到帮助。还是在上游范围内使用这些功能?
Slytael 2014年

很抱歉,我忘了解决那部分的其他好处。:)编辑。
gregmac 2014年
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.