Лучшие практики: Где функциональные комментарии должны войти в код C/C++? [закрытый]

Если бы сами GOTO были злыми, компиляторы были бы злыми, потому что они генерируют JMPs. Если вскакивание в блок кода, особенно после указателя, было по сути злым, инструкция по Возврату будет злой. Скорее зло находится в потенциале для злоупотребления.

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

request something
wait for it to be done
while some condition
    request something
    wait for it
    if one response
        while another condition
            request something
            wait for it
            do something
        endwhile
        request one more thing
        wait for it
    else if some other response
        ... some other similar sequence ...
    ... etc, etc.
endwhile

я уверен, что это не является новым, но способ, которым я обработал его в C (++), состоял в том, чтобы определить некоторые макросы:

#define WAIT(n) do{state=(n); enque(this); return; L##n:;}while(0)
#define DONE state = -1

#define DISPATCH0 if state < 0) return;
#define DISPATCH1 if(state==1) goto L1; DISPATCH0
#define DISPATCH2 if(state==2) goto L2; DISPATCH1
#define DISPATCH3 if(state==3) goto L3; DISPATCH2
#define DISPATCH4 if(state==4) goto L4; DISPATCH3
... as needed ...

Тогда (принимающий состояние первоначально 0) структурированный конечный автомат выше превращается в структурированный код:

{
    DISPATCH4; // or as high a number as needed
    request something;
    WAIT(1); // each WAIT has a different number
    while (some condition){
        request something;
        WAIT(2);
        if (one response){
            while (another condition){
                request something;
                WAIT(3);
                do something;
            }
            request one more thing;
            WAIT(4);
        }
        else if (some other response){
            ... some other similar sequence ...
        }
        ... etc, etc.
    }
    DONE;
}

С изменением на этом, может быть ВЫЗОВ и ВОЗВРАТ, таким образом, некоторые конечные автоматы могут действовать как подпрограммы других конечных автоматов.

действительно ли это необычно? Да. Требуется некоторое изучение со стороны специалиста по обслуживанию? Да. Это учение наизусть платит? Я думаю так. Это могло обойтись без GOTOs, которые вскакивают в блоки? Нет.

15
задан Polaris878 4 December 2009 в 22:12
поделиться

14 ответов

Я помещаю комментарии, описывающие то, что функция делает в заголовке, и комментарии, описывающие , как это делает, в файле cpp.

46
ответ дан 30 November 2019 в 23:49
поделиться

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

/**
 * Fills the handler with GIF information
 * 
 * @param filename GIF File name to be loaded
 * @return Inited GIF Handler or NULL for error
 */
pGifHandler gifHandlerLoad(const char* filename);

/**
 * Removes all data used by the GIF handler
 * 
 * @param gifHandler GIF Handler to be destroyed
 * @note This also clears palette and bitmap(s)
 */
void gifHandlerDestroy(pGifHandler gifHandler);

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

9
ответ дан 30 November 2019 в 23:49
поделиться

В порядке важности:

  1. Если это часть существующего проекта и существует преобладающий стиль комментариев, используйте его. Согласованность в базе кода более важна, чем индивидуальные предпочтения разработчика.

  2. Если это новый проект, используйте Doxygen или подобное для документирования вашего кода. Хотя это не отвечает на ваш вопрос, поскольку с ним можно использовать оба стиля. Запускайте его каждую ночь, чтобы у вас была обновленная исходная документация для просмотра.

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

Меня также сильно раздражают ленивые комментарии, особенно однострочные:

например, этот комментарий - пустая трата места, и его также можно удалить:

/** Get the width */
double getWidth();

Этот комментарий полезен:

/** Get the width in inches excluding any margin. */
double getWidth();
5
ответ дан 30 November 2019 в 23:49
поделиться

Размещение комментариев в заголовке - лучшее решение. Это потому, что:

  • При поиске документации по функция, заголовок является первым место для проверки.
  • Исходный файл может быть недоступен.
  • Исходный файл содержит намного больше чем объявление функции, а полезные комментарии могут утонуть.
3
ответ дан 30 November 2019 в 23:49
поделиться

Я использую Doxygen и использую короткое однострочное описание в заголовке и мощное многострочное описание в файле реализации. Я думаю, что это дает более чистые заголовочные файлы, которые мне легче воспринимать.

Примечание: Если бы вы выпускали этот код как библиотеку, люди, возможно, не захотели бы копаться в реализации. Тем не менее, файлы заголовков - это обычно честная игра. В этом случае я бы поместил подробную документацию в заголовок.

header:

// foo.h

class foo
{
public:
    /**\brief This function solves P = NP */
    int bar(int in);
};

cpp:

// foo.cpp

/** 
 \param[in]    an integer as input to algorithm foo

 \returns    The result of the algorithm foo on input in
*/
int foo::bar(int in)
{
    // some algorithm here which modifies in and returns the modified value
}
3
ответ дан 30 November 2019 в 23:49
поделиться

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

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

3
ответ дан 30 November 2019 в 23:49
поделиться

Мне нравится использовать условия PRE / POST. Что предпочитаете вы / компания. Но условия PRE и POST сообщают вам, что такое входящие / исходящие переменные и как они используются. Это также гарантирует, что вы следуете некоему руководству о том, как вы собираетесь вызывать функцию (предварительные условия) и какие будут выходы после этой функции (условия публикации).

2
ответ дан 30 November 2019 в 23:49
поделиться

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

2
ответ дан 30 November 2019 в 23:49
поделиться

Это все равно что спрашивать, как лучше всего надевать носки. Некоторые инструменты имеют больше шансов работать, если вы объедините декларацию и комментарий, и это, вероятно, лучше всего соответствует ожиданиям людей. Но комментировать случайным образом бессмысленно. Особенно иметь вход / выход, если у вас нет инструмента, который это использует. Любой программист может увидеть из объявления, что ему нужно, и то же самое относится к языку в целом. Нет ничего более бесполезного, чем комментарии вроде // это конструктор. // Нам пришлось это сделать, потому что какой-то странный API, который мы используем, требует определенных вещей // из-за чего некоторые другие вещи ломались, и вызовы к нему иногда оптимизируются // поэтому не удаляйте эти вызовы методов, иначе оптимизатор выполнит оптимизацию // что-то еще и вся программа перестает работать

2
ответ дан 30 November 2019 в 23:49
поделиться

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

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

2
ответ дан 30 November 2019 в 23:49
поделиться

Лучшая практика - это то, что стандартно для организации, для которой написан код.

Если это только для меня:

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

1
ответ дан 30 November 2019 в 23:49
поделиться

Поскольку я всегда использовал Visual Assist X и имею возможность очень легко перемещаться по коду, я использую файл заголовка в качестве индекса. То есть файл заголовка содержит только релевантные данные без дополнительных комментариев, чтобы не добавлять в файл раздувания. Если читателю нужна дополнительная информация о функции, он может перейти к cpp.

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

1
ответ дан 30 November 2019 в 23:49
поделиться

Назначение в заголовке, контракт выше реализации функции, почему в функции body.

Это требует либо доставки .cpp, либо использования такого инструмента, как doxygen , для публикации документации.

Преимущество во время зависимостей: улучшение документации не повлияет на зависимости заголовков.

В любом случае, выберите стиль и будьте последовательны

1
ответ дан 30 November 2019 в 23:49
поделиться

Внутри функции вы можете поместить комментарий в той же строке, что и открывающая скобка.


/* what is this function for, and so on.  Stuff the caller needs to know. */
foo ()
{       // pre-condition
}

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

В противном случае я всегда стараюсь помещать общие описания функции за его пределами и объяснять, почему он закодирован так, как внутри функции, рядом с кодом. Так что в целом согласен со стилем промоутеров Doxygen.

1
ответ дан 30 November 2019 в 23:49
поделиться