Whip Monstrous Code Into Shape 12-Too Many Method Parameters is a Sign

As a general guideline, when you find yourself wanting to create a method with four or more parameters, that might be an indication that there's a missing class. You may want to refactor. As always, rules are meant to be broken, but, nonetheless, train yourself to be suspicious of such methods.


这个视频讲的是避免方法中有过多的参数。

一般来说,方法中最好保持最多三个参数,方法中有三个以上参数的时候就要考虑是不是应该用一个类来替代。类(class)本质上是一种自定义的类型(type)。创建一个类,就是创建了一种新的类型,具有特定的外观与行为。

参数过多带来的问题显而易见。首先是违背职责单一原则,通常参数过多的很大一个原因就是添加了各种“表示参数”,比如 boolean 的值,或者类似于 $type 的变量。这些参数的加入仿佛在宣告“本函数干的事可不止一件”,随之而来的就是方法中各种的if 判断,这种情况下还不如把不同情况分拆成不同的方法。

另外一个情况参数过多带来的逻辑层级混乱,本来不同层级的逻辑随着参数加入都掺合在一起。

另外参数过多对于测试来说是很大的麻烦,你必须模拟不同参数的组合情况并做相应的测试;在调用的时候也可能出错,参数过多导致调用的时候需要一个一个参数好好对应。

想象一个情景,有一个 compress(打包) 方法,用来给样式文件打包。

function compress($file, $destination)
{
    // todo ...
}

开始只有两个参数,只能针对 css 文件打包。随着项目进展,这个方法被扩展到不仅可以针对css 打包,也可以针对 js 文件打包,所以代码就进化成这个样子:

function compress($file, $fileType, $destination, $compressor)
{
    if ($fileType == 'css') {
        // todo ...
    }
    if ($fileType == 'js') {
        if ($compressor) {
            // todo ...
        } else {
            // todo ...
        }
    }
}

随着参数的增多,这个方法的职责也变多,要判断文件类型,要选择不同的压缩工具,要处理压缩。。。

这个时候就要考虑把有些参数封装到一个类中。compress 的职责就是压缩文件,而文件本身的类型以及对应的压缩工具可以是一种“类型(type)”,也就是可以创建一个对应的类。

interface CompressionStrategy
{
    public function compress();
}

class JavascriptStrategy implements CompressionStrategy
{
    private $file;

    private $destination;

    private $compressor;

    public function __construct($file, $destination)
    {

        $this->file = $file;
        $this->destination = $destination;
    }

    public function compress()
    {
        // TODO: ...
    }
}

class CssStrategy implements CompressionStrategy
{
    private $destination;

    private $file;

    private $compressor;

    public function __construct($file, $destination)
    {

        $this->destination = $destination;
        $this->file = $file;
    }

    public function compress()
    {
        // TODO: ...
    }
}

这个时候 compress 方法就很简单了,层级的逻辑也很清楚,就是调用一个可压缩的文件的压缩方法而已。

function compress(CompressionStrategy $strategy)
{
    $strategy->compress();
    // ....
}

而且通过类型上溯你可以随意的添加更多的类型,只要实现了 CompressionStrategy 接口。

本帖已被设为精华帖!
本帖由 Summer 于 7年前 加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 3
Summer

感谢分享

7年前 评论

@Summer summer哥不睡懒觉,这么早起啊

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!