PSR规范

 

为什么统一代码规范

1.提高可读性(isset、is_null、empty、false/true)

2.促进团队协作

3.减少名字冗余,降低维护成本

4.通过名称理解变量、方法含义,少挖坑少踩坑

5.提高程序员的个人能力

为什么选择PSR规范

  1. 规范提出者:FIG是 Framework Interoperability Group(框架可互用性小组)缩写,目的是以最低程度的限制,来统一各个项目的编码规范,避免各家自行发展的风格阻碍了程序设计师开发的困扰。
  2. PSR规范被CodeIgniter,Laravel,Yii, Zend2, CakePHP,Symfony2, AWS SDK等项目遵守,越来越多公司、团队、开发者遵守PSR规则。

PSR规范

  1. PSR-0 (Autoloading Standard) 自动加载标准
  2. ** PSR-1 (Basic Coding Standard) 基础编码标准 **
  3. ** PSR-2 (Coding Style Guide) 编码风格向导 **
  4. PSR-3 (Logger Interface) 日志接口
  5. PSR-4 (Autoloader) 自动加载改进

PSR-0 & PSR-4:类命名与autoloader

  1. 一个完全标准的命名空间(namespace)类(class)的结构是这样的:\<Vendor Name>\(<Namespace>\)*<Class Name>
  2. 每个命名空间(namespace)都必须有一个顶级的空间名(namespace)(“组织名(Vendor Name)“)。
  3. 每个命名空间(namespace)中可以根据需要使用任意数量的子命名空间(sub-namespace)
  4. ~~从文件系统中加载源文件时,空间名(namespace)中的分隔符将被转换为 DIRECTORY_SEPARATOR。~~
  5. ~~类名(class name)中的每个下划线_都将被转换为一个DIRECTORY_SEPARATOR。下划线_空间名(namespace)中没有什么特殊的意义。~~
  6. 完全标准的命名空间(namespace)类(class)从文件系统加载源文件时将会加上.php后缀。
  7. 组织名(vendor name)空间名(namespace)类名(class name)都由大小写字母组合而成。
  8. PSR-4中,在类名中使用下划线没有任何特殊含义。而PSR-0则规定类名中的下划线 _ 会被转化成目录分隔符。

示例:

\Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php

\Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php

\Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php

\Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php


下面是一个怎样利用上述标准来实现自动加载的示例函数。

<?php

function autoload($className)
{
$className = ltrim($className, ‘\’);
$fileName = ”;
$namespace = ”;
if ($lastNsPos = strrpos($className, ‘\’)) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace(‘\’, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= str_replace(‘_’, DIRECTORY_SEPARATOR, $className) . ‘.php’;

  require $fileName;
 }

PSR-1 简单编码规范

  • 源文件必须只使用 &lt;?php&lt;?= 这两种标签。
  • 源文件中php代码的编码格式必须只使用不带字节顺序标记(BOM)UTF-8
  • 一个源文件建议只用来做声明(类(class)函数(function)常量(constant)等)或者只用来做一些引起副作用的操作(例如:输出信息,修改.ini配置等),但不建议同时做这两件事。下面是一个既包含声明又有副作用的示例文件;即应避免的例子:

    <?php
    // 副作用:修改了ini配置
    ini_set(‘error_reporting’, E_ALL);

    // 副作用:载入了文件
    include “file.php”;

    // 副作用:产生了输出
    echo “<html>\n”;

    // 声明
    function foo()
    {
    // 函数体
    }

  • 命名空间(namespace)类(class) 必须遵守PSR-0标准。
  • 类名(class name) 必须使用骆驼式(StudlyCaps)写法 (译者注:驼峰式(cameCase)的一种变种,后文将直接用StudlyCaps表示)。PHP5.3之后的代码必须使用正式的命名空间(namespace)

    <?php
    // PHP 5.3 及之后:
    namespace Vendor\Model;

    class Foo
    {
    }

  • 类(class)中的常量必须只由大写字母和下划线(_)组成。类常量必须只由大写字母和下划线(_)组成。

    <?php
    namespace Vendor\Model;

    class Foo
    {
    const VERSION = ‘1.0’;
    const DATE_APPROVED = ‘2012-06-01’;
    }

  • 方法名(method name) 必须使用驼峰式(cameCase)写法(译者注:后文将直接用camelCase表示)。

PSR-2 编码风格

  • 代码必须遵守 PSR-1。
  • 代码必须使用4个空格来进行缩进,而不是用制表符。
  • 命名空间(namespace)的声明下面必须有一行空行,并且在导入(use)的声明下面也必须有一行空行。示例:

    <?php
    namespace Vendor\Package;

    use FooClass;
    use BarClass as Bar;
    use OtherVendor\OtherPackage\BazClass;

  • 类(class)的左花括号必须放到其声明下面自成一行,右花括号则必须放到类主体下面自成一行。
  • 方法(method)的左花括号必须放到其声明下面自成一行,右花括号则必须放到方法主体的下一行。示例:

    <?php
    namespace Vendor\Package;

    use FooClass;
    use BarClass as Bar;
    use OtherVendor\OtherPackage\BazClass;

    class ClassName extends ParentClass implements \ArrayAccess, \Countable
    {
    // 常量、属性、方法
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
    // 方法主体部分
    }
    }

  • 所有的属性(property)方法(method) 必须有可见性声明;抽象(abstract)终结(final)声明必须在可见性声明之前;而静态(static)声明必须在可见性声明之后。示例:

    <?php
    namespace Vendor\Package;

    abstract class ClassName
    {
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
    // 方法主体部分
    }
    }

  • 在控制结构关键字的后面必须有一个空格;而方法(method)函数(function)的关键字的后面不可有空格。
  • 控制结构的左花括号必须跟其放在同一行,右花括号必须放在该控制结构代码主体的下一行。
  • 控制结构的左括号之后不可有空格,右括号之前也不可有空格。示例:

    <?php

    if ($expr1) {
    // if body
    } elseif ($expr2) {
    // elseif body
    } else {
    // else body;
    }

    foreach ($iterable as $key => $value) {
    // foreach body
    }

PSR-3 LoggerInterface

  • PSR-3主要目标是让类库获得一个Psr\Log\LoggerInterface对象并能通过简单通用的方式来写日志。有自定义需求的框架和CMS可以根据情况扩展这个接口,但推荐保持和该文档的兼容性,以确保应用中使用到的第三方库能将日志集中写到应用日志里。

总结

  • 规范不是义务的,当然你也可以选择自己的方式,但使用规范会让你的合作更轻松。
  • 多读开源代码
  • PSR规范中文翻译

代码重构

 

程序开发做什么

1.开发新功能

2.重构

什么是重构

> 重构(名词):对软件内部结构的一种调整, 目的是在不改变”软件之可察行为”前提下,提高其可理解性,降低其修改成本.
>
> 重构(动词):使用一系列重构准则(手法),在不改变”软件之可察行为”前提下,调整其结构.

  1. 不改变原有功能
  2. 调整程序结构,提高程序维护性

重构目的

  • 让代码易读易理解。(代码是写给人看的, 顺便能在计算机上运行)
  • 改进程序设计,程序模块化,把代码放在合适的位置
  • 找出隐藏BUG及缺陷
  • 提高开发速度
  • 提高程序性能

重构结果

  • 可以更快更好的开发程序
  • 良好的设计
  • 代码清晰易读易理解
  • 稳定健壮的程序
  • 清晰高效的算法
  • 提高对代码的控制能力
  • 代码清晰易读,良好的代码风格
  • 对常见BUG敏感,少出BUG
  • 提高程序的设计能力,学会抽象和模块化

常用基本重构方法

  • 重命名:对类,接口,方法,属性,参数等重命名,使代码更易理解( 统一编码统规范,PSR规范)
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)
  • 图3(图片来自博客园)

  • 抽取代码:
  1. 将复杂的处理过程分解成独立功能的小函数,函数名称解释函数功能(不要复制代码
  2. 将多处出现的代码段抽取封装为一个特定功能的方法,其他方法调用该方法(不要复制代码
  3. 将类的某些属性,方法抽取,组成新的类。原类继承或者使用(不要复制代码
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)

  • 抽取参数:提升方法内的局部变量为方法的参数
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)

  • 删除参数:将方法的一个或多个参数删掉(对象作为参数传递)
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)

  • 方法迁移:将函数放在它应该在的地方,降低耦合性
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)

  • 对象替代数组:值域名称和函数名称清晰表达元素意义。
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)

  • 合并条件语句:考虑合并理由
  • 图1(图片来自博客园)
  • 图2(图片来自博客园)
  • 图3(图片来自博客园)

其他方法

  1. 隐藏属性、方法,控制权限。
  2. 使用多态,替换switch
  3. 避免硬编码

总结

  1. 开发过程中注意抽象、模块化编程。
  2. 不要只为实现功能而写代码,要保证代码质量。代码结构和维护性比实现功能更复杂更重要。