玩转 PhpStorm 系列(六):通过代码重构提高代码复用性

在 PhpStorm 中,我们可以通过自带的重构功能(Refactor)非常方便地对代码进行重构,从而提升代码复用性。

重构变量/属性

我们以下面这段代码为例进行演示:

<?php
$n1 = pow(100, 2); // 10000
$n2 = sqrt(100);   // 10
$n3 = decbin(100);  // 转化为二进制
$n4 = mt_rand(0, 100);  // 生成0-100之间的随机数

比如我们想要将上述代码中的数字 100 重构为通过变量引入,可以选中要重构的代码,通过快捷键 Ctrl + T 快速打开代码重构操作界面(也可以通过右键 -> Refactor 弹出,Windows 下对应的快捷键是 Ctrl + Alt + Shift + T):

-w661 选择引入变量(序号3对应的操作),并且应用到所有数字 100 出现的地方(只应用到当前位置,选择只替换当前位置选项即可):

-w654 这样,引入变量替换内联数字的重构就完成了:

-w737

注意到现在 number 外面有个红框,意思是你如果想要将其命名为其他变量名,可以现在进行编辑,这个修改会批量应用到其他位置:

-w711 如果你想要切换会之前的内联数字(Inline),可以在代码重构界面选择 Inline 选项切换回去(当然,也可以通过 Option + Command + N 快捷键跳过这个选择界面直接操作):

-w665

-w531

-w648

同样的操作也可以应用到将内联变量值(即以字面量形式直接引入的变量值,比如上面的数字 100,或者字符串、布尔类型字面量,比如 "学院君"true 等)重构为常量、类属性,操作流程完全一样,这里就不重复展示了。

重构函数/方法

除了重构变量、属性、常量外,还可以将某个代码块重构为一个函数/方法来提高复用性。

重构函数

还是以上面的示例代码为例,选中整段代码,通过 Ctrl + T 快捷键弹出代码重构菜单:

-w751 选择 Extract Method... 选项,即可进入重构方法流程(你也可以通过 Option + Command + M 快捷键直接进入),但是此时会报错:

-w681 这是因为上面的代码都是赋值语句,没有任何表达式,我们修改示例代码如下:

<?php
$num = 100;
$n1 = pow($num, 2); // 10000
$n2 = sqrt($num);   // 10
$n3 = decbin($num);  // 转化为二进制
$n4 = mt_rand(0, $num);  // 生成0-100之间的随机数
printf("pow(%d, 2) = %d\nsqrt(%d)=%d\ndecbin(%d)=%d\nmt_rand(0, %d)=%d\n", 
    $num, $n1, $num, $n2, $num, $n3, $num, $n4);

这一次,通过快捷键 Option + Command + M 即可直接进入方法重构导航界面,不要选中第一行代码,这样,系统会将 $num 变量作为参数传入,我们设置函数名为 math_func_test

-w990

点击「Refactor」按钮,就可以看到重构后的代码了:

-w802 是不是很方便?这样一来,我们就可以传入不同的数字多次调用这个函数了,而不必反复编写重复的代码。

重构类方法

同理,我们也可以在类中通过这种机制来重构类成员方法。

以下面这段示例代码为例:

class LynkCo01 extends Car
{
    public function __construct()
    {
        $this->brand = '领克01';
        parent::__construct($this->brand);
    }

    public function drive()
    {
        echo "启动{$this->brand}汽车" . PHP_EOL;
    }
}

我们可以为 brand 属性重构出 Getters/Setters 方法(当然,你可以通过 Generate 功能快速生成,不过这里我们以代码重构的形式进行演示)。

首先通过重构变量的方式将内联变量 '领克01' 重构为 $brand 变量:

public function __construct()
{
    $brand = '领克01';
    $this->brand = $brand;
    parent::__construct($this->brand);
}

然后选中要重构的代码进行方法重构操作,重构类成员方法的界面和重构函数的界面略有不同,这里多了方法可见性设置:

-w871

同理,你可以对 drive 方法中获取 brand 属性的操作进行重构:

-w817

最后,呈现的重构后代码如下所示:

class LynkCo01 extends Car
{
    public function __construct()
    {
        $this->setBrand('领克01');
        parent::__construct($this->brand);
    }

    public function drive()
    {
        echo "启动{$this->getBrand()}汽车" . PHP_EOL;
    }

    /**
     * @param string $brand
     */
    public function setBrand(string $brand): void
    {
        $this->brand = $brand;
    }

    /**
     * @return mixed
     */
    public function getBrand()
    {
        return $this->brand;
    }
}

在父子类之间转移方法

你可以通过代码重构菜单中的「Pull Members Up...」选项将子类方法上移到父类中:

-w735

选择要上移的方法:

-w526

点击「Refactor」按钮,就可以将子类方法上移到父类中:

abstract class Car
{
    protected $brand;

    /**
     * Car constructor.
     * @param $brand
     */
    public function __construct($brand)
    {
        $this->setBrand($brand);
    }

    abstract public function drive();

    /**
     * @param string $brand
     */
    public function setBrand(string $brand): void
    {
        $this->brand = $brand;
    }

    /**
     * @return mixed
     */
    public function getBrand()
    {
        return $this->brand;
    }
}

该重构支持逆操作,你还可以将指定方法从父类下沉到子类中去:

-w659

-w831

重构接口

除此之外,我们还可以将一组实现类似功能的类方法抽象出来构建一个接口,比如汽车、轮船、飞机、摩托车都属于交通工具,交通工具有一些共性,比如可以驾驶、具备品牌属性。

我们以上面的抽象类 Car 为例,将其中 drivesetBrandgetBrand 方法抽象出来构建一个 Transportation 接口,要完成这个重构,需要选中对应的类名,通过 Ctrl + T 弹出重构菜单,选择「Extract Interface...」:

-w671

然后在弹出窗口中编写接口名,选择要声明的接口方法:

-w609

点击「Refactor」按钮即可创建对应的接口文件,并且在接口文件中生成对应的接口代码:

-w926

这个时候,回到定义抽象类 Car 的地方,可以看到它已经声明为实现 Transportation 接口:

abstract class Car implements Transportation

其他重构操作

最后,如果你想要将某个类移动/复制到其他地方,或者对其进行重命名、删除,可以通过重构菜单里面的下面几个选项完成:

-w619

这些操作都有对应的快捷键(右侧),重命名和删除都是日常经常用到的操作,对于移动操作,如果移动到的目录命名空间与当前不一致的话,记得进行调整:

-w550

以上就是 PhpStorm 中常用的代码重构功能,合理的代码重构,可以提升代码复用性,而 PhpStorm 为代码重构提供的快捷操作,可以提升我们日常进行代码重构的效率。

(全文完)

本系列教程会录制视频演示并发布到学院君微信视频号,欢迎扫码关注:

学院君视频号

上一篇: 玩转 PhpStorm 系列(五):灵活使用代码模板功能提高编码效率

下一篇: 玩转 PhpStorm 系列(七):一些提高工作效率的小技巧