Стандарт кодирования
********************
.[perex]
Этот документ описывает правила и рекомендации для разработки Nette. Внося код в Nette, вы обязаны им следовать. Проще всего добиться этого, подражая существующему коду. Цель в том, чтобы весь код выглядел так, будто его написал один человек.
Стандарт кодирования Nette соответствует [PSR-12 Extended Coding Style |https://www.php-fig.org/psr/psr-12/] с двумя главными исключениями: для отступов он использует [табуляции вместо пробелов |#Табуляции вместо пробелов] и [PascalCase для констант классов|https://blog.nette.org/en/for-less-screaming-in-the-code].
.[tip]
Многие из этих правил умеет автоматически проверять и исправлять инструмент [Nette Coding Standard |tools:coding-standard], так что проверять их вручную вам не придётся.
Общие правила
=============
- Каждый PHP-файл должен содержать `declare(strict_types=1)`
- Для разделения методов ради лучшей читаемости используются две пустые строки
- Причина использования оператора подавления (`@`) должна быть задокументирована: `@mkdir($dir); // @ - directory may exist`
- Если используется оператор нестрогого сравнения (то есть `==`, `!=`, ...), намерение должно быть задокументировано: `// == to accept null`
- Несколько классов исключений можно записать в один файл с именем `exceptions.php`, а несколько перечислений - в `enums.php`
- У интерфейсов видимость методов не указывается, потому что они всегда публичные
- У каждого свойства, возвращаемого значения и параметра должен быть указан тип. И наоборот, у финальных констант тип мы никогда не указываем, потому что он очевиден
- Для ограничения строк следует использовать одинарные кавычки, кроме случаев, когда сам литерал содержит апострофы
Соглашения об именовании
========================
- Избегайте сокращений, если только полное имя не окажется чрезмерным
- Для двухбуквенных сокращений используйте прописные буквы, а для более длинных - PascalCase/camelCase
- Для имени класса используйте существительное или именное словосочетание
- Имена классов должны содержать не только конкретику (`Array`), но и общность (`ArrayIterator`). Исключение - атрибуты PHP
- "Константы классов и перечисления следует писать в PascalCaps":https://blog.nette.org/en/for-less-screaming-in-the-code
- "Интерфейсы и абстрактные классы не должны содержать приставок или суффиксов":https://blog.nette.org/en/prefixes-and-suffixes-do-not-belong-in-interface-names вроде `Abstract`, `Interface` или `I`
Переносы и скобки
=================
Стандарт кодирования Nette соответствует PSR-12 (или PER Coding Style), но в некоторых пунктах уточняет или меняет его:
- Стрелочные функции пишутся без пробела перед скобкой, то есть `fn($a) => $b`
- Пустая строка между разными видами импортов `use` не требуется
- Возвращаемый тип функции или метода и открывающая фигурная скобка всегда находятся на разных строках:
```php
public function find(
string $dir,
array $options,
): array
{
// тело метода
}
```
Открывающая фигурная скобка на отдельной строке важна для визуального отделения сигнатуры функции или метода от тела. Если сигнатура на одной строке, разделение очевидно (изображение слева). Если она на нескольких строках, в PSR сигнатура и тело сливаются (посередине), а в стандарте Nette остаются разделёнными (справа):
[* new-line-after.webp *]
Блоки документации (phpDoc)
===========================
Главное правило: **никогда не дублируйте** сведения из сигнатуры, такие как тип параметра или возвращаемый тип, если это не добавляет ценности.
Блок документации к определению класса:
- Начинается с описания класса
- Дальше пустая строка
- Дальше аннотации `@property` (или `@property-read`, `@property-write`), по одной на строку. Синтаксис: аннотация, пробел, тип, пробел, `$имя`
- Дальше аннотации `@method`, по одной на строку. Синтаксис: аннотация, пробел, возвращаемый тип, пробел, `имя(тип $параметр, ...)`
- Аннотация `@author` опускается. Авторство хранится в истории исходного кода
- Можно использовать аннотации `@internal` или `@deprecated`
```php
/**
* MIME message part.
*
* @property string $encoding
* @property-read array $headers
* @method string getSomething(string $name)
* @method static bool isEnabled()
*/
```
Блок документации к свойству, содержащий только аннотацию `@var`, должен быть на одной строке:
```php
/** @var string[] */
private array $name;
```
Блок документации к определению метода:
- Начинается с краткого описания метода
- Без пустой строки
- Аннотации `@param`, по одной на строку
- Аннотация `@return`
- Аннотации `@throws`, по одной на строку
- Можно использовать аннотации `@internal` или `@deprecated`
За каждой аннотацией следует один пробел, кроме `@param`, за которой ради лучшей читаемости следуют два пробела.
```php
/**
* Finds a file in directory.
* @param string[] $options
* @return string[]
* @throws DirectoryNotFoundException
*/
public function find(string $dir, array $options): array
```
Глобальные функции и константы
==============================
Глобальные функции и константы пишутся без ведущего обратного слеша, то есть `count($arr)`, а не `\count($arr)`. Для функций, которые PHP умеет оптимизировать, добавьте в начало файла `use function`, чтобы компилятор мог перевести их эффективнее. К ним относятся функции вроде `count`, `strlen`, `is_array`, `is_string`, `is_scalar`, `sprintf` и т. п. Функции перечисляются на одной строке, чтобы блок импортов оставался компактным:
```php
use Nette;
use function count, is_array, is_scalar, sprintf;
```
Изредка мы импортируем и константы, знание значения которых может помочь компилятору:
```php
use const PHP_OS_FAMILY;
```
Табуляции вместо пробелов
=========================
У табуляций есть несколько преимуществ перед пробелами:
- Размер отступа настраивается в редакторах и в "вебе":https://developer.mozilla.org/en-US/docs/Web/CSS/tab-size
- Они не навязывают коду предпочтения автора по размеру отступа, благодаря чему код становится переносимее
- Их можно ввести одним нажатием клавиши (где угодно, а не только в редакторах, которые преобразуют табуляции в пробелы)
- Отступ - их прямое назначение
- Они учитывают нужды слабовидящих и слепых коллег
Используя в наших проектах табуляции, мы даём возможность настроить ширину, что большинству людей может показаться ненужным, но для людей с нарушениями зрения это принципиально важно.
Для слепых программистов, использующих брайлевские дисплеи, каждый пробел означает одну брайлевскую ячейку. Так что если отступ по умолчанию равен 4 пробелам, отступ 3-го уровня тратит 12 ценных брайлевских ячеек ещё до начала кода. На дисплее из 40 ячеек, самом распространённом для ноутбуков, это больше четверти доступных ячеек, потраченных впустую и не несущих никаких сведений.
{{priority: -1}}
Стандарт кодирования
Этот документ описывает правила и рекомендации для
разработки Nette. Внося код в Nette, вы обязаны им следовать. Проще всего
добиться этого, подражая существующему коду. Цель в том, чтобы весь код
выглядел так, будто его написал один человек.
Многие из этих правил умеет автоматически проверять и
исправлять инструмент Nette Coding Standard,
так что проверять их вручную вам не придётся.
Общие правила
Каждый PHP-файл должен содержать declare(strict_types=1)
Для разделения методов ради лучшей читаемости используются две
пустые строки
Причина использования оператора подавления (@) должна быть
задокументирована: @mkdir($dir); // @ - directory may exist
Если используется оператор нестрогого сравнения (то есть ==,
!=, …), намерение должно быть
задокументировано: // == to accept null
Несколько классов исключений можно записать в один файл с именем
exceptions.php, а несколько перечислений – в enums.php
У интерфейсов видимость методов не указывается, потому что они
всегда публичные
У каждого свойства, возвращаемого значения и параметра должен быть
указан тип. И наоборот, у финальных констант тип мы никогда не
указываем, потому что он очевиден
Для ограничения строк следует использовать одинарные кавычки, кроме
случаев, когда сам литерал содержит апострофы
Соглашения об именовании
Избегайте сокращений, если только полное имя не окажется
чрезмерным
Для двухбуквенных сокращений используйте прописные буквы, а для
более длинных – PascalCase/camelCase
Для имени класса используйте существительное или именное
словосочетание
Имена классов должны содержать не только конкретику (Array), но и
общность (ArrayIterator). Исключение – атрибуты PHP
Стандарт кодирования Nette соответствует PSR-12 (или PER Coding Style), но в
некоторых пунктах уточняет или меняет его:
Стрелочные функции пишутся без пробела перед скобкой, то
есть fn($a) => $b
Пустая строка между разными видами импортов use не
требуется
Возвращаемый тип функции или метода и открывающая фигурная скобка
всегда находятся на разных строках:
public function find(
string $dir,
array $options,
): array
{
// тело метода
}
Открывающая фигурная скобка на отдельной строке важна для
визуального отделения сигнатуры функции или метода от тела. Если
сигнатура на одной строке, разделение очевидно (изображение слева).
Если она на нескольких строках, в PSR сигнатура и тело сливаются
(посередине), а в стандарте Nette остаются разделёнными (справа):
Блоки документации (phpDoc)
Главное правило: никогда не дублируйте сведения из сигнатуры,
такие как тип параметра или возвращаемый тип, если это не добавляет
ценности.
Блок документации к определению класса:
Начинается с описания класса
Дальше пустая строка
Дальше аннотации @property (или @property-read, @property-write),
по одной на строку. Синтаксис: аннотация, пробел, тип,
пробел, $имя
Дальше аннотации @method, по одной на строку. Синтаксис:
аннотация, пробел, возвращаемый тип,
пробел, имя(тип $параметр, ...)
Аннотация @author опускается. Авторство хранится в истории
исходного кода
Можно использовать аннотации @internal или @deprecated
Блок документации к свойству, содержащий только аннотацию @var,
должен быть на одной строке:
/** @var string[] */
private array $name;
Блок документации к определению метода:
Начинается с краткого описания метода
Без пустой строки
Аннотации @param, по одной на строку
Аннотация @return
Аннотации @throws, по одной на строку
Можно использовать аннотации @internal или @deprecated
За каждой аннотацией следует один пробел, кроме @param, за
которой ради лучшей читаемости следуют два пробела.
/**
* Finds a file in directory.
* @param string[] $options
* @return string[]
* @throws DirectoryNotFoundException
*/
public function find(string $dir, array $options): array
Глобальные функции и константы
Глобальные функции и константы пишутся без ведущего обратного слеша,
то есть count($arr), а не \count($arr). Для функций, которые PHP умеет
оптимизировать, добавьте в начало файла use function, чтобы
компилятор мог перевести их эффективнее. К ним относятся функции вроде
count, strlen, is_array, is_string, is_scalar,
sprintf и т. п. Функции перечисляются на одной строке, чтобы блок
импортов оставался компактным:
use Nette;
use function count, is_array, is_scalar, sprintf;
Изредка мы импортируем и константы, знание значения которых может
помочь компилятору:
use const PHP_OS_FAMILY;
Табуляции вместо пробелов
У табуляций есть несколько преимуществ перед пробелами:
Размер отступа настраивается в редакторах и в вебе
Они не навязывают коду предпочтения автора по размеру отступа,
благодаря чему код становится переносимее
Их можно ввести одним нажатием клавиши (где угодно, а не только в
редакторах, которые преобразуют табуляции в пробелы)
Отступ – их прямое назначение
Они учитывают нужды слабовидящих и слепых коллег
Используя в наших проектах табуляции, мы даём возможность настроить
ширину, что большинству людей может показаться ненужным, но для людей с
нарушениями зрения это принципиально важно.
Для слепых программистов, использующих брайлевские дисплеи, каждый
пробел означает одну брайлевскую ячейку. Так что если отступ по
умолчанию равен 4 пробелам, отступ 3-го уровня тратит 12 ценных
брайлевских ячеек ещё до начала кода. На дисплее из 40 ячеек, самом
распространённом для ноутбуков, это больше четверти доступных ячеек,
потраченных впустую и не несущих никаких сведений.