Стандарт оформления и документирования кода

Используем Proposing a Standards Recommendation

С некоторыми уточнениями: кодестайл.


Пример хорошего кода можно увидеть тут или тут (с другой подсветкой).

PSR-1

1. Обзор

  • Файлы ДОЛЖНЫ использовать только <?php и <?= теги.

  • Файлы ДОЛЖНЫ использовать только UTF-8 без BOM для PHP кода.

  • Файлам СЛЕДУЕТ либо объявлять знаки (классы, функции, константы, и т.д.) или оказывать побочный эффект (например, генерировать вывод, изменять .ini настройки, и т.д.) но НЕ СЛЕДУЕТ делать и то и другое.

  • Пространства имен и классы ДОЛЖНЫ следовать PSR-0.

  • Имена классов ДОЛЖНЫ быть объявлены используя StudlyCaps.

  • Константы класса ДОЛЖНЫ быть объявлены в верхнем регистре с подчеркиванием в качестве разделителей.

  • Имена методов ДОЛЖНЫ быть объявлены используя camelCase.

2. Файлы

2.1. PHP Теги

PHP код ДОЛЖЕН использовать длинные <?php ?> теги или короткие-выводящие <?= ?> теги; другие варианты тегов НЕ ДОЛЖНЫ использоваться.

2.2. Кодировка символов

PHP код ДОЛЖЕН использовать только UTF-8 без BOM.

2.3. Побочные эффекты

Файлу СЛЕДУЕТ объявлять знаки (классы, функции, константы, и т.д.), и не оказывать побочный эффект, или ему СЛЕДУЕТ выполнять логику с побочным эффектом, но НЕ СЛЕДУЕТ делать и то и другое.

Фраза "побочны эффекты" означает выполнение логики непосредственно не связанной с объявлением классов, функций, констант и т.д., просто от включения файла.

"Побочные эффекты" включают, но не ограничены: генерацией вывода, явным использованием require или include, подключением к внешним сервисам, изменениям настроек ini, испусканием ошибок или исключений, изменением глобальных или статичных переменных, чтением или записью в файл, и так далее.

Ниже приведен пример файла с одновременно объявляющий знаки и оказывающий побочные эффекты; т.е., пример того, что следует избегать:

<?php
// побочный эффект: изменение ini настроек
ini_set('error_reporting', E_ALL);

// побочный эффект: загрузка файла
include "file.php";

// побочный эффект: вывод результата
echo "<html>\n";

// описание
function foo()
{
    // тело функции
}

В следующем примере файл который содержит объявление без оказания побочных эффектов; т.е., пример того, к чему следует стремится:

<?php
// объявление
function foo()
{
    // тело функции
}

// условное объявление это *не* побочный эффект
if (! function_exists('bar')) {
    function bar()
    {
        // тело функции
    }
}

3. Пространства имен и Имена Классов

Пространства имен и классы ДОЛЖНЫ следовать PSR-0.

Это означает, что каждый класс находится в собственном файле, и в пространстве имен, по крайней мере, на один уровень: верхний уровень имя поставщика.

Имена классов ДОЛЖНЫ быть объявлены используя StudlyCaps.

Код написанный на PHP 5.3 и старше ДОЛЖЕН использовать формальные пространства имен.

Например:

<?php
// PHP 5.3 и старше:
namespace Vendor\Model;

class Foo
{
}

В коде написанном для 5.2.x и раньше СЛЕДУЕТ использовать псевдо-пространства имен, условные приставки Vendor_ к именам классов.

<?php
// PHP 5.2.x и раньше:
class Vendor_Model_Foo
{
}

4. Константы, Свойства, и Методы Класса

Термин "класс" относится ко всем классам, интерфейсам и трейтам.

4.1. Константы

Константы класса ДОЛЖНЫ быть объявлены в верхнем регистре с подчеркиванием в качестве разделителей. Например:

<?php
namespace Vendor\Model;

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

4.2. Свойства

Это руководство намеренно избегает любых рекомендаций, касающихся использования $StudlyCaps, $camelCase, или $under_score для имен свойств.

Независимо от соглашения именования его СЛЕДУЕТ применять последовательно в разумных пределах. Этот предел может быть на уровне поставщика, на уровне пакета, на уровне класса, или уровне метода.

4.3. Методы

Имена методов ДОЛЖНЫ быть объявлены используя camelCase.

PSR-2

1. Обзор

  • Код ДОЛЖЕН следовать PSR-1.

  • Код ДОЛЖЕН использовать 4 пробела для отступов, не табуляцию.

  • НЕ ДОЛЖНО быть жесткого ограничения на длину строки; мягкое ограничение ДОЛЖНО быть 120 знаков; строкам СЛЕДУЕТ быть 80 символов или менее.

  • ДОЛЖНА быть одна пустая строка после объявления namespace, и ДОЛЖНА быть одна пустая строка после блока с объявлениями use.

  • Открывающие фигурные скобки для классов ДОЛЖНЫ быть на новой строке, и закрывающие фигурные скобки ДОЛЖНЫ быть на новой строке после тела класса.

  • Открывающие фигурные скобки для методов ДОЛЖНЫ быть на новой строке, и закрывающие фигурные скобки ДОЛЖНЫ быть на новой строке после тела метода.

  • Область видимости ДОЛЖНА быть описана у всех свойств и методов; abstract и final ДОЛЖНЫ быть описаны перед областью видимости; static ДОЛЖНО быть описано после области видимости.

  • Ключевые слова управляющих конструкций ДОЛЖНЫ иметь один пробел после себя; вызовы методов и функции НЕ ДОЛЖНЫ.

  • Открывающие фигурные скобки для управляющих конструкций ДОЛЖНЫ быть на той же строке, а закрывающие фигурные скобки ДОЛЖНЫ быть на новой строке после тела конструкции.

  • Открывающие круглые скобки для управляющих конструкций НЕ ДОЛЖНЫ иметь пробел после себя, а закрывающие круглые скобки для управляющих конструкций НЕ ДОЛЖНЫ иметь пробел перед собой.

1.1. Пример

Этот пример как краткий обзор включает в себя некоторые из ниже указанных правил:

<?php
namespace Vendor\Package;

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

class Foo extends Bar implements FooInterface
{
    public function sampleFunction($a, $b = null)
    {
        if ($a === $b) {
            bar();
        } elseif ($a > $b) {
            $foo->bar($arg1);
        } else {
            BazClass::bar($arg2, $arg3);
        }
    }

    final public static function bar()
    {
        // тело метода
    }
}

2. Общее

2.1 Основной стандарт написания кода

Код ДОЛЖЕН следовать всем правилам изложенным в PSR-1.

2.2 Файлы

Все PHP файлы ДОЛЖНЫ использовать переводы строк Unix LF (linefeed).

Все PHP файлы ДОЛЖНЫ оканчиваться одной пустой строкой.

Закрывающий ?> тег ДОЛЖЕН быть исключен из файлов содержащих только PHP.

2.3. Строки

НЕ ДОЛЖНО быть жесткого ограничения на длину строки.

Мягкое ограничение на длину строки ДОЛЖНО быть 120 знаков; автоматические проверки стиля ДОЛЖНЫ предупредить но НЕ ДОЛЖНЫ выдавать ошибку на мягкие ограничения.

Строкам НЕ СЛЕДУЕТ быть длиннее 80 знаков; более длинные строки СЛЕДУЕТ разбивать на несколько последующих строк не более чем 80 знаков в каждой.

НЕ ДОЛЖНО быть замыкающий пробелов в конце строки на не пустых строках.

Пустые строки МОГУТ быть добавлены для улучшения читабельности и указания связанных блоков кода.

НЕ ДОЛЖНО быть более одного оператора в строке.

2.4. Отступы

Код ДОЛЖЕН использовать отступ в 4 пробела, и НЕ ДОЛЖЕН использовать табуляцию для отступов.

Обратите особое внимание: Использование только пробелов, и не смешивание пробелов и табуляции, помогает избежать проблем с диффами, патчами, историей, и аннотациями. Использование пробелов также позволяет легко вставить тонко-настроенный суб-отступ для межстрочного выравнивания.

2.5. Ключевые слова и True/False/Null

PHP Ключевые слова ДОЛЖНЫ быть в нижнем регистре.

PHP константы true, false, и null ДОЛЖНЫ быть в нижнем регистре.

3. Объявление Пространства имен и Use

Если они присутствуют, то ДОЛЖНА быть одна пустая строка после объявления namespace.

Если они присутствуют, все объявления use ДОЛЖНЫ идти после объявления namespace.

ДОЛЖНО быть ключевое слово use на каждое объявление.

ДОЛЖНА быть одна пустая строка после блока use.

Например:

<?php
namespace Vendor\Package;

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

// ... дополнительный PHP код ...

4. Классы, Свойства, и Методы

Термин "класс" относится ко всем классам, интерфейсам и трейтам.

4.1. Extends и Implements

Ключевые слова extends и implements ДОЛЖНЫ быть объявлены на той же строке, что и имя класса.

Открывающая фигурная скобка для класса ДОЛЖНА идти на своей собственной строке; закрывающая фигурная скобка для класса ДОЛЖНА идти на следующей строке после тела класса.

<?php
namespace Vendor\Package;

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

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
    // константы, свойства, методы
}

Список implements МОЖЕТ быть разделен на несколько строк, где каждая последующая строка с одним отступом. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и ДОЛЖЕН быть только один интерфейс на строку.

<?php
namespace Vendor\Package;

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

class ClassName extends ParentClass implements
    \ArrayAccess,
    \Countable,
    \Serializable
{
    // константы, свойства, методы
}

4.2. Свойства

Область видимости ДОЛЖНА быть объявлена на все свойства.

Ключевое слово var НЕ ДОЛЖНО быть использовано для объявления свойства.

НЕ ДОЛЖНО быть более одного свойства объявленного на оператор.

Имена свойств НЕ СЛЕДУЕТ делать с подчеркиванием в качестве приставки для обозначения области видимости protected или private.

Объявление свойства выглядит следующим образом.

<?php
namespace Vendor\Package;

class ClassName
{
    public $foo = null;
}

4.3. Методы

Область видимости ДОЛЖНА быть объявлена на все методы.

Имена методов НЕ СЛЕДУЕТ делать с подчеркиванием в качестве приставки для обозначения области видимости protected или private.

Имена методов НЕ ДОЛЖНЫ быть объявлены с пробелом после имени метода. Открывающая фигурная скобка ДОЛЖНА идти на своей собственной строке, а закрывающая фигурная скобка ДОЛЖНА быть на следующей строке после тела метода. НЕ ДОЛЖНО быть пробела после открытия круглой скобки, и НЕ ДОЛЖНО быть пробела перед закрывающей круглой скобкой.

Объявление метода выглядит следующим образом. Обратите внимание на размещение круглых скобок, запятых, пробелов и фигурных скобок:

<?php
namespace Vendor\Package;

class ClassName
{
    public function fooBarBaz($arg1, &$arg2, $arg3 = [])
    {
        // тело метода
    }
}

4.4. Аргументы Метода

В списке аргументов, НЕ ДОЛЖНО быть пробела перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.

Аргументы Метода со значениями по умолчанию должны идти в конце списка аргументов.

<?php
namespace Vendor\Package;

class ClassName
{
    public function foo($arg1, &$arg2, $arg3 = [])
    {
        // тело метода
    }
}

Список аргументов МОЖЕТ быть разделен на несколько строк, где каждая последующая строка с одним отступом. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и ДОЛЖЕН быть только один аргумент на строку.

Когда список аргументов разделен на несколько строк, закрывающая круглая скобка и открывающая фигурная скобка ДОЛЖНЫ быть установлены вместе на их собственную строку с одним пробелом между ними.

<?php
namespace Vendor\Package;

class ClassName
{
    public function aVeryLongMethodName(
        ClassTypeHint $arg1,
        &$arg2,
        array $arg3 = []
    ) {
        // тело метода
    }
}

4.5. abstract, final, и static

Если они присутствуют, то abstract и final ДОЛЖНЫ предшествовать перед объявлением области видимости.

Если присутствует объявление static, то оно ДОЛЖНО идти после объявления области видимости.

<?php
namespace Vendor\Package;

abstract class ClassName
{
    protected static $foo;

    abstract protected function zim();

    final public static function bar()
    {
        // тело метода
    }
}

4.6. Вызовы Метода и Функции

При выполнении вызова метода или функции, НЕ ДОЛЖНО быть пробела между именем метода или функции и открывающей круглой скобкой, НЕ ДОЛЖНО быть пробела после открытия круглой скобки, а также НЕ ДОЛЖНО быть пробела перед закрывающей круглой скобкой. В списке аргументов, НЕ ДОЛЖНО быть пробела перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.

<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

Списки аргументов МОГУТ быть разделены на несколько строк, где каждая последующая строка с одним отступом. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и ДОЛЖЕН быть только один аргумент на строку.

<?php
$foo->bar(
    $longArgument,
    $longerArgument,
    $muchLongerArgument
);

5. Управляющие конструкции

Общие правила стиля для управляющих конструкций следующие:

  • ДОЛЖЕН быть один пробел после ключевого слова управляющей конструкции
  • НЕ ДОЛЖНО быть пробела после открывающих круглых скобок
  • НЕ ДОЛЖНО быть пробела перед закрывающими круглыми скобками
  • ДОЛЖЕН быть один пробел между закрывающей круглой скобкой и открывающей фигурной скобкой
  • Тело конструкции должно быть с одним отступом
  • Закрывающая фигурная скобка ДОЛЖНА быть на следующей строке после тела управляющей конструкции

Тело каждой конструкции ДОЛЖНО быть заключено в фигурные скобки. Это стандартизирует вид конструкций, и уменьшает вероятность внесения ошибок при добавлении новых строк к телу управляющей конструкции.

5.1. if, elseif, else

Оператор if выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок; и что else и elseif находятся на одной линии, как и закрывающая фигурная скобка тела оператора.

<?php
if ($expr1) {
    // тело оператора if
} elseif ($expr2) {
    // тело оператора elseif
} else {
    // тело оператора else;
}

Ключевое слово elseif СЛЕДУЕТ использовать вместо else if так что все управляющие ключевые слова выглядят как единые слова.

5.2. switch, case

Конструкция switch выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок. Оператор case ДОЛЖЕН быть с одним отступом от switch, а ключевое слово break (или другое завершающее ключевое слово) ДОЛЖНО быть с таким же отступом как тело оператора case. ДОЛЖЕН быть комментарий, такой как // no break когда есть преднамеренное падение в не-пустое тело оператора case.

<?php
switch ($expr) {
    case 0:
        echo 'First case, with a break';
        break;
    case 1:
        echo 'Second case, which falls through';
        // no break
    case 2:
    case 3:
    case 4:
        echo 'Third case, return instead of break';
        return;
    default:
        echo 'Default case';
        break;
}

5.3. while, do while

Оператор while выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

<?php
while ($expr) {
    // structure body
}

Кроме того, оператор do while выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

<?php
do {
    // structure body;
} while ($expr);

5.4. for

Оператор for выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

<?php
for ($i = 0; $i < 10; $i++) {
    // тело оператора for
}

5.5. foreach

Оператор foreach выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

<?php
foreach ($iterable as $key => $value) {
    // тело оператора foreach
}

5.6. try, catch

Блок try catch выглядит следующим образом. Обратите внимание на размещение круглых скобок, пробелов и фигурных скобок.

<?php
try {
    // тело оператора try
} catch (FirstExceptionType $e) {
    // тело оператора catch
} catch (OtherExceptionType $e) {
    // тело оператора catch
}

6. Замыкания

Замыкания ДОЛЖНЫ быть объявлены с пробелом после ключевого слова function, и пробелом перед и после ключевого слова use.

Открывающая фигурная скобка ДОЛЖНА идти на той же строке, а закрывающая фигурная скобка ДОЛЖНА идти на следующей строке после тела функции.

НЕ ДОЛЖНО быть пробела после открывающей круглой скобки списка аргументов или списка переменных, и НЕ ДОЛЖНО быть пробела перед закрывающей круглой скобкой списка аргументов или списка переменных.

В списке аргументов и списке переменных НЕ ДОЛЖНО быть пробела перед каждой запятой, и ДОЛЖЕН быть один пробел после каждой запятой.

Аргументы замыкания со значениями по умолчанию должны идти в конце списка аргументов.

Объявление замыкания выглядит следующим образом. Обратите внимание на размещение круглых скобок, запятых, пробелов и фигурных скобок:

<?php
$closureWithArgs = function ($arg1, $arg2) {
    // тело функции
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
    // тело функции
};

Список аргументов и список переменных МОЖЕТ быть разделен на несколько строк, где каждая последующая строка с одним отступом. При этом первый элемент в списке ДОЛЖЕН быть на следующей строке, и ДОЛЖЕН быть только один аргумент или переменная на строку.

Когда конечный список (или аргументов или переменных) разделен на несколько строк, закрывающая круглая скобка и открывающая фигурная скобка ДОЛЖНЫ быть установлены вместе на их собственную строку с одним пробелом между ними.

Ниже приведены примеры замыканий с и без списка аргументов и списка переменных разбитого на несколько строк.

<?php
$longArgs_noVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) {
   // тело функции
};

$noArgs_longVars = function () use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // тело функции
};

$longArgs_longVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // тело функции
};

$longArgs_shortVars = function (
    $longArgument,
    $longerArgument,
    $muchLongerArgument
) use ($var1) {
   // тело функции
};

$shortArgs_longVars = function ($arg) use (
    $longVar1,
    $longerVar2,
    $muchLongerVar3
) {
   // тело функции
};

Обратите внимание, что правила форматирования применяются также когда замыкание используется прямо как аргумент при вызове метода или функции.

<?php
$foo->bar(
    $arg1,
    function ($arg2) use ($var1) {
        // тело функции
    },
    $arg3
);

7. Заключение

Есть много элементов оформления и практик умышленно опущенных в этом руководстве. Они включают, но не ограничиваются:

  • Объявление глобальных переменных и глобальных констант

  • Объявление функций

  • Операторы и присваивания

  • Вписанное выравнивание

  • Комментарии и блоки документации

  • Приставки и окончания имен классов

  • Практический опыт