Как правильно документировать файлы, классы и конструкторы? - PullRequest
25 голосов
/ 21 апреля 2011

Какой самый полезный / самый стандартный / наименее удивительный способ последовательной записи блоков комментариев для конструкторов и классов и файлов, содержащих только один класс?

  • Блоки комментариев для классов, а не конструкторов
  • Блоки комментариев для конструкторов, а не классов
  • Блоки комментариев как для конструкторов, так и для классов -> В таком случае, какие детали должны содержаться в каждом?

А затемсам файл?Нужен ли для этого блок комментария, если он содержит только один класс?Какие детали должны быть там указаны?

Я хочу, насколько это возможно, избегать повторения между классом, конструктором и блоками комментариев к файлу.

Ответы [ 4 ]

62 голосов
/ 21 апреля 2011

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

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

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

Что вам абсолютно нужно

Если вы хотите использовать PHPDoc, вы нужен блок документа файла и еще один блок документа после этого (обычно это блок класса документа).

Эти ** должны * иметь тег @package.Все остальное не является обязательным.

Я бы сказал, что даже тег @package является необязательным, поскольку вы можете автоматически сгенерировать его для проекта.И если я правильно помню, PHPDoc позволяет вам даже установить пакет по умолчанию для всего, что не имеет тега.

Для документации в целом позвольте мне начать с примера ( более длинный пример в конце ):

Сколько раз вы можете объяснить, что означает "uri":

Massive docs Обратите внимание, что для getUri объясняется, что означает URI (просто для того, чтобы о чем-то поговорить в комментарии, который я предполагаю), пока он не находится в isAbsUri, потому что тамВы можете, по крайней мере, дважды сказать «abs означает абсолют».


Если вы не являетесь проектом с открытым исходным кодом (или вам необходимо отправить ЗАВЕРШИТЕ !!! 11eleven API-документацию):

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

Нет смысла снова что-то писать в блоках документов, и с 2011 годаи у нас есть терминалы шириной 120 символов и автозаполнение, больше нет необходимости сокращать все ради экономии некоторых символов.

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

Хороший комментарий должен объяснить ПОЧЕМУ что-то было сделано, покасам код должен объяснить, КАК без дальнейших комментариев.

Мой любимый пример для избыточных документов следующий:

class myClass {
/**
 * Constructor
 */
public function __construct() {
}

НекоторыеВ руководствах говорится, что вы ИМЕЕТ документировать ВСЕ , и в конечном итоге люди снова и снова заявляют об очевидном.

Это не добавляет значения, но тратит время при чтении кода.

Пример правильного именования:

class Person { 
/** 
 * Set a persons weight in Kilogram
 *
 * @param float $kg Weight in Kilogram
 */
public function setWeight($kg) {}

Этот код легко документировать, потому что вам нужно объяснитьчто означает «кг», потому что некоторые люди могут использовать другую систему, а вы не можете гуглить по «кг».

Я за то, чтобы написать

class Person { 
/** 
 * @param float $kilogram
 */
public function setWeight($kilogram) {}

Блок документовИзлишне, потому что ДЕЙСТВИТЕЛЬНО можно ожидать, что вызов setWeight на Person установит Вес на Человека.Не нужно записывать это снова.

Использование $ килограмм в качестве параметра также избавит вас от необходимости объяснять это в документации, и я бы сказал, что в зависимости от вашей среды каждый может ожидать, что 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

И еще маленький, немного постарше, напыщенный: they-told-you-to-document-everything-they-lied

Книжные ссылки:

Clean Code - Cover Clean Code: A Handbook of Agile Software Craftsmanship

Refactoring - Cover Рефакторинг: улучшение дизайна существующего кода

Более длинный пример

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.

Значит, вызов -> initialize для xyzRequest инициализирует этот запрос? В самом деле? Хорошо, если вы так говорите!

   * Available options:
   *
   *  * logging: Whether to enable logging or not (false by default)

Нам сообщают варианты для третьего параметра, а не для второго или третьего параметра, но, может быть, мы знаем их, если знаем структуру? (Так как мы не можем понять, что -> initialize делает без чьего-либо указания на использование, мы можем быть не настолько умны ...)

   * @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

Таким образом, логическое возвращаемое значение «истина» для «хорошего» и «ложь» для плохого ».

   * @throws <b>xyzInitializationException</b> If an error occurs while initializing this xyzRequest
   */

Значит, выдается исключение, если возникает ошибка, когда мы делаем то, что называется функцией?

Таким образом, исключения используются для случаев ошибки. Хорошо. Полезно знать.

  • Не говорит мне разницу между возвращаемым ложным и исключением.
  • @ выбрасывает себя хорошо, потому что добавляет информацию
  • Кстати: почему это BOLD, а не @ link
1 голос
/ 21 апреля 2011

Лично я комментирую в конструкторах, только если есть что-то особенное, чтобы комментировать (например, специальная инициализация).

Я бы не сказал, что это «самый полезный» способ, но этосохраняет код в чистоте и повторять его дважды, в действительности одно и то же не нужно (если это ваша проблема).

0 голосов
/ 21 апреля 2011

Лично я считаю, что документация по классам и методам - ​​самая важная документация.Когда я пишу код, мне нужна помощь моей IDE, когда завершение кода показывает мне документацию, относящуюся к методу.Таким образом, я легко могу найти нужный мне метод.

Поскольку я стараюсь свести явную инициализацию классов к минимуму, я не использую комментарии конструктора.Поэтому я стараюсь избегать использования самих конструкторов.

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

0 голосов
/ 21 апреля 2011

Комментируйте все - файлы (авторство, авторское право, описание и т.д.), классы (описание, примеры кода), методы и свойства Здесь - хороший пример с phpDoc комментариями.

...