Ответ 1
Это сильно зависит от вашего контекста и предполагаемого уровня квалификации людей, с которыми вы работаете, или от людей, которые приходят после вас.
Если вы публикуете фреймворк, библиотеку или что-то подобное, вы обычно предполагаете, что ваш пользователь имеет все уровни навыков, чтобы мог документировать как можно больше тривиального дерьма, чтобы уменьшить нагрузку вопросов, с которыми ваше сообщество должно справиться.
Позвольте мне начать с примера, где, по моему мнению, документация может быть большой болью.
Что вам нужно?
Если вы хотите использовать PHPDoc, вам понадобится блок doc файла и другой блок doc после этого (как правило, блок doc класса).
Те ** должны * иметь тег @package
. Все остальное не является обязательным.
Я бы зашел так далеко и сказал, что даже тег @package
не является обязательным, поскольку вы можете автоматически генерировать его для проекта. И если я правильно помню, PHPDoc позволяет даже установить пакет по умолчанию для всего, что не имеет тега.
Для документации в целом позвольте мне начать с примера (длинный пример в конце):
Сколько раз вы можете объяснить, что означает "uri":
Обратите внимание, что для
getUri
объясняется, что означает URI (просто нужно что-то обсудить в комментарии, который я предполагаю), пока он не находится в isAbsUri
, потому что там вы можете хотя бы сказать "abs означает абсолютный", дважды.
Если вы не являетесь проектом с открытым исходным кодом (или вам необходимо отправить документацию COMPLETE!!! 11eleven api):
Я бы сильно предлагал вместо правильный, длинный и описательный класс, имена переменных и методов.
В блоках doc нет никакой выгоды в написании чего-либо, и поскольку это 2011 год, и у нас есть 120 char широких терминалов и автозаполнение, просто не нужно больше сокращать все ради сохранения некоторых символов.
Я даже утверждаю, что документирование тривиальных вещей причиняет вам боль и вашу команду, заставляя вас тратить время на то, что никто не получает от вас, привычка всегда писать тривиальные документы и не читать их больше.
Хороший комментарий должен объяснить, ПОЧЕМУ что-то было сделано, в то время как код его сам должен объяснить КАК, не требуя дальнейших комментариев.
Моим любимым примером для избыточных документов является следующее:
class myClass {
/**
* Constructor
*/
public function __construct() {
}
Некоторые рекомендации говорят, что вы HAVE, чтобы документировать ВСЕ, и в итоге вы снова становитесь свидетелями очевидцев.
Это не добавляет значения, но тратит время при чтении кода.
Пример правильного именования:
class Person {
/**
* Set a persons weight in Kilogram
*
* @param float $kg Weight in Kilogram
*/
public function setWeight($kg) {}
Этот код легко документировать, потому что вам нужно объяснить, что означает "кг", потому что некоторые люди могут использовать другую систему, и вы не можете использовать Google для "кг".
Я сторонник написания
class Person {
/**
* @param float $kilogram
*/
public function setWeight($kilogram) {}
Блок doc лишний, потому что вызов setWeight
on Person
может ДЕЙСТВИТЕЛЬНО ожидать, чтобы установить Вес на Человеке. Не нужно писать это снова.
Использование $kilogramm в качестве параметра также избавляет вас от необходимости объяснять его в документах, и я бы сказал, что в зависимости от вашей среды всех можно ожидать от Google за килограмм, если он действительно не знает измерения блок.
Документация @PHPDoc
- Все мое скромное мнение конечно
- Если вы не используете подсказки типов, всегда используйте теги @param.
- Всегда используйте теги @return
- Не используйте теги @author. Соблюдение коллекционного кода более ценно, и информация всегда находится в репозитории управления версиями.
- Используйте только теги @copyright, если вам нужно. Мне нравится иметь только файл LICENSE, но я не юрист, поэтому это может быть необходимо.
Встроенные комментарии:
public function generateReport() {
// get the db connection
$reg = WhateverGlobalStorage::get("db");
// auth
if(!$reg->getOne("SELECT view_report FROM USER ...")) {}
// template
$id = $reg->getOne("select ... ");
// render
new ReportTemplate($id); // ...
}
Если это отдельные "блоки", просто переместите их на описательные именованные функции
public function generateReport() {
$this->checkAuthentication();
$template = this->createReportTemplate();
$this->renderReport($template);
}
// Not perfect but at least you can grasp what the method does much quicker
Дополнительные ресурсы:
Слайды презентации, которые я дал на эту тему на некоторых конференциях: Slideshare: clean-code-stop-wasting-my-time
И еще маленький, немного старше, rant: they-told-you-to-document-everything-they-lied
Ссылки на книги:
Clean Code: A Handbook of Agile Software Craftsmanship
Рефакторинг: улучшение дизайна существующего кода
Более длинный пример
abstract class xyzRequest {
/**
* Initializes this xyzRequest.
*
* Available options:
*
* * logging: Whether to enable logging or not (false by default)
*
* @param xyzEventDispatcher $dispatcher An xyzEventDispatcher instance
* @param array $parameters An associative array of initialization parameters
* @param array $attributes An associative array of initialization attributes
* @param array $options An associative array of options
*
* @return bool true, if initialization completes successfully, otherwise false
*
* @throws <b>xyzInitializationException</b> If an error occurs while initializing this xyzRequest
*/
public function initialize(xyzEventDispatcher $dispatcher, $parameters = array(), $attributes = array(), $options = array()) {
Посмотрим, по очереди, на что указывает эта документация. (Я немного шучу здесь, чтобы понять свою точку зрения)
* Initializes this xyzRequest.
Итак, вызов → инициализация в xyzRequest инициализирует этот запрос? В самом деле? Хорошо, если вы так говорите!
* Available options:
*
* * logging: Whether to enable logging or not (false by default)
Нам сообщаются параметры для третьего параметра, а не для второго или третьего параметра, но, возможно, мы знаем это, если мы знаем структуру? (Так как мы не можем понять, что → инициализировать, без того, чтобы кто-то говорил об использовании, мы, возможно, не были такими умными...)
* @param xyzEventDispatcher $dispatcher An xyzEventDispatcher instance
Да, тип-подсказка есть. Поэтому, если метод ожидает "экземпляр xyzEventDispatcher", нам нужно передать "экземпляр xyzEventDispatcher". Полезно знать.
* @param array $parameters An associative array of initialization parameters
* @param array $attributes An associative array of initialization attributes
* @param array $options An associative array of options
Ok. Так что это не линейный массив. Но мне нужно передать "параметры инициализации" методу "инициализации", который я мог бы вычислить.
По-прежнему не знаю, что мне на самом деле нужно пройти там, но пока его документально зафиксировать, это должно быть хорошо!
* @return bool true, if initialization completes successfully, otherwise false
Таким образом, возвращаемое значение boolean является "true" для "good" и "false" для "bad".
* @throws <b>xyzInitializationException</b> If an error occurs while initializing this xyzRequest
*/
Итак, возникает исключение, если возникает ошибка, когда мы выполняем то, что называется функцией?
Таким образом, исключения используются для ошибок. ОК. Полезно знать.
- Не говорит мне разницу между return false и исключением.
- The @throws его сам отлично, потому что он добавляет информацию
- Btw: Почему этот BOLD, а не @link