介绍

robert c.martin’s 的 软件工程师准则 clean code 同样适用于 php。它并不是一个编码风格指南,它指导我们用 php 写出具有可读性,可复用性且可分解的代码。

并非所有的准则都必须严格遵守,甚至一些已经成为普遍的约定。这仅仅作为指导方针,其中许多都是 clean code 作者们多年来的经验。

尽管许多开发者依旧使用 php 5 版本,但是这篇文章中绝大多数例子都是只能在 php 7.1 + 版本下运行。

变量

 

使用有意义的且可读的变量名

不友好的:

$ymdstr = $moment->format('y-m-d');

  

友好的:

$currentdate = $moment->format('y-m-d');

  

对同类型的变量使用相同的词汇

不友好的:

getuserinfo();
getuserdata();
getuserrecord();
getuserprofile();

  

友好的:

getuser();

  

使用可搜索的名称(第一部分)

我们阅读的代码超过我们写的代码。所以我们写出的代码需要具备可读性、可搜索性,这一点非常重要。要我们去理解程序中没有名字的变量是非常头疼的。让你的变量可搜索吧!

不具备可读性的代码:

//  见鬼的 448 是什么意思?
$result = $serializer->serialize($data, 448);

  

具备可读性的:

$json = $serializer->serialize($data, json_unescaped_slashes | json_pretty_print | json_unescaped_unicode);

  

使用可搜索的名称(第二部分)

不好的:

// 见鬼的 4 又是什么意思?
if ($user->access & 4) {
    // ...
}

  

好的方式:

class user
{
    const access_read = 1;
    const access_create = 2;
    const access_update = 4;
    const access_delete = 8;
}

if ($user->access & user::access_update) {
    // do edit ...
}

  

使用解释性变量

不好:

$address = 'one infinite loop, cupertino 95014';
$cityzipcoderegex = '/^[^,]+,\s*(.+?)\s*(\d{5})$/';
preg_match($cityzipcoderegex, $address, $matches);

savecityzipcode($matches[1], $matches[2]);

  

一般:

这个好点,但我们仍严重依赖正则表达式。

$address = 'one infinite loop, cupertino 95014';
$cityzipcoderegex = '/^[^,]+,\s*(.+?)\s*(\d{5})$/';
preg_match($cityzipcoderegex, $address, $matches);

[, $city, $zipcode] = $matches;
savecityzipcode($city, $zipcode);

  

很棒:

通过命名子模式减少对正则表达式的依赖。

$address = 'one infinite loop, cupertino 95014';
$cityzipcoderegex = '/^[^,]+,\s*(?<city>.+?)\s*(?<zipcode>\d{5})$/';
preg_match($cityzipcoderegex, $address, $matches);

savecityzipcode($matches['city'], $matches['zipcode']);

  

避免嵌套太深和提前返回 (第一部分)

使用太多 if else 表达式会导致代码难以理解。
明确优于隐式。

不好:

function isshopopen($day): bool
{
    if ($day) {
        if (is_string($day)) {
            $day = strtolower($day);
            if ($day === 'friday') {
                return true;
            } elseif ($day === 'saturday') {
                return true;
            } elseif ($day === 'sunday') {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    } else {
        return false;
    }
}

  

很棒:

function isshopopen(string $day): bool
{
    if (empty($day)) {
        return false;
    }

    $openingdays = [
        'friday', 'saturday', 'sunday'
    ];

    return in_array(strtolower($day), $openingdays, true);
}

  

避免嵌套太深和提前返回 (第二部分)

不好:

function fibonacci(int $n)
{
    if ($n < 50) {
        if ($n !== 0) {
            if ($n !== 1) {
                return fibonacci($n - 1) + fibonacci($n - 2);
            } else {
                return 1;
            }
        } else {
            return 0;
        }
    } else {
        return 'not supported';
    }
}

  

很棒:

function fibonacci(int $n): int
{
    if ($n === 0 || $n === 1) {
        return $n;
    }

    if ($n > 50) {
        throw new \exception('not supported');
    }

    return fibonacci($n - 1) + fibonacci($n - 2);
}

  

避免心理映射

不要迫使你的代码阅读者翻译变量的意义。
明确优于隐式。

不好:

$l = ['austin', 'new york', 'san francisco'];

for ($i = 0; $i < count($l); $i++) {
    $li = $l[$i];
    dostuff();
    dosomeotherstuff();
    // ...
    // ...
    // ...
    // wait, what is `$li` for again?
    dispatch($li);
}

  

很棒:

$locations = ['austin', 'new york', 'san francisco'];

foreach ($locations as $location) {
    dostuff();
    dosomeotherstuff();
    // ...
    // ...
    // ...
    dispatch($location);
}

  

不要增加不需要的上下文

如果类名或对象名告诉你某些东西后,请不要在变量名中重复。

小坏坏:

class car
{
    public $carmake;
    public $carmodel;
    public $carcolor;

    //...
}

  

好的方式:

class car
{
    public $make;
    public $model;
    public $color;

    //...
}

  

更多学习内容请访问:

腾讯t3-t4标准精品php架构师教程目录大全,只要你看完保证薪资上升一个台阶(持续更新)