很多时候,在互联网上的代码或同事的代码中,我看到他们只用一种方法创建一个Object,只在整个应用程序中使用一次。像这样:
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(); }
将代码移动到一个新对象真的更好,然后只是创建一个函数或直接将代码放在那里? 对我来说,函数部分更有意义,似乎更容易读取,然后创建一个几乎没有任何用处的对象,因为它只有一个方法。
答案 0 :(得分:8)
问题不在于它是在函数还是在对象中。
问题是你在一个blob中有数百行。无论是大量的代码是在一个对象的方法中,还是只是一个类似乎或多或少都与我无关,只是作为次要的合成糖。
那几百行都在做什么?这是实现面向对象最佳实践的地方。
如果你的其他开发人员真的认为使用一个对象而不是一个函数会使它更加“面向对象”,但是有几百行函数/方法不被视为代码气味,那么我认为从组织上来说你有一些要做的教育。
答案 1 :(得分:4)
好吧,如果方法中确实存在“加载和加载”代码,那么它应该分解为该类中的几个受保护方法,在这种情况下,使用类范围是合理的。
也许该代码不可重复使用,因为它尚未被多种方法考虑在内。通过将其移动到一个类并将其分解,您可能会发现它可以更好地在其他地方重用。至少它会更加可维护。
答案 2 :(得分:2)
虽然具有数百行代码的函数清楚地表明存在问题(正如其他人已经指出的那样),但将它放在单独的实例类而不是静态函数中具有优势,可以通过重新调整你的例子来利用分数:
// 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
。
如果您只使用静态功能,这些优势都不可用。
我认为,虽然简单的静态函数有它们的位置,但非平凡的方法(因为这显然是通过'数百行'评论)仍然值得拥有自己的实例:
答案 3 :(得分:1)
你真的在这里提出两个问题:
第一部分:如果您希望能够动态切换功能,则可能需要显式对象封装作为无法以这种方式处理函数的语言的变通方法。当然,必须分配一个新对象,将它分配给一个变量,然后当你想做的就是调用一个函数时,从该变量中调用该函数有点愚蠢。
第二部分:理想情况下没有,但没有明确的“载荷”定义,在某些情况下可能是适当的做法。
答案 4 :(得分:0)
是的,加载和加载代码的存在是Code Smell。
答案 5 :(得分:0)
我会说你几乎从不想要一个块或一个带有大量代码的方法 - 无论是否属于它自己的类都没关系。
将它移动到一个对象可能是重构'的第一步 - 所以它可能就这样有意义了。首先将它移到自己的类中,然后将其拆分为几个较小的方法。
答案 6 :(得分:0)
好吧,我会说这取决于代码块与代码调用部分的紧密耦合程度。
如果它是如此紧密耦合,我无法想象它在其他任何地方被使用,我宁愿将它粘贴在调用类的私有方法中。这样,它就不会被系统的其他部分看到,保证它不会被其他人滥用。
另一方面,如果代码块足够通用(电子邮件验证即可能)在系统的其他部分可能很有趣,那么将该部分提取到自己的类中就没有问题,然后考虑到成为一个实用工具类。即使这意味着它将是一个单方法类。
如果您的问题更多的是“如何处理数百行代码”,那么您确实需要进行一些重构。
答案 7 :(得分:0)
一个包含大量代码的方法就像代码味道一样多。我的第一个想法是至少使方法静态。类中没有数据,因此不需要创建对象。
答案 8 :(得分:0)
我想我会重新考虑你提出的问题。我想你想问的问题是我的班级支持singles responsibility principle。无论如何,要将你的类的各个部分分解成可能彼此独立变化的单独的小块(数据访问和解析等)。你能轻松地对你的班级进行单元测试。
如果你能对上述项目说“是”,我不会担心方法与新类,因为这里的重点是你有可读的,可维护的代码。
在我的团队中,如果一个类变长(超过x行数),我们会有红旗,但这只是一种启发式,就好像你的类有2000行代码一样,它可能会被分解并且可能不支持SRP。
答案 9 :(得分:0)
对于可测试性,最好将它分解为使用单独方法的单独类。为单个方法编写单元测试比在代码隐藏文件中使用内联if语句或其他方法更容易。
话虽如此,我同意其他所有人的观点,即该方法应该分解为单一责任方法,而不是数百行代码。这也将使其更易读和更容易测试。并且希望您可以从一大堆代码中包含的一些逻辑中重用一些。