php整洁之道(代码片段)

Codsing-代码演奏者 Codsing-代码演奏者     2022-11-24     720

关键词:

摘录自 Robert C. Martin的Clean Code 书中的软件工程师的原则 ,适用于PHP。 这不是风格指南。 这是一个关于开发可读、可复用并且可重构的PHP软件指南。
并不是这里所有的原则都得遵循,甚至很少的能被普遍接受。 这些虽然只是指导,但是都是Clean Code作者多年总结出来的。
 
Inspired from clean-code-javascript
 
变量
 
使用有意义且可拼写的变量名
Bad:
$ymdstr = $moment->format(y-m-d);
Good:
$currentDate = $moment->format(y-m-d);

 

同种类型的变量使用相同词汇
Bad:
getUserInfo();
getClientData();
getCustomerRecord();
Good:
getUser();

 

使用易检索的名称
我们会读比写要多的代码。通过是命名易搜索,让我们写出可读性和易搜索代码很重要。
Bad:
// What the heck is 86400 for?
addExpireAt(86400);
Good:
// Declare them as capitalized `const` globals.
interface DateGlobal 
  const SECONDS_IN_A_DAY = 86400;

 
addExpireAt(DateGlobal::SECONDS_IN_A_DAY);

 

使用解释型变量
Bad:
$address = One Infinite Loop, Cupertino 95014;
$cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d5)?$/;
preg_match($cityZipCodeRegex, $address, $matches);
saveCityZipCode($matches[1], $matches[2]);
Good:
$address = One Infinite Loop, Cupertino 95014;
$cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d5)?$/;
preg_match($cityZipCodeRegex, $address, $matches);
list(, $city, $zipCode) = $matchers;
saveCityZipCode($city, $zipCode);

 

避免心理映射,明确比隐性好
Bad:
$l = [Austin, New York, San Francisco];
foreach($i=0; $i<count($l); $i++) 
  oStuff();
  doSomeOtherStuff();
  // ...
  // ...
  // ...
  // 等等`$l` 又代表什么?
  dispatch($l);

Good:
$locations = [Austin, New York, San Francisco];
foreach($i=0; $i<count($locations); $i++) 
  $location = $locations[$i];
 
  doStuff();
  doSomeOtherStuff();
  // ...
  // ...
  // ...
  dispatch($location);
);

 

不要添加不必要上下文
如果你的class/object 名能告诉你什么,不要把它重复在你变量名里。
Bad:
$car = [
  carMake  => Honda,
  carModel => Accord,
  carColor => Blue,
];
 
function paintCar(&$car) 
  $car[carColor] = Red;

Good:
$car = [
  make  => Honda,
  model => Accord,
  color => Blue,
];
 
function paintCar(&$car) 
  $car[color] = Red;

 

使用参数默认值代替短路或条件语句。
Bad:
function createMicrobrewery($name = null) 
  $breweryName = $name ?: Hipster Brew Co.;
  // ...

Good:
function createMicrobrewery($breweryName = Hipster Brew Co.) 
  // ...

 

函数
 
函数参数最好少于2个
限制函数参数个数极其重要因为它是你函数测试容易点。有超过3个可选参数参数导致一个爆炸式组合增长,你会有成吨独立参数情形要测试。
无参数是理想情况。1个或2个都可以,最好避免3个。再多旧需要加固了。通常如果你的函数有超过两个参数,说明他多做了一些事。 在参数少的情况里,大多数时候一个高级别对象(数组)作为参数就足够应付。
Bad:
function createMenu($title, $body, $buttonText, $cancellable) 
  // ...

Good:
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) 
  // ...

 

函数应该只做一件事
这是迄今为止软件工程里最重要的一个规则。当函数做超过一件事的时候,他们就难于实现、测试和理解。当你隔离函数只剩一个功能时,他们就容易被重构,然后你的代码读起来就更清晰。如果你光遵循这条规则,你就领先于大多数开发者了。
Bad:
function emailClients($clients) 
  foreach ($clients as $client) 
    $clientRecord = $db->find($client);
    if($clientRecord->isActive()) 
       email($client);
    
  

Good:
function emailClients($clients) 
  $activeClients = activeClients($clients);
  array_walk($activeClients, email);

 
function activeClients($clients) 
  return array_filter($clients, isClientActive);

 
function isClientActive($client) 
  $clientRecord = $db->find($client);
  return $clientRecord->isActive();

 

函数名应当描述他们所做的事
Bad:
function addToDate($date, $month) 
  // ...

 
$date = new \DateTime();
 
// It‘s hard to to tell from the function name what is added
addToDate($date, 1);
Good:
function addMonthToDate($month, $date) 
  // ...

 
$date = new \DateTime();
addMonthToDate(1, $date);

 

函数应当只为一层抽象,当你超过一层抽象时,函数正在做多件事。拆分功能易达到可重用性和易用性。.
Bad:
function parseBetterJSAlternative($code) 
  $regexes = [
    // ...
  ];
 
  $statements = split( , $code);
  $tokens = [];
  foreach($regexes as $regex) 
    foreach($statements as $statement) 
      // ...
    
  
 
  $ast = [];
  foreach($tokens as $token) 
     // lex...
  
 
  foreach($ast as $node) 
   // parse...
  

Good:
function tokenize($code) 
  $regexes = [
    // ...
  ];
 
  $statements = split( , $code);
  $tokens = [];
  foreach($regexes as $regex) 
    foreach($statements as $statement) 
      $tokens[] = /* ... */;
    );
  );
 
  return tokens;

 
function lexer($tokens) 
  $ast = [];
  foreach($tokens as $token) 
    $ast[] = /* ... */;
  );
 
  return ast;

 
function parseBetterJSAlternative($code) 
  $tokens = tokenize($code);
  $ast = lexer($tokens);
  foreach($ast as $node) 
    // parse...
  );

 

删除重复的代码
尽你最大的努力来避免重复的代码。重复代码不好,因为它意味着如果你修改一些逻辑,那就有不止一处地方要同步修改了。
想象一下如果你经营着一家餐厅并跟踪它的库存: 你全部的西红柿、洋葱、大蒜、香料等。如果你保留有多个列表,当你服务一个有着西红柿的菜,那么所有记录都得更新。如果你只有一个列表,那么只需要修改一个地方!
经常你容忍重复代码,因为你有两个或更多有共同部分但是少许差异的东西强制你用两个或更多独立的函数来做相同的事。移除重复代码意味着创造一个处理这组不同事物的一个抽象,只需要一个函数/模块/类。
抽象正确非常重要,这也是为什么你应当遵循SOLID原则(奠定Class基础的原则)。坏的抽象可能比重复代码还要糟,因为要小心。在这个前提下,如果你可以抽象好,那就开始做把!不要重复你自己,否则任何你想改变一件事的时候你都发现在即在更新维护多处。
Bad:
function showDeveloperList($developers) 
  foreach($developers as $developer) 
    $expectedSalary = $developer->calculateExpectedSalary();
    $experience = $developer->getExperience();
    $githubLink = $developer->getGithubLink();
    $data = [
      $expectedSalary,
      $experience,
      $githubLink
    ];
 
    render($data);
  

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

Good:
function showList($employees) 
  foreach($employees as $employe) 
    $expectedSalary = $employe->calculateExpectedSalary();
    $experience = $employe->getExperience();
    $githubLink = $employe->getGithubLink();
    $data = [
      $expectedSalary,
      $experience,
      $githubLink
    ];
 
    render($data);
  

 

通过对象赋值设置默认值
Bad:
$menuConfig = [
  title       => null,
  body        => Bar,
  buttonText  => null,
  cancellable => true,
];
 
function createMenu(&$config) 
  $config[title]       = $config[title] ?: Foo;
  $config[body]        = $config[body] ?: Bar;
  $config[buttonText]  = $config[buttonText] ?: Baz;
  $config[cancellable] = $config[cancellable] ?: true;

 
createMenu($menuConfig);
Good:
$menuConfig = [
  title       => Order,
  // User did not include ‘body‘ key
  buttonText  => Send,
  cancellable => true,
];
 
function createMenu(&$config) 
  $config = array_merge([
    title       => Foo,
    body        => Bar,
    buttonText  => Baz,
    cancellable => true,
  ], $config);
 
  // config now equals: title: "Order", body: "Bar", buttonText: "Send", cancellable: true
  // ...

 
createMenu($menuConfig);

 

不要用标志作为函数的参数,标志告诉你的用户函数做很多事了。函数应当只做一件事。 根据布尔值区别的路径来拆分你的复杂函数。
Bad:
function createFile(name, temp = false) 
  if (temp) 
    touch(./temp/.$name);
   else 
    touch($name);
  

Good:
function createFile($name) 
  touch(name);

 
function createTempFile($name) 
  touch(./temp/.$name);

 

避免副作用
一个函数做了比获取一个值然后返回另外一个值或值们会产生副作用如果。副作用可能是写入一个文件,修改某些全局变量或者偶然的把你全部的钱给了陌生人。
现在,你的确需要在一个程序或者场合里要有副作用,像之前的例子,你也许需要写一个文件。你想要做的是把你做这些的地方集中起来。不要用几个函数和类来写入一个特定的文件。用一个服务来做它,一个只有一个。
重点是避免常见陷阱比如对象间共享无结构的数据,使用可以写入任何的可变数据类型,不集中处理副作用发生的地方。如果你做了这些你就会比大多数程序员快乐。
Bad:
// Global variable referenced by following function.
// If we had another function that used this name, now it‘d be an array and it could break it.
$name = Ryan McDermott;
 
function splitIntoFirstAndLastName() 
  $name = preg_split(/ /, $name);

 
splitIntoFirstAndLastName();
 
var_dump($name); // [‘Ryan‘, ‘McDermott‘];
Good:
$name = Ryan McDermott;
 
function splitIntoFirstAndLastName($name) 
  return preg_split(/ /, $name);

 
$name = Ryan McDermott;
$newName = splitIntoFirstAndLastName(name);
 
var_export($name); // ‘Ryan McDermott‘;
var_export($newName); // [‘Ryan‘, ‘McDermott‘];

 

不要写全局函数
在大多数语言中污染全局变量是一个坏的实践,因为你可能和其他类库冲突并且你api的用户不明白为什么直到他们获得产品的一个异常。让我们看一个例子:如果你想配置一个数组,你可能会写一个全局函数像config(),但是可能和试着做同样事的其他类库冲突。这就是为什么单例设计模式和简单配置会更好的原因。
Bad:
function config() 
  return  [
    foo: bar,
  ]
;
Good:
class Configuration 
  private static $instance;
  private function __construct($configuration) /* */
  public static function getInstance() 
     if(self::$instance === null) 
         self::$instance = new Configuration();
     
     return self::$instance;
 
 public function get($key) /* */
 public function getAll() /* */

 
$singleton = Configuration::getInstance();

 

封装条件语句
Bad:
if ($fsm->state === fetching && is_empty($listNode)) 
  // ...

Good:
function shouldShowSpinner($fsm, $listNode) 
  return $fsm->state === fetching && is_empty(listNode);

 
if (shouldShowSpinner($fsmInstance, $listNodeInstance)) 
  // ...

 

避免消极条件
Bad:
function isDOMNodeNotPresent($node) 
  // ...

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

Good:
function isDOMNodePresent($node) 
  // ...

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

 

避免条件声明
这看起来像一个不可能任务。当人们第一次听到这句话是都会这么说。 "没有一个if声明" 答案是你可以使用多态来达到许多case语句里的任务。第二个问题很常见, “那么为什么我要那么做?” 答案是前面我们学过的一个整洁代码原则:一个函数应当只做一件事。当你有类和函数有很多if声明,你自己知道你的函数做了不止一件事。记住,只做一件事。
Bad:
class Airplane 
  // ...
  public function getCruisingAltitude() 
    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:
class Airplane 
  // ...

 
class Boeing777 extends Airplane 
  // ...
  public function getCruisingAltitude() 
    return $this->getMaxAltitude() - $this->getPassengerCount();
  

 
class AirForceOne extends Airplane 
  // ...
  public function getCruisingAltitude() 
    return $this->getMaxAltitude();
  

 
class Cessna extends Airplane 
  // ...
  public function getCruisingAltitude() 
    return $this->getMaxAltitude() - $this->getFuelExpenditure();
  

 

Avoid 避免类型检查 (part 1)
PHP是弱类型的,这意味着你的函数可以接收任何类型的参数。 有时候你为这自由所痛苦并且在你的函数渐渐尝试类型检查。有很多方法去避免这么做。第一种是考虑API的一致性。
Bad:
function travelToTexas($vehicle) 
  if ($vehicle instanceof Bicycle) 
    $vehicle->peddle($this->currentLocation, new Location(texas));
   else if ($vehicle instanceof Car) 
    $vehicle->drive($this->currentLocation, new Location(texas));
  

Good:
function travelToTexas($vehicle) 
  $vehicle->move($this->currentLocation, new Location(texas));

 

避免类型检查 (part 2)
如果你正使用基本原始值比如字符串、整形和数组,你不能用多态,你仍然感觉需要类型检测,你应当考虑类型声明或者严格模式。 这给你了基于标准PHP语法的静态类型。 手动检查类型的问题是做好了需要好多的废话,好像为了安全就可以不顾损失可读性。保持你的PHP 整洁,写好测试,做好代码回顾。做不到就用PHP严格类型声明和严格模式来确保安全。
Bad:
function combine($val1, $val2) 
  if (is_numeric($val1) && is_numeric(val2)) 
    return val1 + val2;
  
 
  throw new \Exception(Must be of type Number);

Good:
function combine(int $val1, int $val2) 
  return $val1 + $val2;

 

移除僵尸代码
僵尸代码和重复代码一样坏。没有理由保留在你的代码库中。如果从来被调用过,见鬼去!在你的版本库里是如果你仍然需要他的话,因此这么做很安全。
Bad:
function oldRequestModule($url) 
  // ...

 
function newRequestModule($url) 
  // ...

 
$req = new newRequestModule();
inventoryTracker(apples, $req, www.inventory-awesome.io);
Good:
function newRequestModule($url) 
  // ...

 
$req = new newRequestModule();
inventoryTracker(apples, $req, www.inventory-awesome.io);

 

 


php开发-代码整洁之道(代码片段)

CleanCodePHP目录介绍变量使用见字知意的变量名同一个实体要用相同的变量名使用便于搜索的名称(part1)使用便于搜索的名称(part2)使用自解释型变量避免深层嵌套,尽早返回(part1)避免深层嵌套,尽早返回(part2)少用无意义的变量名... 查看详情

php代码整洁之道

介绍RobertC.Martin‘s的软件工程师准则CleanCode同样适用于PHP。它并不是一个编码风格指南,它指导我们用PHP写出具有可读性,可复用性且可分解的代码。并非所有的准则都必须严格遵守,甚至一些已经成为普遍的约定。这仅仅作为... 查看详情

代码整洁之道(代码片段)

有意义的命名1名副其实2避免误导3做有意义的分区废话都是冗余。Variable永远不应出现在变量名中,Table一词永远不应出现在表名中。当缺少明确约定:变量moneyAmout与money没区别,customerInfo与customer没区别,accountData与account没区别... 查看详情

代码整洁之道(代码片段)

有意义的命名1名副其实2避免误导3做有意义的分区废话都是冗余。Variable永远不应出现在变量名中,Table一词永远不应出现在表名中。当缺少明确约定:变量moneyAmout与money没区别,customerInfo与customer没区别,accountData与account没区别... 查看详情

代码整洁之道-对象和数据结构(代码片段)

现在,有一个计算面积的需求,其中一种实现如下:classSquarepublic$side;classGeometrypublicfunctionarea($shape)if($shapeinstanceofSquare)return$shape->side*$shape->side;return0; 有人看了,你这抽象的有问题啊,很明显是面向过程的,如果新加 查看详情

代码整洁之道(代码片段)

文章目录一、有意义的命名1.名副其实2.避免误导3.做有意义的区分一、有意义的命名软件中随处可见命名。我们给变量、函数、参数、类和封包命名、源代码文件命名、目录命名,良好的命名规范使得代码以及工程的维护难... 查看详情

整洁架构之道--三种经典的编程范式(代码片段)

本文是《CleanArchitecture》--整洁架构之道中关于编程范式相关章节的笔记,首发于公众号「Go招聘」这和软件架构的三大关注重点不谋而合:功能性、组件独立性以及数据管理。的方式。回答此问题的同时另外还会搬出这三个词语... 查看详情

读《cleancode代码整洁之道》之感悟(代码片段)

盲目自信,自认为已经敲了几年代码,还看什么整洁之道啊。我那可爱的书架读懂了我的心思,很明事理的保护起来这本小可爱,未曾让它与我牵手最近项目中的bug有点多,改动代码十分吃力,每看一行代码都带一句“这是什么... 查看详情

15个书写javascript代码的整洁之道(实用!)(代码片段)

...且别人能看懂吗?下面的规则可以让你的JavaScript代码更加整洁和清晰.规则1.不要使用随机的字符 查看详情

代码整洁之道(cleancode)读后感(代码片段)

第二次读代码整洁之道(CleanCode)了,在少许开发经验加持下,没有第一次那么晦涩后,整体对本书也有了共鸣,这本书应该作为指导手册,平时可以多翻一翻,说不定会有新的不同感悟,当然... 查看详情

架构整洁之道,看这一篇就够了!(代码片段)

...中就不会迷路,架构思想就是这样的知识。本文是《架构整洁之道》的读书心得,作者将书中内容拆解后再组织,不仅加入了个人的独到见解,而且用一张详细的知识脉络图帮助大家了解整本书的精华。如果你读过这本书,可以... 查看详情

《代码整洁之道》

代码整洁之道代码猴子(CodeMonkey):低水平编码者.童子军规.技艺(craftsmanship):知和行.学写整洁代码,掌握原则和模式,并付出行动.整洁代码代码呈现了需求的细节.这些细节无法被忽略或抽象,必须要严谨,精确,规范和详细.糟糕的代码... 查看详情

代码整洁之道源码分享(代码片段)

最近学习代码整洁之道,在练习的过程一直想找到章节中的源码案例,直接进行练习,无奈没有找到,只能自己耗时耗力的从头开始敲,总觉的讲解代码的书籍,不提供源码是可耻的,哈哈。分享链接为代码整洁之道书中部分章... 查看详情

整洁之道如何写出更整洁的代码(上)

 如何写出更整洁的代码    代码整洁之道不是银弹,不会立竿见影的带来收益。  没有任何犀利的武功招式,只有一些我个人异常推崇的代码整洁之道的内功心法。它不会直接有效的提高你写代码的能力与速度,... 查看详情

typescript代码整洁之道

干净整洁的代码,不但质量更可靠,也为后期升级、维护打下了良好的基础。那么,整洁代码的衡量标准是什么?本文将RobertC.Martin的CleanCode思想融入到TypeScript,一起探讨研究代码整洁之道。 WTFs/Minute 1.命名的艺术计算... 查看详情

代码整洁之道读书笔记

代码整洁之道 前言如何用功 阅读大量代码 找优点和缺点第一章整洁代码不要留到以后,稍后等于永不烂代码影响生产力代码整洁性不但有关效率,还有关生存好代码 C++之父  尽量减少依赖关系,便于维护... 查看详情

代码整洁之道

文章目录代码整洁之道定义变量名字的时候常用的单词有意义的命名怎样写简洁的,别人一眼可以看的懂的方法方法参数越少越好注释格式别给方法返回null值我们该提炼方法中的变量还是不提炼方法中的变量?代码整洁之道定... 查看详情

代码整洁之道pdf下载

网盘下载地址:代码整洁之道PDF下载–易分享电子书PDF资源网 作者:  [美]RobertC·Martin出版社: 人民邮电出版社原作名: CleanCode:AHandbookofAgileSoftwareCraftsmanship译者: 韩磊出版年: 2010-1-1页数: 388定... 查看详情