编写干净的PHP代码

变量

使用见字知意的变量名

坏:

$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);

 

使用自解释型变量

坏:

$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']);

 

避免深层嵌套,尽早返回

坏:

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();
    // ...
    // ...
    // ...
    // 等等, $li 代表什么?
    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;

    //...
}

表达式

使用恒等式

不好(简易对比会将字符串转为整型):

$a = '42';
$b = 42;

if ($a != $b) {
   // 这里始终执行不到
}

对比 $a != $b 返回了 false 但应该返回 true ! 字符串 '42' 跟整数 42 不相等

好(使用恒等判断检查类型和数据):

$a = '42';
$b = 42;

if ($a !== $b) {
}

函数

函数参数(最好少于 2 个)

限制函数参数个数极其重要,超过 3 个可选参数会有很多参数组合要测试。

无参数是理想情况,通常如果你的函数有超过 2 个参数,说明它要处理的事太多了。 如果必须要传入很多数据,建议封装一个高级别对象作为参数。

坏:

function createMenu(string $title, string $body, string $buttonText, bool $cancellable): void
{
    // ...
}

好:

class MenuConfig
{
    public $title;
    public $body;
    public $buttonText;
    public $cancellable = false;
}

$config = new MenuConfig();
$config->title = 'Foo';
$config->body = 'Bar';
$config->buttonText = 'Baz';
$config->cancellable = true;

function createMenu(MenuConfig $config): void
{
    // ...
}

 

函数应该只做一件事

这是迄今为止软件工程里最重要的一个规则。当一个函数做超过一件事的时候,他们就难于实现、测试和理解。当你把一个函数拆分到只剩一个功能时,他们就容易被重构,然后你的代码读起来就更清晰。如果你遵循这条规则,你就领先于大多数开发者了。

坏:

function emailClients(array $clients): void
{
    foreach($clients as $client) {
        $clientRecord = $db->find($client);
        if ($clientRecord->isActive()) {
            email($client);
        }
    }
}

好:

function emailClients(array $clients): void
{
    $activeClients = activeClients($clients);
    array_walk($activeClients, 'email');
}

function activeClients(array $clients): array
{
    return array_filter($clients, 'isClientActive');
}

function isClientActive(int $client): bool
{
    $clientRecord = $db->find($client);
    return $clientRecord->isActive();
}

 

函数名应体现它做了什么事

坏:

class Email
{
    public function handle(): void
    {
        mail($this->to, $this->subject, $this->body);
    }
}

$message = new Email(...);
// 啥?handle 处理一个消息干嘛了?是往一个文件里写吗?
$message->handle();

好:

class Email 
{
    //...

    public function send(): void
    {
        mail($this->to, $this->subject, $this->body);
    }
}

$message = new Email(...);
// 简单明了
$message->send();

 

不要用 flag 作为函数的参数

flag 就是在告诉大家,这个方法里处理很多事。前面刚说过,一个函数应当只做一件事。 把不同 flag 的代码拆分到多个函数里。

坏:

function createFile(string $name, bool $temp = false): void
{
    if ($temp) {
        touch('./temp/'.$name);
    } else {
        touch($name);
    }
}

好:

function createFile(string $name): void
{
    touch($name);
}

function createTempFile(string $name): void
{
    touch('./temp/'.$name);
}

 

封装条件语句

坏:

if ($article->state === 'published') {
    // ...
}

好:

if ($article->isPublished()) {
    // ...
}

 

避免用反义条件判断

坏:

function isDOMNodeNotPresent(\DOMNode $node): bool
{
    // ...
}

if (!isDOMNodeNotPresent($node))
{
    // ...
}

好:

function isDOMNodePresent(\DOMNode $node): bool
{
    // ...
}

if (isDOMNodePresent($node)) {
    // ...
}

 

避免条件判断

这看起来像一个不可能的任务。但是当有很多 if 语句的类和函数时,函数做了不止一件事。

坏:

class Airplane
{
    // ...

    public function getCruisingAltitude(): int
    {
        switch($this->type) {
            case '777':
                return $this->getMaxAltitude() - $this->getPassengerCount();
            case 'Air Force One':
                return $this->getMaxAltitude();
            case 'Cessna':
                return $this->getMaxAltitude() - $this->getFuelExpenditure();
        }
    }
}

好:

interface Airplane
{
    public function getCruisingAltitude(): int;
}

class Boeing777 implements Airplane
{
    public function getCruisingAltitude(): int
    {
        return $this->getMaxAltitude() - $this->getPassengerCount();
    }
}

class AirForceOne implements Airplane
{
    public function getCruisingAltitude(): int
    {
        return $this->getMaxAltitude();
    }
}

class Cessna implements Airplane
{
    public function getCruisingAltitude(): int
    {
        return $this->getMaxAltitude() - $this->getFuelExpenditure();
    }
}

 

移除僵尸代码

僵尸代码和重复代码一样坏。没有理由保留在你的代码库中。如果从来没被调用过,就删掉!因为还在代码版本库里,很安全。

坏:

function oldRequestModule(string $url): void
{
    // ...
}

function newRequestModule(string $url): void
{
    // ...
}

$request = newRequestModule($requestUrl);
inventoryTracker('apples', $request, 'www.inventory-awesome.io');

好:

function requestModule(string $url): void
{
    // ...
}

$request = requestModule($requestUrl);
inventoryTracker('apples', $request, 'www.inventory-awesome.io');

别写重复代码(DRY)

试着去遵循 DRY 原则。

尽你最大的努力去避免复制代码,它是一种非常糟糕的行为,复制代码通常意味着当需要变更一些逻辑时,修改不止一处。

坏:

function showDeveloperList(array $developers): void
{
    foreach($developers as $developer) {
        $expectedSalary = $developer->calculateExpectedSalary();
        $experience = $developer->getExperience();
        $githubLink = $developer->getGithubLink();
        $data = [
            $expectedSalary,
            $experience,
            $githubLink
        ];

        render($data);
    }
}

function showManagerList(array $managers): void
{
    foreach($managers as $manager) {
        $expectedSalary = $manager->calculateExpectedSalary();
        $experience = $manager->getExperience();
        $githubLink = $manager->getGithubLink();
        $data = [
            $expectedSalary,
            $experience,
            $githubLink
        ];

        render($data);
    }
}

好:

function showList(array $employees): void
{
    foreach($employees as $employee) {
        $expectedSalary = $employee->calculateExpectedSalary();
        $experience = $employee->getExperience();
        $githubLink = $employee->getGithubLink();
        $data = [
            $expectedSalary,
            $experience,
            $githubLink
        ];

        render($data);
    }
}

极好(最好让代码紧凑一点):

function showList(array $employees): void
{
    foreach($employees as $employee) {
        render([
            $employee->calculateExpectedSalary(),
            $employee->getExperience(),
            $employee->getGithubLink()
        ]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值