Function 什么时候函数太长?

Function 什么时候函数太长?,function,refactoring,coding-style,Function,Refactoring,Coding Style,35行,55行,100行,300行?你应该什么时候开始把它拆开?我问这个问题是因为我有一个60行的函数(包括注释),并且正在考虑将其拆分 long_function(){ ... } 进入: 函数不会在long_函数之外使用,使函数更小意味着调用更多函数,等等 什么时候将函数分解为更小的函数?为什么? 方法应该只做一件合乎逻辑的事情(考虑功能) 你应该能用一句话来解释这个方法 它应该适合你显示器的高度 避免不必要的开销(指出明显问题的注释…) 对于小型逻辑函数,单元测试更容易 检查函数的一部分

35行,55行,100行,300行?你应该什么时候开始把它拆开?我问这个问题是因为我有一个60行的函数(包括注释),并且正在考虑将其拆分

long_function(){ ... }
进入:

函数不会在long_函数之外使用,使函数更小意味着调用更多函数,等等

什么时候将函数分解为更小的函数?为什么?

  • 方法应该只做一件合乎逻辑的事情(考虑功能)
  • 你应该能用一句话来解释这个方法
  • 它应该适合你显示器的高度
  • 避免不必要的开销(指出明显问题的注释…)
  • 对于小型逻辑函数,单元测试更容易
  • 检查函数的一部分是否可以被其他类或方法重用
  • 避免类间过度耦合
  • 避免深度嵌套的控制结构
  • 谢谢大家的回答,编辑列表并投票选出正确的答案,我会选择那个;)


    我现在正在重构这些想法:)

    这在一定程度上是一个品味的问题,但我如何确定这一点,我会尽量保持我的函数在一次屏幕上的大致长度(最多)。原因是,如果你能同时看到整个事情,就更容易理解发生了什么

    当我编写代码时,它是编写长函数,然后进行重构以提取可被其他函数重用的位,以及编写执行离散任务的小函数的混合


    我不知道这个问题有没有正确或错误的答案(例如,你可以选择67行作为你的最大行数,但有时添加更多行数是有意义的)。

    我通常分解一个函数的主要原因可能是因为它的一些片段也是我正在编写的另一个邻近函数的组成部分,因此,公共部分得到了分解。此外,如果它使用了其他类中的大量字段或属性,则很有可能会将相关块整体提升,并在可能的情况下移动到其他类中

    如果你有一个顶部有注释的代码块,考虑把它拉到一个函数中,函数和参数名说明它的目的,并为代码的原理保留注释。


    你确定里面没有其他有用的东西吗?它是什么类型的函数?

    一个函数只能做一件事。如果你在一个函数中做很多小事情,那么把每个小事情都变成一个函数,并从长函数中调用这些函数


    你真正不想做的是将长函数的每10行复制粘贴到短函数中(如你的例子所示)。

    没有真正的硬性规则。一般来说,我喜欢我的方法只是“做一件事”。因此,如果它正在抓取数据,然后对该数据执行某些操作,然后将其写入磁盘,那么我会将抓取和写入拆分为单独的方法,这样我的“main”方法就包含了“doing something”

    不过,“做点什么”可能仍然有很多行,所以我不确定有多少行是正确的度量标准:)

    编辑:这是我上周在工作中发的一行代码(为了证明这一点……这不是我的习惯:)-我当然不想在我的方法中有50-60个这样的坏男孩:D

    return level4 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3) && (r.Level4 == (int)level4)).ToList() : level3 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3)).ToList() : level2 != null ? GetResources().Where(r => (r.Level2 == (int)level2)).ToList() : GetAllResourceList();
    

    我想你会在这方面找到很多答案

    我可能会根据函数中正在执行的逻辑任务将其分解。如果你觉得你的短篇小说正在变成一部小说,我建议你找出并摘录不同的步骤

    例如,如果您有一个处理某种字符串输入并返回字符串结果的函数,则可能会根据将字符串拆分为部分的逻辑、添加额外字符的逻辑以及将其重新组合为格式化结果的逻辑来分解该函数


    简言之,让代码干净易读的方法(无论是简单地确保函数有好的注释还是将其分解)都是最好的方法。

    60行是大的,但对于函数来说不是太长。如果它适合编辑器中的一个屏幕,您可以一次看到所有内容。这实际上取决于函数在做什么

    为什么我可以分解一个函数:

    • 太长了
    • 它将代码分解并为新函数使用有意义的名称,从而使代码更易于维护
    • 该函数不具有内聚性
    • 函数的某些部分本身是有用的
    • 当很难为函数想出一个有意义的名称时(它可能做得太多了)

      • 在我看来,答案是:当它做太多事情时。 您的函数应该只执行您期望从函数本身的名称中执行的操作。
        另一个要考虑的是,如果你想重用你的函数的一些部分在其他;在这种情况下,拆分它可能很有用。

        假设您正在做一件事,那么长度将取决于:

        • 你在干什么
        • 你在用什么语言
        • 您需要在代码中处理多少抽象级别

        60行可能太长,也可能刚好。但是我怀疑它可能太长了。

        我通常会因为需要放置描述下一个代码块的注释而中断函数。以前添加到注释中的内容现在添加到新函数名中。这不是硬性规定,但(对我来说)是一个很好的经验法则。与需要注释的代码相比,我更喜欢为自己说话(因为我知道注释通常是存在的)

        大小与您的屏幕大小近似(因此,去拿一个大轴宽屏并转动它)…:-)

        撇开玩笑不谈,每个函数都有一个合乎逻辑的东西

        积极的一面是,单元测试实际上更容易进行
        return level4 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3) && (r.Level4 == (int)level4)).ToList() : level3 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3)).ToList() : level2 != null ? GetResources().Where(r => (r.Level2 == (int)level2)).ToList() : GetAllResourceList();
        
        function build_address_list_for_zip($zip) {
        
            $query = "SELECT * FROM ADDRESS WHERE zip = $zip";
            $results = perform_query($query);
            $addresses = array();
            while ($address = fetch_query_result($results)) {
                $addresses[] = $address;
            }
        
            // now create a nice looking list of
            // addresses for the user
            return $html_content;
        }
        
        function fetch_addresses_for_zip($zip) {
            $query = "SELECT * FROM ADDRESS WHERE zip = $zip";
            $results = perform_query($query);
            $addresses = array();
            while ($address = fetch_query_result($results)) {
                $addresses[] = $address;
            }
            return $addresses;
        }
        
        function build_address_list_for_zip($zip) {
        
            $addresses = fetch_addresses_for_zip($zip);
        
            // now create a nice looking list of
            // addresses for the user
            return $html_content;
        }