Русские Блоги
Написание аккуратного кода является задачей каждого программиста. «Чистый код» указывал на то, что для написания хорошего кода вы должны сначала знать, что такое грязный код и что такое аккуратный код, а затем, благодаря целенаправленной практике, вы действительно можете написать аккуратный код.
WTF / min является единственным стандартом для измерения качества кода. Дядя Боб называет плохой код в книге "ванилью", что лишь подчеркивает, что мы являемся жертвами плохого кода. В Китае есть более подходящий словарный запас: программисты Шишан, хотя и не очень элегантные, но более объективные, являются жертвами и преступниками.
Что касается аккуратного кода, книга дает краткое изложение мастеров:
- Бьярне Страуструп: элегантный и эффективный, простой, уменьшает зависимость, делает только одно
- Grady Booch: просто и понятно
- Дэйв Томас: читаемый, поддерживаемый, модульный тест
- Рон Джеффрис: не повторяй, одиночная ответственность, выразительность
Среди них моим любимым является описание выразительности, слово, кажется, говорит об истинном значении хорошего кода: опишите функцию кода простым и прямым способом, не больше и не меньше.
Эта статья записывает некоторые мнения человека, который «имеет глубокое чувство того же самого» или «Dingguineng» после прочтения «чистого кода».
1. Искусство именования
Честно говоря, присвоение имен — это сложная задача, и для того, чтобы придумать правильное наименование, требуются большие усилия, особенно наш родной язык не является английским, обычно используемым в языках программирования. Но все это того стоит: хорошее именование делает ваш код более интуитивным и выразительным.
Хорошее имя должно иметь следующие характеристики:
1.1 Истинно
Хорошее имя переменной говорит вам: что это такое, почему оно существует, как его использовать
Если вам нужно объяснить переменные в комментариях, вы должны быть менее достойны названия.
Ниже приведен пример кода в книге, демонстрирующий улучшение качества кода путем именования.
1.2 Избегайте введения в заблуждение
- Не продаю овечье мясо
- Не охватывают идиомы
Здесь я должен вырвать код, который я видел только два дня назад, фактически использовал l в качестве имени переменной, и пользователь фактически является списком (единственное и множественное число плохо изучены !!)
1.3 Значимое различие
Код пишется на машину для выполнения, а также для чтения человеком, поэтому концепция должна быть разграничена.
1.4 Используйте прочитанные слова
Если имя не может быть прочитано, то это будет как глупая птица во время обсуждения
1.5 Простое в использовании наименование
Длина имени должна соответствовать размеру его области
1.6 Избегайте размышлений
Например, напишите временный код в коде, тогда читатель должен будет переводить его в его истинное значение каждый раз, когда он видит слово
2. Примечания
Выразительный код не нуждается в комментариях: правильное использование комментариев должно компенсировать нашу неспособность выразить себя в коде.
Надлежащая функция комментариев — компенсировать ошибку, с которой мы столкнулись при выражении наших намерений в коде. Это звучит разочаровывающе, но это правда. Правда в коде, комментарий — просто информация из вторых рук, и эти два не синхронизированы или не эквивалентны — самая большая проблема комментария.
Книга дает очень яркий пример для показа: используйте код для объяснения, а не комментарии
Поэтому, когда вы хотите добавить комментарий, вы можете подумать о том, сможете ли вы показать намерение кода, изменив наименование или изменив абстрактный уровень функции (кода).
Конечно, вы не тратите пищу из-за удушья. Книга указывает, что следующие ситуации являются хорошими примечаниями.
- Легальная информация
- Заметки о намерениях, почему вы это делаете
- Предупреждение
- TODO комментарий
- Увеличьте важность того, что кажется необоснованным
Среди них наиболее согласен личный пункт 2 и пункт 5, который легко выразить по имени, но почему он не интуитивен, особенно когда речь идет о профессиональных знаниях и алгоритмах. Кроме того, некоторый «не очень элегантный» код на первый взгляд может иметь свою особую готовность, затем следует прокомментировать такой код, чтобы объяснить, почему это так, например, чтобы повысить производительность критического пути, некоторый код может быть принесен в жертву. читаемость.
Худший комментарий — это устаревший или неправильный комментарий, который наносит огромный ущерб сопровождающему кода (возможно, через несколько месяцев), но кроме проверки кода, нет простого способа обеспечить код и комментарии Синхронизировать.
Три, функция
3.1 Единая ответственность функции
Функция должна делать только одну вещь, эта вещь должна четко отображаться именем функции. Метод суждения прост: посмотрите, может ли функция разделить функцию.
Функция будет либо делать do_sth, либо запрашивать query_sth. Самое отвратительное в том, что имя функции говорит только query_sth, но на самом деле это будет do_sth, что заставляет функцию иметь побочные эффекты. Как примеры в книге
3.2 Абстрактный уровень функции
Каждая функция имеет абстрактный уровень, и операторы в функции должны быть на одном абстрактном уровне, и разные абстрактные уровни не могут быть соединены вместе. Например, если мы хотим положить слона в холодильник, он должен выглядеть так:
Три строки кода в функции описывают три шага, связанных с порядком помещения слона в холодильник на одном уровне (высоте). Очевидно, что шаг pushElephant может содержать много подэтапов, но на уровне pushElephantIntoRefrige вам не нужно знать слишком много деталей.
Когда мы хотим понять новый проект, читая код, мы обычно применяем стратегию в ширину, читаем код сверху вниз, сначала понимаем общую структуру, а затем углубляемся в детали, представляющие интерес. Если нет хорошей абстракции деталей реализации (и сжатой функции), читатель может легко потеряться в деталях.
В какой-то степени это похоже на принцип пирамиды
Каждый уровень должен демонстрировать точку зрения предыдущего уровня, но также нуждается в поддержке следующего уровня: несколько аргументов одного уровня должны быть отсортированы в определенных логических отношениях. pushElephantIntoRefrige является центральным аргументом и требует поддержки нескольких подэтапов, и между этими подэтапами также существует логическая последовательность.
3.3 Параметры функции
Чем больше параметров функции, тем больше входных данных объединено, тем больше нужно тестов и тем проще будет ошибиться.
Выходной параметр труден для понимания по сравнению с возвращаемым значением, которое глубоко эмпатично, а выходной параметр на самом деле не интуитивно понятен. С точки зрения вызывающей функции, возвращаемое значение можно увидеть с первого взгляда, и трудно определить выходной параметр. Выходные параметры обычно вынуждают вызывающую программу проверять сигнатуру функции, что действительно недружелюбно.
Передача логического (называемого в книге аргументом флага) функции обычно не очень хорошая идея. Особенно поведение после перехода в Истину или Ложь — это не две стороны одного, а две разные вещи. Это явно нарушает ограничение единственной ответственности функции, решение простое, то есть использовать две функции.
3.4 Dont repear yourself
На функциональном уровне проще всего реализовать интуитивно понятное и интуитивно понятное решение, и многим IDE также сложно помочь нам рассказать о куске кода для реконструкции функции.
Однако на практике также может возникнуть ситуация, когда фрагмент кода используется в нескольких методах, но это не совсем то же самое. Если он абстрагирован в общую функцию, то вам нужно добавить параметры и добавить, если еще. Это немного неловко, кажется, что оно исправимо, но не идеально.
Одна из причин вышеуказанной проблемы состоит в том, что этот код также нарушает принцип единой ответственности и выполняет более чем одно, что приводит к плохому повторному использованию. Решение состоит в том, чтобы разделить метод для лучшего повторного использования. Вы также можете рассмотреть метод шаблона, чтобы справиться с разницей.
Четыре, тест
Очень стыдно, что в проектах, которые я испытал, тестированию (особенно модульному тестированию) не уделялось достаточно внимания, а TDD не пробовали. Именно из-за недостатка он более ценен для хорошего тестирования.
Мы часто говорим, что хороший код должен быть читаемым, обслуживаемым и расширяемым, а хороший код и архитектура должны постоянно подвергаться рефакторингу и повторению, но автоматическое тестирование является основой для обеспечения всего этого, и нет высокого охвата Автоматизированное модульное тестирование, регрессионное тестирование, никто не решается изменить код, может только дать ему сгнить.
Даже если модульные тесты написаны для основных модулей, они, как правило, очень случайные, считая, что это всего лишь тестовый код, не достоин статуса производственного кода, думая, что пока он может выполняться. Это приводит к очень плохой читаемости и удобству сопровождения тестового кода, а затем затрудняет обновление и развитие тестового кода с помощью рабочего кода и, в конечном итоге, приводит к сбою тестового кода. Таким образом, грязный тест — эквивалентно — никакого теста.
Поэтому проверьте три элемента кода: читаемость, читаемость и читаемость.
8 признаков плохого кода
Порой для того, чтобы определить, что перед вами плохой код достаточно одного взгляда на него: форматирование и регистр имён сущностей сразу бросаются в глаза. В этой статье перечислены признаки, которые помогут вам понять, что перед вами действительно плохой код.
Загадочные имена
Одна из основных особенностей плохого кода — стратегия именования сущностей. Если в команде отсутствуют соглашения об именовании, их следует принять. С ростом приложения правильное именование становится критически важным.
Общие принципы именования помогут команде (особенно если в ней есть разработчики разного уровня) находить общий язык и лишний раз не ломать голову в попытках понять\придумать имя для переменной.
Вот принципы которые вы можете использовать:
- Имя должно описывать цель существования переменной:
- Всеми силами избегайте непонимания:
- Имена должны быть произносимыми:
- Имя должно быть удобно искать:
- Стратегия именования должна быть согласованной:
Огромные методы
Слишком большие методы являются источником ошибок и сложны для понимания. Есть правило: функция должна выполнять одну задачу и выполнять её хорошо.
Божественный объект
Так называют огромный класс, который делает слишком много разных вещей. Класс, как и функция, должен иметь одну цель существования. Поэтому божественный объект должен быть разделён на несколько сущностей, каждая из которых имеет только одну задачу.
Дублирующийся код
Идентичный код, который разбросан по всему приложению. Он увеличивает сложность поддержки и тестирования системы. Повторяющиеся куски кода являются признаком того, что вам пора задуматься о рефакторинге.
Избыток параметров
Длинный список параметров усложняет чтение, вызов и тестирование функций. Уменьшение числа параметров позволит вам сократить время на изучение и тестирование кода.
Неуместная сложность
Принудительное использование чрезмерно сложных шаблонов проектирования там, где более простой архитектуры было бы достаточно.
Использование сложных паттернов без необходимости показывает не ваш скилл, а неспособность увидеть картину целиком и избежать излишней сложности.
Хирургия дробовиком
Термин shotgun surgery используется для случая, когда одно изменение в коде влечёт за собой множество других изменений.

Изменения в классе A требуют множества незначительных изменений в других классах
Изменяемость переменных
Код, переменные в котором изменяются непредсказуемо, сложно отлаживать и проводить рефакторинг.
Теория чистого кода. Стиль кодирования
Чистый код должен быть эффективным, простым для восприятия и сопровождения, гибким и надежным. Приведенные требования зачастую противоречат друг другу, поэтому для написания чистого кода в каждом конкретном случае надо идти на некоторый компромисс. Нередко опытные программисты пытаются сформулировать советы по написанию чистого кода [1, 2, 3, 4, 5], которые зависят от используемого языка программирования, но во многом сходятся.
Эта статья изначально планировалась как своеобразная критика книги «Чистый код. Создание, анализ и рефакторинг» Роберта Мартина [1], поэтому я часто буду на него ссылаться. Мартин писал наиболее общие советы безотносительно конкретного языка программирования — этим его книга в корне отличается от других [2, 3, 4].
Статья не является сборником готовых инструкций к написанию кода, но должна наводить на мысль о том, как делать это более правильно.
Содержание:
Эволюция требований к чистому коду
Требования к коду менялись со временем. Очевидно, что в 80х годах компьютеры были менее производительны чем сейчас и огромный упор делался на эффективность программ. Рост производительности привел к появлению новых синтаксических конструкций, подходов к программированию и языкам. Так например, использование кодов ошибок вместо исключений в настоящее время считается дурным тоном, однако на заре компьютерной эры исключений просто не существовало.
Однако, изменение требований связано не только с ростом производительности — например, ограничение на ширину и высоту кода стали неактуальны с распространением мониторов с высоким разрешением. На старых мониторах строки, длина которых была более 80 символов, приходилось перематывать — это сильно осложняло чтение кода. Помимо ограничения на ширину, существовало также ограничение высоты функций — очень удобно если функция целиком умещается на один экран монитора. Сейчас эти требования не исчезли совсем, но стали более мягкими — писать весь код в одну строку не стоит.
Выработаны архитектурные конструкции, правильное использование которых упрощает проектирование, восприятие и сопровождение программ — шаблоны проектирования. Шаблоны имеют широкое распространение и хорошо описаны в литературе — если программист, читая исходный код увидит слово Factory, то он заранее знает чего ждать от такого кода. Для каждого шаблона проанализированы сильные и слабые стороны, поэтому их использование предпочтительнее велосипедостроения.
Наконец, изменились средства разработки программ — появились системы контроля версий, удобные инструменты тестирования, системы отслеживания ошибок, управления задачами и многое другое. Весь этот инструментарий оказался интегрирован в удобные среды разработки.
Независимо от того, какой язык программирования вы используете, хороший код должен обладать следующими характеристиками:
- не должен мешать программисту вносить изменения;
- должен легко тестироваться;
- должны использоваться, по возможности, стандартные решения.
Соглашения о кодировании
В каждой конторе существуют свои собственные соглашения о стиле кодирования (coding conventions). Когда я устроился на свою первую работу — мне тоже выдали такой документ, который представлял собой сборник правил. Было не понятно чем обусловлены эти правила, но в будущем я узнал, что основная их часть имеет под собой крепкое основание.
Например в соглашении было регламентировано именование файлов с исходным кодом, которое, среди прочего, запрещало использование строчных букв. Правило может выглядеть причудливо, де тех пор, пока его нарушение не приведет к тому, что код будет отлично работать в Windows, но откажется собираться в Linux. Связано это с тем, что по умолчанию Linux учитывает регистр в именах файлов, а Windows — нет.
В соглашении обычно фиксируется использование множества специфичных для конкретного языка программирования конструкций. Например, для языка С++ может быть закреплено обязательное использование ключевого слова const везде где это возможно (это позволяет переносить обнаружение ряда ошибок на этап компиляции), запрет использования директив pragma (они могут оказать негативное влияние на переносимость программ) или, например, требование использовать, по возможности, const вместо define.
Стандарты кодирования закрепляются в документах, которые описывают все детали — есть такой документ у любой крупной компании (типа Mozilla, Google, Microsoft [6,7,8]). Причем, для разных языков программирования стандарты могут отличаться — тем не менее, во многом они схожи, именно эти аспекты (а точнее, их причины) раскрываются в статье.
Отступы
Большое внимание в соглашениях уделяется расстановке скобок, пробелов и переводов строк и т.п.. Казалось бы, нет разницы — поставлен пробел перед фигурной скобкой или нет, однако все эти правила стремятся обеспечить:
- Единый стиль оформления кода во всем проекте;
- Визуальное выделение наиболее значимых частей.
Может получиться так, что участники проекта привыкли использовать разные соглашения о кодировании – все они могут быть очень хорошими, но их смешанное использование даст плохой результат. Код просто будет почти также плохо читаться, как если бы его вообще не форматировали.
В качестве примера я взял первую попавшуюся студенческую поделку — решаемая задача стоит в том, чтобы заполнить массив случайными числами, а затем обработать его элементы по заданной формуле:
Четвертая строка смещена вправо — возможно автор сделал это намеренно, чтобы нас о чем-то предупредить, но скорее всего, смещение произошло из за того, что при форматировании вперемешку использовались пробелы и символы табуляции. Современные среды разработки программ позволяют настроить автоматическую замену табуляций пробелами для решения указанной проблемы. Аналогичная проблема наблюдается в 15 строке.
Смещение тела цикла (7-11 строки) произошло, вероятно, в следствии модификации кода — изначально это был вложенный цикл, но затем студент что-то исправил, но форматирование сохранил. В маленькой функции такое отсутствие форматирования не сильно мешает, но в более серьезном коде, оно отвлекает, расходует ваше время и портит зрение. В конце концов, многие IDE имеют горячие клавиши, для форматирования фрагмента кода по заранее заданным правилам — достаточно один раз настроить среду разработки чтобы всегда экономить время.
В приведенном коде есть множество других недочетов:
- в 9 строке выполняется приведение типа в функциональном стиле (тип используется как функция) и после открывающей скобки стоит пробел, но в 14 строке — при вызове функции pow, пробел не поставлен. Возможно, автор лишний пробел поставил умышленно и человек, читающий код, обратит на это внимание;
- лишний пробел стоит перед объявлением переменных в третьей строке;
- оператор присваивания в 9 строке выделен пробелами, но в 10 — пробелы отсутствуют.
Возможно, часть проблем связана с тем, что студент попросил помощи у одногруппников, которые исповедуют другие стандарты кодирования.
В приведенной программе стоит множество лишних круглых скобок, которые очень сильно осложняют восприятие. Мало того, что скобки очень важны и часто таят в себе ошибки, они имеют свойство скапливаться — как в 14 строке. Большинство сред разработки подсвечивают парные скобки, но это не очень сильно облегчает жизнь.
Общее правило состоит в том, чтобы не ставить скобки там, где они не нужны, при этом надо учитывать, что иногда лишние скобки надо оставить, т.к. далеко не все помнят в совершенстве приоритеты операций. В ряде случаев приоритеты можно показать пробелами (см. ниже).
В 16 строке вокруг оператора умножения нет пробелов, но вокруг сложения они поставлены. Такой прием позволяет визуально выделить приоритеты операторов, а в ряде случаев — избежать расстановки круглых скобок.
Используя вертикальное форматирование, мы выделяем объявление переменных, цикл заполнения массива случайными числами и цикл обработки по формуле. Если ваша функция выполняет несколько действий — то разумно разделить соответствующие блоки кода пустыми строками.
Приведенная программа все еще далека от совершенства. Возможно, открывающие фигурные скобки не стоило выносить на отдельную строку, а между ключевым словом for и открывающей круглой скобкой нужно поставить пробел. Такие вопросы связаны с конкретным языком программирования и являются скорее религиозными, чем техническими — поэтому я не уделю им внимания. Однако, нельзя не заметить «плохие» имена переменных.
Во многих стандартах кодирования запрещается использовать табуляции — их требуют заменять пробелами, например в стандарте PHP (PSR-2):
Code MUST use 4 spaces for indenting, not tabs.
Или стандарте Python (PEP 0008):
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
Чем табуляция настолько хуже пробелов? — В различных редакторах может устанавливаться длина символа табуляции (обычно выражаемая пробелами), поэтому если в коде смешать табуляцию с пробелами — то исходник будет выглядеть по-разному в разных редакторах. Особенно критично это в языках типа Python, где отступы являются часть синтаксиса языка.
Имена
Коротко и ясно ключевое правило именования сформулировал Мартин — «имя должно отражать намерения программиста«, большинство других советов вытекает из этого утверждения: имя не должно дезинформировать, содержать лишнее, отвлекать, …. Достаточно часто пишут про недопустимость каламбуров и шуток в именах, а в моей педагогической деятельности был случай:
Студентка решала задачу о вычислении суммы ряда, при этом накопитель суммы назвала «i», а счетчики циклов — «s» и «o». На вопрос о том, почему она так назвала переменные, она ответила, что все ее одногруппники называют счетчики «i», а сумму — «s» или «sum» — поэтому это серые, унылые имена, а ей хочется писать красивые программы с гламурными именами.
Имена «i», «j» зарезервированы для счетчиков, от них не ожидают другого поведения. Имя «s» логично использовать для накопления суммы, а имя «o» — вообще лучше не использовать (визуально оно плохо отличимо от ноля).
Одно время мне приходилось использовать WinAPI, изобилующее всевозможными префиксами — разработчики Windows использовали Венгерскую нотацию, согласной которой тип своеобразным образом кодируется в имени [6].
В приведенном примере имена аргументов содержат закодированную информацию о типе. Так, префикс lp означает long pointer, префикс dw — double word (два машинных слова — unsigned long), а префикс b кодирует логический тип данных.
В настоящее время Венгерская нотация не в моде, причиной тому стала эволюция средств разработки. Сейчас программисту достаточно написать имя функции, чтобы IDE подсказала типы аргументов, при наведении указателя мыши (или каретки) на переменную может высвечиваться ее тип. С другой стороны, использование Венгерской нотации — это очень утомительно, мало того, что надо помнить все префиксы и печатать кучу лишних букв, так еще феерические проблемы подстерегают при изменении типа переменной.
Тем не менее, частично такие нотации до сих пор применяются — например, я нахожу удобным дополнять имя областью видимости. Соглашение о стиле кодирования Google [7] предлагает в конце имени данных-членов класса ставить символ подчеркивания. Согласно правилам кодирования mozilla [8] различные префиксы присваиваются данным-членам, глобальным переменным, аргументам функций, статическим членам и константам.
Мартин считает что и такие префиксы не нужны, его мнение разделяют многие программисты — на habrahabr не однократно проводились опросы о соглашениях кодирования и префиксах [9], которые это подтверждают. Например, вместо префикса, выделяющего данные-члены класса (часто это m, m_ или символ подчеркивания), предлагается использовать указатель на текущий объект — this (это не пройдет в списке инициализации конструктора):
Кроме префиксов областей видимости есть и другие, например:
- имена абстрактных классов (интерфейсов) дополняются префиксом I (ISocket), напротив — классы реализации могут снабжаться постфиксом Imp (SocketImp) или Impl (при использовании идиомы Pimpl). Класс в составе иерархии может содержать префикс C (CFigure), а классы исключений — постфикс Exception (BadArgumentsException)[1, 2, 10]. Есть множество других вариантов, которые часто противоречат друг другу.
- имена функций дополняются префиксами:
- is_ — проверяет что-то и возвращает логический тип — is_digit;
- has_ — выполняет поиск какого-либо значения в контейнере — has_primeNumber;
- get_ и set_ — метод возвращает или устанавливает значение какого-либо поля — set_volume, set_volume;
Правила именования не ограничиваются префиксами, например:
- названия должны использовать по возможности слова из предметной области решаемой задачи;
- имена классов должны выражаться существительными, функций и методов — глаголами;
- имена классов должны быть хорошо различимы — Страуструп приводит пример с именами fl, f1, fI и fi [11].
Важно соблюдение одних и тех же правила всеми разработчиками проекта, в противном случае проблем не избежать. Например, один программист может захотеть писать имена всех констант заглавными буквами, а другой — выводить заглавными только макросы, в то время, как константы будет выделять заглавной буквой в начале и «верблюжьим регистром«.
Приведен утрированный пример, однако, в файле pr.cpp окажутся как константы, объявленные первым программистом, так и вторым. Различия в обозначениях будут мешать обоим программистам — один может думать, что FIVE — это макрос, другой не сразу поймет, что TripleWaterPointTemp является константой.
Комментарии
Комментарий в программировании — это некомпилируемая часть исходного кода, поясняющая принцип работы программы. Иногда в комментариях фиксируют, также, информацию:
- о версии кода и, внесенных в ней, изменениях;
- об авторе кода или конкретных правок,
- о лицензии, по которой распространяется код;
- о неисправленных ошибках и прочих недочетах, заметки разного рода.
От комментариев, несущих информацию об авторском праве и лицензии никуда не деться, однако с остальными можно бороться — в последнее время все шире распространяется мнение, о том, что «комментарии — признак плохого кода» [12, 13]. Впрочем, есть и другое мнение — так, например, соглашение о кодировании mozilla требует использовать комментарии в стиле JavaDoc [8], а Мейерс в одном из своих 55 советов упоминает doxygen [2].
Существуют разногласия, однако, все программисты сходятся на том, что:
- комментарии должны говорить правду о коде. Корень зла — изменение кода, ведь параллельно надо менять комментарии. Слишком часто комментарии не изменяются, ведь начальство требует чтобы вы сдали проект вчера, а изменение комментариев в некоторых случаях занимает гораздо больше времени, чем сама правка кода;
- комментарии не должны пояснять очевидные моменты, т.к. читать в любом случае приходится и код, и комментарии — это отнимает время;
- комментарии должны быть понятны всем, а не только тем, кто их пишет;
- комментарии не должны содержать мусора и размышлений автора о жизни;
- написание комментариев и поддержка единого стиля комментариев не должна отнимать слишком много времени.
Из этого понятно, что комментарий должен быть точным, коротким и по теме. Комментариев следует избегать — по возможности стоит переписать код так понятно, чтобы потребность в комментарии пропала вовсе. Использование современных инструментов разработки позволяют полностью исключить некоторые типы комментариев из программы:
- информацию о версии программы, авторе изменений и ее особенностях позволяют хранить системы управления версиями [14 , 15];
- комментарии TODO, BUG и FIXME могут быть перенесены в трекеры задач и ошибок.
В информации, связанной с описанием ошибки или версии программы обычно указывается дата время и автор изменений — специализированные системы делают это автоматически в едином формате. Кроме того, такие системы управляют доступом к задачам (могут как сделать информацию общедоступной, так и доступной узкому кругу лиц) и позволяют распределять задачи и изменять их статус. Очевидно, что использование специализированных инструментов предпочтительнее.
Несмотря на то, что современные среды разработки умеют обрабатывать и выводить в окошках информацию о TODO, FIXME, NOTE и прочих специальных комментариях, могут существовать различия в формате:
Различные IDE могут как среагировать на оба комментария, так и ни на один из них :). В данном случае проблему создал один лишний пробел — в конторе где я работал с этим столкнулись, когда начали переносить проект с Windows (использовали Microsoft Visual Studio) на Linux (в качестве IDE выбрали Qt Creator).
Комментарии часто дублируют код — когда код понятен без комментариев. Особенно хорошо это видно при написании комментариев для doxygen или javadoc. Системы типа doxygen позволяют строить документацию к программе по исходному коду, при этом сама документация размазывается по коду в виде комментариев, записанных в специальном формате [16, 17]. Использования этих систем требуют многие соглашения о кодировании, использовались они и в фирме где я работал.
В приведенном фрагменте — «pure virtual member» заменяет описание функции, обычно на этом месте пишут что именно делает функция. Кроме того, часто пишут и короткое, и полное описание (они по-разному отображаются в документации). Тег «@see» позволяет связывать функции (связи отображаются в документации) — есть другие типы связей, а еще якоря, ссылки, секции, параграфы и т.п. Теги @param используются для описания аргументов функции.
Пример взят без изменения в официальной документации и ярко демонстрирует недостатки комментариев doxygen. Вообще, комментарии в этом случае нужны лишь потому, что у функции и аргументов выбраны плохие имена. С другой стороны, если имена были бы выбраны правильно, то комментарии попросту бы их дублировали. Дополнительные пометки — такие как теги, секции и т.п. — быстро устаревают. Программист может изменить тело функции (находящееся в другом файле), а неактуальными окажутся пометки в файле описания функции.
В реальных программах недостатки таких комментариев еще более очевидны, т.к. в них нет непонятного «pure virtual member», а каждая функция решает вполне определенную проблему. Код, приведенный ниже, взят из статьи про разработку игры. Дописанные комментарии ничего по существу добавить не могут, однако значительно увеличивают размер исходного кода — очевидно, что на их написание и поддержку расходуется немало времени.
Поддерживать соответствие кода и документации тяжело в любом случае — при изменении функции надо изменять документацию. Системы типа doxygen смешивают документацию с кодом, но никак не решают проблему.
С другой стороны, чтобы использовать doxygen, совсем не обязательно писать дополнительные комментарии. Если в вашей программе используются нормальные имена, то и документация получится съедобной — система doxygen построит вам нужные диаграммы (не только такую, как приведена ниже) и упакует все в удобный для чтения формат:

диаграмма классов doxygen
Выводы этой статьи состоят в том, что:
- форматировать код надо. Единообразно;
- правильные имена переменных могут сильно помочь при поддержке проекта;
- комментарии не решают проблемы плохого кода;
- современные инструменты разработки могут значительно облегчить поддержку и улучшить код;
- не всем советам «чистого кода» надо слепо следовать — часть из них может навредить.
В этой статье я касался лишь внешних моментов оформления кода, но чистый код этим не ограничивается — важной является правильная архитектура программ. Именно архитектуре и, связанным с ней, вопросам тестирования я посвящу несколько следующих статей.
Кстати, вопросы именования переменных и некоторые связанные с этим проблемы, относящиеся именно к языку С++, а также конструктивную критику Венгерской нотации можно прочитать в отдельной статье: «Именование переменных и констант в С++» [19].