代码之家  ›  专栏  ›  技术社区  ›  Pim Jager

长方法应该在它自己的类中还是在函数中只使用一次?

oop
  •  1
  • Pim Jager  · 技术社区  · 17 年前

    很多时候,在互联网上的代码或同事的代码中,我看到他们只用一种方法创建一个对象,在整个应用程序中只使用一次。这样地:

     class iOnlyHaveOneMethod{
       public function theOneMethod(){
         //loads and loads of code, say 100's of lines
         // but it only gets used once in the whole application
       }
     }
    
     if($foo){ 
      $bar = new iOnlyHaveOneMEthod;
      $bar->theOneMethod();
     }
    

    那真的更好吗

    if($foo){
     //loads and loads of code which only gets used here and nowhere else
    }
    

    ?
    为了可读性,将加载的代码移开是有意义的,但它不应该只是在函数中吗?

    function loadsAndLoadsOfCode(){
     //Loads and loads of code
    }
    if($foo){ loadsAndLoadsOfCode(); }
    

    将代码移动到一个新对象真的比仅仅创建一个函数或直接将代码放入其中更好吗?
    对我来说,函数部分比创建一个几乎没有任何用处的对象更有意义,看起来更易读,因为它只包含一个方法。

    10 回复  |  直到 17 年前
        1
  •  9
  •   The Archetypal Paul    17 年前

    问题不在于它是在函数中还是在对象中。

    那几百条线在干什么?这就是实现面向对象最佳实践的地方。

        2
  •  4
  •   Eran Galperin    17 年前

    好的,如果方法中确实存在代码的“加载和加载”,那么应该将其分解为该类中的几个受保护的方法,在这种情况下,使用类作用域是合理的。

    也许代码是不可重用的,因为它没有被很好地分解成几个不同的方法。通过将它移动到一个类中并将其分解,您可能会发现它可以更好地在其他地方重用。至少它会更易于维护。

        3
  •  2
  •   Dan Vinton    17 年前

    虽然包含数百行代码的函数清楚地指出了一个问题(正如其他人已经指出的),但将它放在一个单独的实例类中,而不是一个静态函数中 有一些优势,您可以通过重新调整示例来利用这些优势:

    // let's instead assume that $bar was set earlier using a setter
    if($foo){ 
        $bar = getMyBar();
        $bar->theOneMethod();
    }
    

    现在,这为您提供了两个优势:

    • Strategy Pattern . 如果 $bar 实现一个接口,该接口提供 theOneMethod()

    • 独立测试你的类 $bar->theOneMethod() 非常简单,因为您可以替换 $bar 在测试时使用模拟。

    我认为,虽然简单的静态函数有自己的位置,但非平凡的方法(正如“数百行”注释中明确指出的那样)无论如何都应该有自己的实例:

    • 分离关注点;
    • 帮助重构和重新实现。
        4
  •  1
  •   Svante    17 年前

    • 仅仅声明一个函数比创建一个只包含这个函数的对象好吗?
    • 任何函数都应该包含“代码负载”吗?

    第二部分:理想情况下不是,但“荷载”没有明确的定义,在某些情况下,这可能是适当的做法。

        5
  •  0
  •   Joel Martinez    17 年前

    是的,负载和代码负载的存在是一个问题 Code Smell .

        6
  •  0
  •   Simon Groenewolt    17 年前

    不过,将其移动到对象可能是重构的第一步,所以这样做可能有意义。首先将其移动到自己的类中,然后将其拆分为几个较小的方法。

        7
  •  0
  •   Simon B. Jensen    17 年前

    嗯,我想说这取决于代码块与调用代码段的紧密耦合程度。

    若它是如此紧密地耦合,以至于我无法想象它会在其他任何地方使用,我更愿意将它固定在调用类的私有方法中。这样系统的其他部分就看不到它,保证它不会被其他人滥用。

    另一方面,如果代码块是通用的(电子邮件验证,即)在系统的其他部分可能是有趣的,那么我将毫无疑问地将该部分提取到它自己的类中,然后将其视为实用类。即使这意味着它将是一个单一的方法类。

    如果你的问题更多的是“如何处理成百上千行的代码”,那么你真的需要做一些重构。

        8
  •  0
  •   Tom    17 年前

    一个包含大量代码的单一方法就是一种代码气味。我的第一个想法是至少让这个方法是静态的。类中没有数据,因此不需要创建对象。

        9
  •  0
  •   leora Matt Lacey    17 年前

    singles responsibility principle . 是否可以将类的各个部分分解为单独的小部分,这些小部分可能会相互独立地更改(数据访问和解析等)。你能很容易地对你的类进行单元测试吗。

    如果您可以对上述各项说是,我就不必担心方法与新类的区别,因为这里的重点是您拥有可读的、可维护的代码。

    在我的团队中,如果一个类变长(超过x行数),我们会发出红旗,但这只是一个启发,因为如果您的类有2000行代码,它可能会被分解,并且可能不支持SRP。

        10
  •  0
  •   Chris Conway    17 年前

    也就是说,我同意其他人的观点,即应该将该方法分解为单个责任方法,而不是数百行代码。这也将使它更具可读性,更易于测试。希望您能从这些乱七八糟的代码中得到一些重用。