Документирование PHP кода. DocBlock комментарии
Хочу рассмотреть принцип документирования программного PHP кода, основанный на DocBlock (DocBlock comments). Многие называют его стандартом, хотя каких-то авторитетных источников, подтверждающих это, я не нашел. Тем не менее, данный формат комментариев распространен во многих языка. Насколько я понимаю, пришел он из Java и по своему принципу наследует Javadoc. Он прекрасно поддерживается и интерпретируется средами разработки. Также существует немало решений, позволяющих автоматически генерировать документацию на основе таких комментариев.
DocBlock – это многострочный комментарий, требующий соблюдения определенного синтаксиса. В PHP данный способ более известен под другим именем – phpDoc. Оно происходит от названия утилиты phpDocumentor, предоставляющей возможность создавать страницы документации автоматически. Результат ее работы очень похож на официальную документацию PHP.
О пользе написания комментариев написано немало. Обычно призывы основаны на необходимости заботиться о тех, кому придется работать с вашим кодом в дальнейшем. Безусловно, я с этим согласен, но считаю это очень плохой мотивацией. Люди эгоистичны и зачастую действуют только в своих собственных интересах, что совершенно нормально.
Я хочу привести ряд аргументов, которые, возможно, смогут убедить в том, что хороший комментарий несет пользу прежде всего нам самим. phpDoc блоки позволяют увеличить не только читаемость существующего кода, но и ускорят написание нового за счет использования возможностей IDE.
Синтаксис phpDoc
Весь синтаксис строится на использовании дескрипторов и их значений, обернутых в Си подобный многострочный комментарий.
/**
* @имя_дескриптора значение_директивы
* @еще_дескриптор
*
*/
Наверное, стоит заметить, что каждая строка внутри блока должна начинаться с символа *. Именам дескрипторов предшествует знак @.
phpDoc может описывать не только отдельные участки кода, но и весь файл скрипта, располагаясь в самом начале файла. Такой блок называется заголовочным.
Ниже предлагаю список дескрипторов phpDoc и мои комментарий к ним.
Дескриптор | Значения/Пример | Описание |
---|---|---|
@abstract | none | Описывает абстрактные классы, методы или свойства |
@access | private/protected/public | Указывает на модификатор доступа свойства или метода класса. |
@author | @author Oleg Murashov |
Имя автора кода. phpDocumentor будет искать текст между угловыми скобками (< >). Если такая конструкция будет найдена и ее формат будет соответствовать e-mail адресу, то она будет преобразована в соответствующую ссылку. |
@category | @category Zend | Имя категории, в которую объединены несколько пакетов. |
@copyright | Copyright (c) 2005-2011 Company | Информация, указывающая на правообладателя кода. |
@deprecated | @deprecated 1.7 | Дескриптор указывает на то, что код устарел. В качестве значения дескриптора указывается версия, начиная с которой код считается устаревшим. |
@example | @example /path/example.php описание | Указывает путь к файлу, содержащему пример использования кода. phpDocumentor опубликует пример, подсветив синтаксис и пронумеровав строки. |
@final | none | Дескриптор отмечает методы или свойства, которые не могут быть перегружены в дочерних классах. Также может быть отмечен класс, который не должен быть наследован. |
@filesource | none | Дескриптор может быть использован только в заголовочном комментарии. В других местах она игнорируется. Указывает phpDocumentor’у на необходимость вывести исходный код текущего файла, подсветить синтаксис и пронумеровать строки. |
@global | @global datatype описание | Дескриптор для декларации глобальных переменных. Для понимания того, как верно использовать данную директиву, лучше всего обратиться к соответствующей документации. |
@ignore | none | Сообщает phpDocumentor’у, что данный код не следует включать в лист документации |
@internal | @internal комментарий | Значение дискриптора не будет добавлено в файлы документации. Удобно, если нужно оставить комментарий только для тех, кто работает с кодом |
@license | @link http://www.example.com/License.txt GPL License | Добавляет ссылку на лицензию, под которой распространяется код |
@link | @link http://www.example.com Текст ссылки | Дает возможность добавить ссылку в к любому документируемому коду. |
@method | @method returntype описание | Используется для описания магического метода __call(). |
@name | @name $globalvariablename | Дает возможность сослаться на краткое имя глобальной переменной, объявленной с помощью @global |
@package | @package Zend_Pdf | Указание имени пакета, в который входит данный программный код (файл). Используется в заголовочном блоке файла или в блоке комментариев класса. |
@param | @param datatype1|datatype2 $paramname описание | Дескриптор описывает входные параметры для функций и методов классов. Содержит информацию и типе данных параметра и его описание. |
@property @property-read @property-write |
Дескрипторы описывают свойства класса, которые могут быть записаны или прочитаны с помощью магических методов __set() и __get(). Если свойство доступно для чтения и записи, необходимо использовать директиву @property. Если только для чтения или только для записи, то @property-read или @property-write соответственно. Используются только в блоке описания класса. | |
@return | @return datatype1|datatype2 описание | Используется для описания данных, возвращаемых функцией или методом класса. Синаксис схож с дискриптором @param. Если в качестве типа будет указано имя класса, phpDocumentor автоматически создаст ссылку на данный класс. |
@see | @see … | Дескриптор предлагает обратиться к другому, уже существующему докблоку. Например, может быть использован при документировании метода, класс которого имплементирует интерфейс, где уже существует полноценный докблок. Позволяет избежать дублирования комментариев. |
@since | @since v 0.7 | Указывает на версию пакета/класса, с которой комментируемый элемент стал доступен. Например, при описаниии метода, который появился только в какой-то версии класса, можно указать эту версию. |
@static | none | Маркирует статические методы или свойства класса |
@subpackage | @subpackage Name | Используется для объединения нескольких пакетов в один раздел документации. Игнорируется, если нет дескриптора @package. Как и @package, помещается в заголовочном блоке комментариев. |
@todo | @todo Something | Можно описать будущие возможные изменения кода |
@throws | @throws MyException | Указывает тип исключения, который может быть возвращен участком кода |
@var | @var string | Указывает тип свойства класса |
@version | @version Version 1.1 | Текущая версия реализации документируемого кода. |
Дескрипторы @access, @final и @abstract были актуальны в PHP 4, но сейчас их можно не использовать, так как они потеряли актуальность с появлением модификаторов доступа и ключевых слов final и abstract.
Каждый docBLock делится на несколько секций:
- заголовок;
- описание;
- список дескрипторов.
Разделителем для секций служит пустая строка.
Примеры использования phpDoc комментариев
Я не хочу приводить синтетические примеры, поэтому заимствую код из популярного фреймворка Zend Framework, который, как мне кажется, имеет самые толковые и подробные блоки комментариев.
Я значительно укоротил многословные описания методов и классов, избегая избыточности в рамках примера. Обратите внимание на общий принцип документирования и на синтаксис дескрипторов.
Использование дескриптора @see
/**
* @see Zend_Acl_Resource_Interface
*/
require_once 'Zend/Acl/Resource/Interface.php';
Пример блока комментариев для метода класса
/**
* Removes "deny" restrictions from the ACL
*
* @param Zend_Acl_Role_Interface|string|array $roles
* @param Zend_Acl_Resource_Interface|string|array $resources
* @param string|array $privileges
* @uses Zend_Acl::setRule()
* @return Zend_Acl Provides a fluent interface
*/
public function removeDeny($roles = null, $resources = null, $privileges = null)
{
return $this->setRule(self::OP_REMOVE, self::TYPE_DENY, $roles, $resources, $privileges);
}
Свойство класса
/**
* Role registry
*
* @var Zend_Acl_Role_Registry
*/
protected $_roleRegistry = null;
А вот один из примеров подсказок (Eclipse code assist), которые может предлагать среда разработки, в данном случае Eclipse.
Также среда разработки может выводить подсказки, основанные на docBlock. Например, подсказка, появляющаяся при наведении на имя метода Zend_Acl_Role_Registry::add().
Комментарии (4)
Есть класс с вспомогательными protected и public методами, который используется в основном классе посредством trait примеси. Как импортировать в основной класс всю автоподсветку из trait класса, чтобы во вне видились также публичные методы, а внутри класса, IDE не ругалась на приватные методы?
Хорошая работа. Спасибо!
Взгляд на ИИ и новейшие технологии
Understanding Artificial Intelligence, Machine Learning, and Deep Learning