前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代码整洁之道

代码整洁之道

作者头像
用户8568307
发布2022-04-18 14:31:01
2160
发布2022-04-18 14:31:01
举报
文章被收录于专栏:PHP全栈技术PHP全栈技术

真了

使用有意义且可发音的变量名

Bad:
代码语言:javascript
复制
$ymdstr = $moment->format('y-m-d');
Good:
代码语言:javascript
复制
$currentDate = $moment->format('y-m-d');

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

Bad:
代码语言:javascript
复制
getUserInfo();
getUserData();
getUserRecord();
getUserProfile();
Good:
代码语言:javascript
复制
getUser();

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

Bad:
代码语言:javascript
复制
$result = $serializer->serialize($data, 448);
Good:
代码语言:javascript
复制
$json = $serializer->serialize($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

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

Bad:
代码语言:javascript
复制
class User
{
    // What the heck is 7 for?
    public $access = 7;
}

// What the heck is 4 for?
if ($user->access & 4) {
    // ...
}

// What's going on here?
$user->access ^= 2;
Good:
代码语言:javascript
复制
class User
{
    public const ACCESS_READ = 1;

    public const ACCESS_CREATE = 2;

    public const ACCESS_UPDATE = 4;

    public const ACCESS_DELETE = 8;

    // User as default can read, create and update something
    public $access = self::ACCESS_READ | self::ACCESS_CREATE | self::ACCESS_UPDATE;
}

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

// Deny access rights to create something
$user->access ^= User::ACCESS_CREATE;

避免嵌套太深,尽早返回

Bad:
代码语言:javascript
复制
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;
            }
            return false;
        }
        return false;
    }
    return false;
}
Good:
代码语言:javascript
复制
function isShopOpen(string $day): bool
{
    if (empty($day)) {
        return false;
    }

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

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

不要添加不必要的上下文

Bad:
代码语言:javascript
复制
class Car
{
    public $carMake;

    public $carModel;

    public $carColor;

    //...
}
Good:
代码语言:javascript
复制
class Car
{
    public $make;

    public $model;

    public $color;

    //...
}

函数参数(理想情况下为2个或更少)

#限制函数参数的数量是非常重要的,因为它使测试函数更容易。有三个以上的参数会导致组合爆炸,你必须用每个单独的参数测试大量不同的情况。
#零参数是理想的情况。一个或两个参数是可以的,应该避免三个参数。除此之外的任何东西都应该得到巩固。通常,如果您有两个以上的参数,那么您的函数尝试做的太多了。在没有的情况下,大多数情况下,更高级别的对象作为参数就足够了。
Bad:
代码语言:javascript
复制
class Questionnaire
{
    public function __construct(
        string $firstname,
        string $lastname,
        string $patronymic,
        string $region,
        string $district,
        string $city,
        string $phone,
        string $email
    ) {
        // ...
    }
}
Good:
代码语言:javascript
复制
class Name
{
    private $firstname;

    private $lastname;

    private $patronymic;

    public function __construct(string $firstname, string $lastname, string $patronymic)
    {
        $this->firstname = $firstname;
        $this->lastname = $lastname;
        $this->patronymic = $patronymic;
    }

    // getters ...
}

class City
{
    private $region;

    private $district;

    private $city;

    public function __construct(string $region, string $district, string $city)
    {
        $this->region = $region;
        $this->district = $district;
        $this->city = $city;
    }

    // getters ...
}

class Contact
{
    private $phone;

    private $email;

    public function __construct(string $phone, string $email)
    {
        $this->phone = $phone;
        $this->email = $email;
    }

    // getters ...
}

class Questionnaire
{
    public function __construct(Name $name, City $city, Contact $contact)
    {
        // ...
    }
}

函数名应该说明它们的作用

Bad:
代码语言:javascript
复制
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();
Good:
代码语言:javascript
复制
class Email
{
    //...

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

$message = new Email(...);
// Clear and obvious
$message->send();

不要将标志用作函数参数

#函数应该做一件事。如果函数遵循基于布尔值的不同代码路径,则将其拆分。
Bad:
代码语言:javascript
复制
function createFile(string $name, bool $temp = false): void
{
    if ($temp) {
        touch('./temp/' . $name);
    } else {
        touch($name);
    }
}
Good:
代码语言:javascript
复制
function createFile(string $name): void
{
    touch($name);
}

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

封装条件句

Bad:
代码语言:javascript
复制
if ($article->state === 'published') {
    // ...
}
Good:
代码语言:javascript
复制
if ($article->isPublished()) {
    // ...
}

避免使用否定条件

Bad:
代码语言:javascript
复制
function isDOMNodeNotPresent(DOMNode $node): bool
{
    // ...
}

if (! isDOMNodeNotPresent($node)) {
    // ...
}
Good:
代码语言:javascript
复制
function isDOMNodePresent(DOMNode $node): bool
{
    // ...
}

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

避免条件句

Bad:
代码语言:javascript
复制
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();
        }
    }
}
Good:
代码语言:javascript
复制
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();
    }
}
多态:一个类,被多个子类继承,如果这个类的某个方法,在多个子类中,表现出不同的功能,我们称这种行为为多态(同一个类的不同子类表现出不同的形态)

反正我是从没这样改过…

避免类型检查(第1部分)

Bad:
代码语言:javascript
复制
function travelToTexas($vehicle): void
{
    if ($vehicle instanceof Bicycle) {
        $vehicle->pedalTo(new Location('texas'));
    } elseif ($vehicle instanceof Car) {
        $vehicle->driveTo(new Location('texas'));
    }
}
Good:
代码语言:javascript
复制
function travelToTexas(Vehicle $vehicle): void
{
    $vehicle->travelTo(new Location('texas'));
}
Bad:
代码语言:javascript
复制
function combine($val1, $val2): int
{
    if (! is_numeric($val1) || ! is_numeric($val2)) {
        throw new Exception('Must be of type Number');
    }

    return $val1 + $val2;
}
Good:
代码语言:javascript
复制
function combine(int $val1, int $val2): int
{
    return $val1 + $val2;
}

删除死代码

没用代码就删掉,如果需要可以去版本记录里面找
Bad:
代码语言:javascript
复制
function oldRequestModule(string $url): void
{
    // ...
}

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

$request = newRequestModule($requestUrl);
inventoryTracker('apples', $request, 'www.inventory-awesome.io');
Good:
代码语言:javascript
复制
function requestModule(string $url): void
{
    // ...
}

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

使用对象封装

当您想在获取对象属性之外做更多的事情时,您不必查找和更改代码库中的每个访问器。
使执行集合时添加验证变得简单。
获取和设置时,易于添加日志记录和错误处理。
继承此类后,可以覆盖默认功能。
您可以延迟加载对象的属性,比如说从服务器获取它。(不是很明白- -)
Bad:
代码语言:javascript
复制
class BankAccount
{
    public $balance = 1000;
}

$bankAccount = new BankAccount();

// Buy shoes...
$bankAccount->balance -= 100;
Good:
代码语言:javascript
复制
class BankAccount
{
    private $balance;

    public function __construct(int $balance = 1000)
    {
      $this->balance = $balance;
    }

    public function withdraw(int $amount): void
    {
        if ($amount > $this->balance) {
            throw new \Exception('Amount greater than available balance.');
        }

        $this->balance -= $amount;
    }

    public function deposit(int $amount): void
    {
        $this->balance += $amount;
    }

    public function getBalance(): int
    {
        return $this->balance;
    }
}

$bankAccount = new BankAccount();

// Buy shoes...
$bankAccount->withdraw($shoesPrice);

// Get balance
$balance = $bankAccount->getBalance();

使对象具有私有/受保护的成员

公共方法和属性对于更改来说是最危险的,因为一些外部代码可能很容易依赖它们,而您无法控制代码依赖它们的内容。类中的修改对类的所有用户都是危险的。
受保护修饰符和公共修饰符一样危险,因为它们在任何子类的范围内都可用。这实际上意味着public和protected之间的区别仅在于访问机制,而封装保证保持不变。类中的修改对所有子类都是危险的。
私有修饰符保证只在单个类的边界中修改代码是危险的(修改是安全的,不会产生Jenga效应)。
Bad:
代码语言:javascript
复制
class Employee
{
    public $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }
}

$employee = new Employee('John Doe');
// Employee name: John Doe
echo 'Employee name: ' . $employee->name;
Good:
代码语言:javascript
复制
class Employee
{
    private $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }
}

$employee = new Employee('John Doe');
// Employee name: John Doe
echo 'Employee name: ' . $employee->getName();

喜欢组合而不是继承

Bad:
代码语言:javascript
复制
class Employee
{
    private $name;

    private $email;

    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }

    // ...
}

// Bad because Employees "have" tax data.
// EmployeeTaxData is not a type of Employee

class EmployeeTaxData extends Employee
{
    private $ssn;

    private $salary;

    public function __construct(string $name, string $email, string $ssn, string $salary)
    {
        parent::__construct($name, $email);

        $this->ssn = $ssn;
        $this->salary = $salary;
    }

    // ...
}
Good:
代码语言:javascript
复制
class EmployeeTaxData
{
    private $ssn;

    private $salary;

    public function __construct(string $ssn, string $salary)
    {
        $this->ssn = $ssn;
        $this->salary = $salary;
    }

    // ...
}

class Employee
{
    private $name;

    private $email;

    private $taxData;

    public function __construct(string $name, string $email)
    {
        $this->name = $name;
        $this->email = $email;
    }

    public function setTaxData(EmployeeTaxData $taxData): void
    {
        $this->taxData = $taxData;
    }

    // ...
}

避免流水似的界面

Bad:
代码语言:javascript
复制
class Car
{
    private $make = 'Honda';

    private $model = 'Accord';

    private $color = 'white';

    public function setMake(string $make): self
    {
        $this->make = $make;

        // NOTE: Returning this for chaining
        return $this;
    }

    public function setModel(string $model): self
    {
        $this->model = $model;

        // NOTE: Returning this for chaining
        return $this;
    }

    public function setColor(string $color): self
    {
        $this->color = $color;

        // NOTE: Returning this for chaining
        return $this;
    }

    public function dump(): void
    {
        var_dump($this->make, $this->model, $this->color);
    }
}

$car = (new Car())
    ->setColor('pink')
    ->setMake('Ford')
    ->setModel('F-150')
    ->dump();
Good:
代码语言:javascript
复制
class Car
{
    private $make = 'Honda';

    private $model = 'Accord';

    private $color = 'white';

    public function setMake(string $make): void
    {
        $this->make = $make;
    }

    public function setModel(string $model): void
    {
        $this->model = $model;
    }

    public function setColor(string $color): void
    {
        $this->color = $color;
    }

    public function dump(): void
    {
        var_dump($this->make, $this->model, $this->color);
    }
}

$car = new Car();
$car->setColor('pink');
$car->setMake('Ford');
$car->setModel('F-150');
$car->dump();

开/闭原理(OCP)

Bad:
代码语言:javascript
复制
abstract class Adapter
{
    protected $name;

    public function getName(): string
    {
        return $this->name;
    }
}

class AjaxAdapter extends Adapter
{
    public function __construct()
    {
        parent::__construct();

        $this->name = 'ajaxAdapter';
    }
}

class NodeAdapter extends Adapter
{
    public function __construct()
    {
        parent::__construct();

        $this->name = 'nodeAdapter';
    }
}

class HttpRequester
{
    private $adapter;

    public function __construct(Adapter $adapter)
    {
        $this->adapter = $adapter;
    }

    public function fetch(string $url): Promise
    {
        $adapterName = $this->adapter->getName();

        if ($adapterName === 'ajaxAdapter') {
            return $this->makeAjaxCall($url);
        } elseif ($adapterName === 'httpNodeAdapter') {
            return $this->makeHttpCall($url);
        }
    }

    private function makeAjaxCall(string $url): Promise
    {
        // request and return promise
    }

    private function makeHttpCall(string $url): Promise
    {
        // request and return promise
    }
}
Good:
代码语言:javascript
复制
interface Adapter
{
    public function request(string $url): Promise;
}

class AjaxAdapter implements Adapter
{
    public function request(string $url): Promise
    {
        // request and return promise
    }
}

class NodeAdapter implements Adapter
{
    public function request(string $url): Promise
    {
        // request and return promise
    }
}

class HttpRequester
{
    private $adapter;

    public function __construct(Adapter $adapter)
    {
        $this->adapter = $adapter;
    }

    public function fetch(string $url): Promise
    {
        return $this->adapter->request($url);
    }
}

利斯科夫替换原理(LSP)

Bad:
代码语言:javascript
复制
class Rectangle
{
    protected $width = 0;

    protected $height = 0;

    public function setWidth(int $width): void
    {
        $this->width = $width;
    }

    public function setHeight(int $height): void
    {
        $this->height = $height;
    }

    public function getArea(): int
    {
        return $this->width * $this->height;
    }
}

class Square extends Rectangle
{
    public function setWidth(int $width): void
    {
        $this->width = $this->height = $width;
    }

    public function setHeight(int $height): void
    {
        $this->width = $this->height = $height;
    }
}

function printArea(Rectangle $rectangle): void
{
    $rectangle->setWidth(4);
    $rectangle->setHeight(5);

    // BAD: Will return 25 for Square. Should be 20.
    echo sprintf('%s has area %d.', get_class($rectangle), $rectangle->getArea()) . PHP_EOL;
}

$rectangles = [new Rectangle(), new Square()];

foreach ($rectangles as $rectangle) {
    printArea($rectangle);
}
Good:
代码语言:javascript
复制
interface Shape
{
    public function getArea(): int;
}

class Rectangle implements Shape
{
    private $width = 0;
    private $height = 0;

    public function __construct(int $width, int $height)
    {
        $this->width = $width;
        $this->height = $height;
    }

    public function getArea(): int
    {
        return $this->width * $this->height;
    }
}

class Square implements Shape
{
    private $length = 0;

    public function __construct(int $length)
    {
        $this->length = $length;
    }

    public function getArea(): int
    {
        return $this->length ** 2;
    }
}

function printArea(Shape $shape): void
{
    echo sprintf('%s has area %d.', get_class($shape), $shape->getArea()).PHP_EOL;
}

$shapes = [new Rectangle(4, 5), new Square(5)];

foreach ($shapes as $shape) {
    printArea($shape);
}

接口隔离原则(ISP)

ISP声明“不应强迫客户依赖他们不使用的接口。”
Bad:
代码语言:javascript
复制
interface Employee
{
    public function work(): void;

    public function eat(): void;
}

class HumanEmployee implements Employee
{
    public function work(): void
    {
        // ....working
    }

    public function eat(): void
    {
        // ...... eating in lunch break
    }
}

class RobotEmployee implements Employee
{
    public function work(): void
    {
        //.... working much more
    }

    public function eat(): void
    {
        //.... robot can't eat, but it must implement this method
    }
}
Good:
代码语言:javascript
复制
interface Workable
{
    public function work(): void;
}

interface Feedable
{
    public function eat(): void;
}

interface Employee extends Feedable, Workable
{
}

class HumanEmployee implements Employee
{
    public function work(): void
    {
        // ....working
    }

    public function eat(): void
    {
        //.... eating in lunch break
    }
}

// robot can only work
class RobotEmployee implements Workable
{
    public function work(): void
    {
        // ....working
    }
}

依赖倒置原理(DIP)

这一原则规定了两个基本事项:

高级模块不应依赖于低级模块。两者都应该依赖于抽象。
抽象不应该依赖于细节。细节应该取决于抽象。
Bad:
代码语言:javascript
复制
class Employee
{
    public function work(): void
    {
        // ....working
    }
}

class Robot extends Employee
{
    public function work(): void
    {
        //.... working much more
    }
}

class Manager
{
    private $employee;

    public function __construct(Employee $employee)
    {
        $this->employee = $employee;
    }

    public function manage(): void
    {
        $this->employee->work();
    }
}
Good:
代码语言:javascript
复制
interface Employee
{
    public function work(): void;
}

class Human implements Employee
{
    public function work(): void
    {
        // ....working
    }
}

class Robot implements Employee
{
    public function work(): void
    {
        //.... working much more
    }
}

class Manager
{
    private $employee;

    public function __construct(Employee $employee)
    {
        $this->employee = $employee;
    }

    public function manage(): void
    {
        $this->employee->work();
    }
}

不要重复你自己

Bad:
代码语言:javascript
复制
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);
    }
}
Good:
代码语言:javascript
复制
function showList(array $employees): void
{
    foreach ($employees as $employee) {
        $expectedSalary = $employee->calculateExpectedSalary();
        $experience = $employee->getExperience();
        $githubLink = $employee->getGithubLink();
        $data = [$expectedSalary, $experience, $githubLink];

        render($data);
    }
}
Very good:
最好使用紧凑版本的代码。
代码语言:javascript
复制
function showList(array $employees): void
{
    foreach ($employees as $employee) {
        render([$employee->calculateExpectedSalary(), $employee->getExperience(), $employee->getGithubLink()]);
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PHP全栈技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用有意义且可发音的变量名
    • Bad:
      • Good:
      • 对同一类型的变量使用相同的词汇表
        • Bad:
          • Good:
          • 使用可搜索的名称(第一部分)
            • Bad:
              • Good:
              • 使用可搜索的名称(第二部分)
                • Bad:
                  • Good:
                  • 避免嵌套太深,尽早返回
                    • Good:
                    • 不要添加不必要的上下文
                      • Bad:
                        • Good:
                        • 函数参数(理想情况下为2个或更少)
                          • Bad:
                            • Good:
                            • 函数名应该说明它们的作用
                              • Bad:
                                • Good:
                                • 不要将标志用作函数参数
                                  • Bad:
                                    • Good:
                                    • 封装条件句
                                      • Bad:
                                        • Good:
                                        • 避免使用否定条件
                                          • Bad:
                                            • Good:
                                            • 避免条件句
                                              • Bad:
                                                • Good:
                                                • 避免类型检查(第1部分)
                                                • 删除死代码
                                                • 使用对象封装
                                                • 使对象具有私有/受保护的成员
                                                • 喜欢组合而不是继承
                                                • 避免流水似的界面
                                                • 开/闭原理(OCP)
                                                • 利斯科夫替换原理(LSP)
                                                • 接口隔离原则(ISP)
                                                • 依赖倒置原理(DIP)
                                                • 这一原则规定了两个基本事项:
                                                  • 不要重复你自己
                                                  领券
                                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档