• PHP 代码简洁之道 ( PHP Clean Code)(第二部分)


    PHP 代码简洁之道 ( PHP Clean Code)(第一部分)

    使用默认参数而不是使用短路运算或者是条件判断

    不好的做法:

    这是不太好的因为 $breweryName 可以是 NULL.

    function createMicrobrewery($breweryName = 'Hipster Brew Co.'): void
    {
        // ...
    }
    

      

    还算可以的做法:

    这个做法比上面的更加容易理解,但是它需要很好的去控制变量的值.

    function createMicrobrewery($name = null): void
    {
        $breweryName = $name ?: 'Hipster Brew Co.';
        // ...
    }
    

      

    好的做法:

    你可以使用 类型提示 而且可以保证 $breweryName 不会为空 NULL.

    function createMicrobrewery(string $breweryName = 'Hipster Brew Co.'): void
    {
        // ...
    }
    }
    

      

     

    对比

     

    使用 相等运算符

    不好的做法:

    $a = '42';
    $b = 42;
    使用简单的相等运算符会把字符串类型转换成数字类型
    
    if( $a != $b ) {
       //这个条件表达式总是会通过
    }
    

      

    表达式 $a != $b 会返回 false 但实际上它应该是 true !
    字符串类型 '42' 是不同于数字类型的 42

    好的做法:
    使用全等运算符会对比类型和值

    if( $a !== $b ) {
        //这个条件是通过的
    }
    

      

    表达式 $a !== $b 会返回 true。

     

    函数

    函数参数(2 个或更少)

    限制函数参数个数极其重要

    这样测试你的函数容易点。有超过 3 个可选参数会导致一个爆炸式组合增长,你会有成吨独立参数情形要测试。

    无参数是理想情况。1 个或 2 个都可以,最好避免 3 个。

    再多就需要加固了。通常如果你的函数有超过两个参数,说明他要处理的事太多了。 如果必须要传入很多数据,建议封装一个高级别对象作为参数。

    不友好的:

    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(...);
    // What is this? A handle for the message? Are we writing to a file now?
    $message->handle()
    

      

    ; 

    很好的例子:

    class Email 
    {
        //...
    
        public function send(): void
        {
            mail($this->to, $this->subject, $this->body);
        }
    }
    
    $message = new Email(...);
    // Clear and obvious
    $message->send();
    

      

    函数只能是一个抽象级别

    当你有多个抽象层次时,你的函数功能通常是做太多了。 分割函数功能使得重用性和测试更加容易。.

    不好:

    function parseBetterJSAlternative(string $code): void
    {
        $regexes = [
            // ...
        ];
    
        $statements = explode(' ', $code);
        $tokens = [];
        foreach ($regexes as $regex) {
            foreach ($statements as $statement) {
                // ...
            }
        }
    
        $ast = [];
        foreach ($tokens as $token) {
            // lex...
        }
    
        foreach ($ast as $node) {
            // parse...
        }
    }
    

      

    同样不是很好:

    我们已经完成了一些功能,但是 parseBetterJSAlternative() 功能仍然非常复杂,测试起来也比较麻烦。

    function tokenize(string $code): array
    {
        $regexes = [
            // ...
        ];
    
        $statements = explode(' ', $code);
        $tokens = [];
        foreach ($regexes as $regex) {
            foreach ($statements as $statement) {
                $tokens[] = /* ... */;
            }
        }
    
        return $tokens;
    }
    
    function lexer(array $tokens): array
    {
        $ast = [];
        foreach ($tokens as $token) {
            $ast[] = /* ... */;
        }
    
        return $ast;
    }
    
    function parseBetterJSAlternative(string $code): void
    {
        $tokens = tokenize($code);
        $ast = lexer($tokens);
        foreach ($ast as $node) {
            // parse...
        }
    }
    

      

    很好的:

    最好的解决方案是取出 parseBetterJSAlternative() 函数的依赖关系.

    class Tokenizer
    {
        public function tokenize(string $code): array
        {
            $regexes = [
                // ...
            ];
    
            $statements = explode(' ', $code);
            $tokens = [];
            foreach ($regexes as $regex) {
                foreach ($statements as $statement) {
                    $tokens[] = /* ... */;
                }
            }
    
            return $tokens;
        }
    }
    
    class Lexer
    {
        public function lexify(array $tokens): array
        {
            $ast = [];
            foreach ($tokens as $token) {
                $ast[] = /* ... */;
            }
    
            return $ast;
        }
    }
    
    class BetterJSAlternative
    {
        private $tokenizer;
        private $lexer;
    
        public function __construct(Tokenizer $tokenizer, Lexer $lexer)
        {
            $this->tokenizer = $tokenizer;
            $this->lexer = $lexer;
        }
    
        public function parse(string $code): void
        {
            $tokens = $this->tokenizer->tokenize($code);
            $ast = $this->lexer->lexify($tokens);
            foreach ($ast as $node) {
                // parse...
            }
        }
    }
    

      

    更多学习内容请访问:

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

  • 相关阅读:
    逻辑卷扩容
    iptables网络防火墙||SNAT,DNAT等转发路由动作
    常用rman操作语句
    常用Oracle的SQL语句
    oracle中的单引号和双竖线||以及q'间隔符
    网站升级HTTPS教程
    站长必备:网站被黑后怎么快速搞定
    常见HTTP错误代码
    在Android中实现一个简易的Http服务器
    Android开发新手常见的10个误区
  • 原文地址:https://www.cnblogs.com/a609251438/p/12582672.html
Copyright © 2020-2023  润新知