Как оставлять комментарии в css
Перейти к содержимому

Как оставлять комментарии в css

  • автор:

Alt linux ssh root или настройка школьного сервера

Как говорится настал час когда срочно приспичил сервер, да не просто сервер а Школьный сервер на базе Alt-Linux server дабы развернуть на нем фильтрующий прокси- сервер. Поставил я сие чудо на Виртуальную машину, и начал мучатся с настройкой ssh долго не копаясь, нашел решение. Авторизация root по умолчанию отключена так давайте её включим . (далее…)

Презентация iPhone 5 онлайн трансляция

Apple официально представила iPhone 5. ВИДЕО, ФОТО

Apple официально представила iPhone 5. ВИДЕО, ФОТО

Сегодня 12 сентября 2012 года состоится долгожданная онлайн презентация Iphone 5, которая будет проходить в городе Сан Франциска в 21:00 по московскому времени .

Пока все ждут официальный анонс iPhone 5, появились данные о том, когда же мы увидим его в России. (далее…)

Nuled 1C Битрикс Часть вторая

И так прошло не много времени сто го момента как я начал пользоваться 1С Битрикс, и скажу я вам функционал у движка довольно-таки не плохой, хотя и мне кажется, что там черт ногу сломит. Ну не об это пойдет речь, а о том что прошло пару месяцев и сайт просто-напросто прекратил работу и появилась надпись «Срок работы пробной версии продукта истек. Вы можете купить полнофункциональную версию продукта на сайте www.1c-bitrix.ru. Регистрация» И все, конечно же в последствии я собираюсь приобрести лицензию на данный движок НО, пока на это нет денег а сайт нужен, тем более, на него уже заходят гости и сотрудники. (далее…)

Сайт для детского садика

Решил я тут поделиться своими последними наработками, а именно как я залепил сайт для детского сада. Как сделать сайт для детского сада, спросите вы? Для создания сайта для детского садика можно пойти несколькими путями. Зарегистрироваться на все известной бесплатной площадке для размещения сайтов системе «Юкоз» все наверняка её знаю, это конечно же если вас не обламывает то что наполняя сайт вы развиваете проект на котором потом довольные админы крутят свою тизерную рекламу и вежливо предлагаю купить у вас доступ на сайт без рекламы за не большую плату в месяц. Ну для тех у кого совсем нет денег такой вариант вполне приемлем. Ну а что делать, если хочется красивый сайт и красивое доменное имя ? тогда вам придется не много вложиться и раскошелиться на покупку домена + хостиг ко всему этому немного потраченного времени и сайт у вас уже готов. (далее…)

JSON, который можно комментировать

Не все JSON нельзя комментировать (например, Хром[иум] вполне переносит комментарии в manifest.json), но в стандарте не предусмотрены комментарии к нему. Поэтому ряд функций в NodeJS не обрабатывают комментарии в формате JS и считают их ошибкой. Точно так же, AJAX с форматом JSON принимает их за ошибку. Поэтому для конфигурационных файлов в формате JSON имеется масса неудобств при попытках их использовать как человеко-читаемые файлы. Может быть, это иногда хорошо. Если хотим прокомментировать, то будем вынуждены оформить комментарий под или над строкой как «ключ-значение».

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

Придумаем JSON-подобный формат с комментариями в стиле JS, чтобы их можно было выполнять как JS, а, очистив от комментариев — читать как JSON. («TL:DR: покажите мне код.»)

Сыр-бор и источник

Кстати, Дуглас Крокфорд, который это всё устроил, в 2012 году объяснил: )

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

Допустим, вы используете JSON для хранения конфигурационных файлов, которые привыкли комментировать. Вставьте любые комментарии, как вам нравится. Затем пропустите их через JSMin перед работой JSON-парсера.

Сделал он это на G+, где можно ставить только «плюсы», а комментарии закрыл. Так что, какова бы ни была реакция общества под объяснением, мы увидим только «плюсы» (или смотреть у тех, кто расшаривал этот пост).

И цитата Крокфорда из другого места:

Основная причина, отчего я удалил комментарии — были люди, которые пытались парсить данные на основе комментариев, что полностью ломало совместимость. Я никак не мог контролировать их, поэтому лучшим выходом было комментарии удалить.

Поэтому дальше читаем, кликнув и согласившись на обещание:

«Обещаю, что я буду осторожен и не буду использовать комментарии для парсинга данных!

Всё уже сделано до нас

В том и дело, что требуется ещё один парсер, а так — большой проблемы нет. И проблема этим не ограничивается — иногда надо файл слегка изменить, оставив комментарии. Первую часть (парсер) решили, например, через JSON.minify(). Вторую и ряд других проблем (концевые запятые или вообще без них, многострочные комменты, ключи и строки-значения без кавычек) — не поленились решить в Hjson, потратив 750 строк на код JS (с комментариями на 10-15%).

Стоп, а нужно ли это вообще?

Несомненно, суровым программистам (таким, которые пишут комментарии как значения ключей в JSON), а также роботам (сетевым и вообще) это не нужно. Они прекрасно перекодируют имена ключей в любом знакомом им конфиге, а программисты — так вообще, имеют ещё интеллект, позволяющий им разбираться в незнакомых названиях и строить эвристики по их расшифровке без всякого компьютера. Остальные, в том числе не суровые программисты, считают комментарии полезными и тратят время не только на их чтение иногда, но и на их написание. Несомненно, Крокфорд относится к суровым программистам, а создатели YAML — нет. С этим приходится мириться и соединять миры роботов (и с.п.) и людей.

Есть ещё хакеры, которым подойдёт совершенно хакерский, валидный способ записи JSON с последовательным повторением одинаковых ключей (в JS+»use strict» даст ошибку). Значение первого ключа в большинстве парсеров не сохранится, поэтому его (и все такие, кроме последнего) можно использовать как комментарии. Способ тоже страдает «машинностью».

Итого, не все будут за «ещё один формат, 16-й по счёту». Любая попытка построить, а тем более, применить конвертор форматов приведёт к игнорированию некоторой частью девелоперских юнитов данного формата. В тех же индивидуумах, в которых странным образом сочетаются осколки разных миров, которые ещё не определились со своей сущностью, процедуры конвертации покажутся полезными. По крайней мере, на первых порах, по мере превращения.

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

Мост между роботами и людьми

Можно придумать плагин к Grunt/Gulp (например, grunt-strip-json-comments, Gulp. ) для очистки файлов от комментриев. Но суть действия сводится к небольшому (до 1 К) регулярному выражению, которое проще написать в Gruntfile.js, чем в него же вписывать ещё один плагин. Более того, такое же выражение нужно и для JS на клиенте, чтобы читать тот же JSON, поэтому от его явного вида мы всё равно не убежим.

Методы для преобразований форматов собраны в объект jsonComm, который работает в среде Javascript. Для решения частных задач не нужен весь объект — не всегда имеет смысл брать в проект все методы. Например с задачей простого удаления комментариев (как в gulp-strip-json-comments) справляется метод, состоящий из одного регулярного выражения (jsonComm.unComment(), до 1 КБ несжатого кода; пример далее; в тестовом разделе проекта jsonComm есть тесты и бенчмарки для оценки корректности и быстродействия), которое даже компилировать не надо, если нет цели применять разные настройки правил.

Настройки могут быть, к примеру, такие. Каким символом отмечать начало комментария? Если в среде чистого JS есть уверенный ответ — «//», то сторонники Пайтона или YAML скажут — «#». Попытки объединить непримиримых приводят к настройкам правил и к конверторам — тем самым, с которых, в том числе, начали. В среде адептов JS нет надобности в настройках, и они выжгут из проекта упоминание о «#». Потому что нельзя тратить 36 микросекуд (микро-) на генерацию регекспа ради лояльности к такой ереси. Лоялисты — тоже выжгут, но удлинят регексп и станут тратить 0.1-0.5 (условно) микросекунд (микро-) уже не на генерацию, а на каждый цикл перекодировки. За это их ненавидят пуритане. Ведь роботы мыслят гораздо быстрее, и им медлительность видится в другом масштабе.

  • просто читать в JS или NodeJS формат jsonComm (с комментариями), удалять из них комментарии и далее верифицировать как обычный JSON в JSON.parse(); то же самое, что делает большинство проектов по добавлению комментариев в JSON. Работает быстро (десятки-сотни мкс).
  • читать не JSON, а файлы JS (с кодом) чтобы из оставшейся части взять некоторые константы как настройки (например, в NodeJS), когда файл JS будет их тоже использовать при своём исполнении в другом месте (на клиенте) — своеобразный шаблон с упрощением структуры конфигурации;
  • как в предыдущем пункте, но уже хочется изменить некоторые настройки после прочтения (например, в Ноде обновить номер сборки или внести настройки конфига), чтобы далее JS на клиенте, ничего не подозревая, использовал их. Это — аналог шаблона на чтение-запись.

Задачи разделяются на 2 практических случая — когда нам не нужно редактировать свой jsonComm, и когда редактировать нужно, при этом оставляя все комментарии. Когда происходит только чтение (это же — случай клиентского AJAX), ограничиваемся единственным методом jsonComm.unComment() c одним регекспом, и далее — JSON.parse().

Случай записи изменённых значений или ключей потребует небольшой процедуры парсинга текстового файла JsonComm (с комментариями, без их удаления) или JS, чтобы точечно изменить требуемое. Манипуляция возможна для файлов «*.js», если коды языка в них не будем трогать скриптами — требуется лишь не ошибаться в записи значений ключей. К необходимым методам добавляется второй: jsonComm.change().

  • получить «валидный» доступ к комментариям jsonComm, переведя их сначала в пары «ключ#»-«комментарий», выбрав основу ключа из той строки, возле которой он найден, а затем, после парсинга из правильного JSON — обрабатывать их далее (например, переводя в другой формат);
  • работать с Yaml напрямую (но теряем признанную браузером/средой JS основу для валидации)
  • взаимное преобразование в Yaml и обратно через выше сделанный валидный JSON;
  • то же для XML; тогда получится кластер из четвёрки языков описания данных, 2 из которых признаны в браузерах и многочисленных вычислительных средах.

Первое же знакомство со способами комментирования создаёт много вопросов — к каким ключам привязвать комментарии до найденной пары, а каким — после? Например, комментарии после разделителя-запятой, но стоящие на той же строке, обычно относятся к предыдущей паре, поэтому на разделитель будет влиять и окончание строки. Второе: многострочные комментарии логически могут относиться к разным смежным парам. Третье: а к чему относятся комментарии в массивах? Их ключи выражены неявно, и логично бы создать рядом лежащий массив. А если он многомерный и с редким заполнением? Четвёртое: комментариев на строке может быть несколько; пара может быть растянута на 3 и более строк.

Весь этот круг не менее надуманных, но реальных проблем потребует достаточно продуманного подхода, чтобы автоматическая конвертация комментариев не приводила к ухудшению читаемости форматов. Поэтому не будем спешить с их изготовлением. Займёмся лучше формальным описанием грамматики jsonComm.

Грамматика jsonComm

Чаще всего встречаются пары в файлах JSON, зписанные на отдельных строчках:

Значение — строка в кавычках или другие термы по всем правилам JSON. Ключ — любая строка, лишь с особым экранированием кавычек внутри себя. Между элементами могут быть пробельные символы, а разделяются пары запятыми или скобками, которые могут стоять где угодно до или после пары, в том числе, на соседних строках.

У нас будет очень похожий формат (jsonComm), с той разницей, что на месте пробельных символов могут быть комментарии 2 типов.

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

Далее, при решении творческой задачи по вопросу того, к какой паре отнести комментарии, расположение разделителя и переносов строк снова будет иметь значение. Для просто удаления комментариев — оказывается, что переносы строк не важны (не следует лишь удалять концевой перенос однострочного комментария).

С учётом сказанного, основная конструкция грамматики jsonComm выглядит так:

После фильтрации выбрасывается всё, что не в скобках, и остаётся всё, что изображено в круглых скобках. С некоторыми особенностями, конечно, которые на этой упрощённой схеме не отображены (пустое значение означает значение-структуру). Схема может пропустить неправильный JSON, может вообще пропустить любой текст, кроме комментариев, например, программу или текст книги. И это хорошо тем, что при валидации, если её делают, JSON всё равно проверяется, а если валидации нет, а текст парсится JS-компилятором, то надобность в удалении комментариев отсутствует, схема в этом режиме не работает.

Похожая, более сложная схема нужна будет для вставления комментариев-значений (функция jsonComm.comm2json()). В ней из jsonComm вида

. ,"some-key":"some-value" //comments_comments . >. 
. "some-key#":"comments_comments", "some-key":"some-value", . >. 

или без строчки с ключом для комментария. Если в области текста, относящейся к паре, встретилось несколько комментариев, всех их копируют в значение «some-key#». Но если комментарий встретился не в районе пары (в массиве, до или после всех скобок), он игнорируется. Все символы комментария приходится преобразовывать в валидные для JSON. Например, табы — в «\t», «\» — в «\\»,….

Как на практике содержать JsonComm?

До сих пор мы могли записать без проблем и плагинов только JSON со всеми оговорками отсутствия комментариев или с присутствием, но в виде значений (или править JS как текстовые файлы, или хранить в БД). Сейчас будем пользоваться изменяемыми (для NodeJS) файлами jsonComm, имеющими расширение *.js.

Выявлены 2 практические ниши применения JsonComm-файлов: на чтение конфигураций, оформленных с комментариями, на обновление конфигураций, и одна академическая — конвертор форматов.

Если файлы нужно только читать (клиентский JS и прочее), читаем их как xhr.responseText в AJAX или как *.js и преобразуем JsonComm в объекты-структуры с валидацией через JSON.parse().

Если файлы нужно модифицировать, то для быстроты работы используем алгоритм поиска и замены по уникальным ключам, не повторяющимся в файле (jsonComm.change()). Тогда не нужно делать дерево разбора, одновременно обходя комментарии (впрочем, это тоже не должно быть медленно, но отдельный сложный однопроходный алгоритм).

Нет проблем добавить пайтоновский стиль однострочных комментариев (#comments_comments). Но тогда не будет работать способ чтения как файла *.js. В коде проекта заложена возможность отключить синтаксис «#» у комментариев (на начальном этапе компиляции регекспа).

Простые случаи, когда это нужно:

* В сборщике проекта на Grunt/Gulp/… вычисляем новый номер версии и запоминаем его в тот же файл конфигураци.

* там же, в сборщике, создаём константы проекта на основе других параметров сборки и пишем их как параметры для JS.

Чуть более сложно, клиентский JS тоже может приобрести функцию записи таких файлов, через отправку результата на сервер. Это даст ещё больше вариантов использования (сборочная панель на клиенте), оставляя комментарии в файле. Для этого ему надо модифицировать и отправить строку (образ многострочного файла) на сервер, а там её записать в файл (конечно, с решением вопросов безопасности).

Реализация

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

Выкусывание комментариев

Преобразователь фактически работает как цикл по строкам, методично выкусывая комментарии и пропуская допустимые фрагменты JSON. На его базе несложно построить и распознаватели текста комментариев, чтобы их сохранять в особые ключи-значения. Таким способом, мы допускаем комментарии для дальнейших операций, но не для того, чтобы «нарушить совместимость» (при желании — всегда можно), а чтобы код с комментарием был более удобной записью хуже читаемого выражения из 2 пар «ключ-комментарий» и «ключ-значение».

 "ключ_": "комментарий", "ключ": "значение", 
 "ключ": "значение" //комментарий 

Решение выполняет также задачу по распределению ответственности за валидность кода. Всё, что относится к комментариям, контролируется визуально и с подсветкой синтаксиса в IDE разработчиком. Правильность остального JSON разбирает стандартный парсер JSON.parse().

Начнём с простого. Как приблизительно работает парсинг на регекспах? Попробуем удалять концевые комментарии. (Код не используется далее, он — только для примера.)

Для понимания, как оно устроено, обратим внимание на функциональные части:

(^|\r?\n) — захватывающие скобки для отображения предыдущего переноса строки.
Следующая за ним скобка и её пара — . [^\/»\r\n]*?) — вторые используемые для копирования захватывающие скобки.
«(\\»|[^»\r\n])*» — ключ или строка в кавычках; если кавычек нет — далее ищется альтернатива из просто

\s*\/\*\*\/|\s*\/\*([\s\S]?(?!\*\/))+. — парсер многострочного комментария.
\/\/[^\r\n]* — парсер однострочного комментария до конца строки.

С выкусыванием комментариев в конце строки у этого несложного выражения — всё отлично. Хуже дело — с выкусыванием комментариев со звёздочкой между ключами и значениями. Можно пренебречь и не писать таких комментариев. Тем более, что у «конкурента» YAML имеются только концевые. Но, имея функциональные части, уже можно построить более сложное выражение, чтобы не накладывать таких ограничений. При этом придётся не просто оставлять «всё до комментария в строке», но и между ними — усложняются оставляемые фрагменты. Фактически, это — вся jsonComm.unComment(jsonCommString). Именно эту строчку можно копировать в Gruntfile.js вместо подключения модуля, чтобы очистить строку JSON от комментариев.

Тут широко используются незахватывающие скобки, чтобы оставить только захватывающие, для дальнейшей простоты второго аргумента в .replace(). (Подсказка-лайфхак: такие строки лучше всего читать в редакторе, имеющем выделение с подсветкой и выделение парных скобок, напр. от jetbrains.)

Для преобразования строки jsonComm в JSON достаточно этого выражения. Как показывают бенчмарки, это преобразование достаточно хорошо летает — время выполнения — десятки-сотни микросекунд на страницу (сильно зависит от сложности разбора). Хуже будет дело с академическим скриптом для вывода комментариев в JSON, когда в replace() понадобится функция.

Так, мы получили валидный JSON, решив первую часть задачи — прочитать jsonComm.

Затем, парсинг валидности оставшегося кода, как задумано, возлагается на стандартную JSON.parse(), после чего получаем структуру данных в JS. Следующая часть задачи — кое-что автоматически подредактировать в исходном тексте, оставив комментарии на местах.

Вставка некоторых обновлённых значений

Созданное отделение данных от комментариев прекрасно используется для поиска по части текста, не включающей комментарии. Соответственно, правка значений тоже ведётся по шаблону пары «ключ-значение» и не попадает в области комментариев, сколь бы похожим на них текст там не был.

  • в тексте jsonComm ищутся уникальные ключи (в кавычках). Копии ключей в комментариях игнорируются. Для одинаковых имён ключей из разных веток структуры — изменится первое и создастся некритическая ошибка в отчёте.
  • цепочки ключей не анализируются (для простоты и скорости поиска)
  • править пары, записанные не с начала строки — без проблем, потому что распознаватель ориентирован на скобки и запятые как маркеры пар. Но для удобства чтения и контроля лучше записывать изменяемые пары с начала строки.
  • удалить пару нельзя; самое большее — заменить на null или «». Как следствие, редактируемые ключи продолжают работать при любых автоматических изменениях, исчезнуть могут только при ручных.
  • изменяются только примитивы; массивы и структуры остаются на месте. Попытка изменить структуру приводит к нефатальной ошибке (пишется в лог ошибок).
  • изменение (переименование) ключей возможно, хотя противоречит человеко-ориентированному подходу и может привести к нарушению цепочки автоматических изменений, которое будет сложно отлаживать. Этим механизмом, возможно, удобно менять значения местами (перестановкой не значений, а ключей).

Такая схема не отменяет правок сериализованных структур, но этот путь — уже не для людей. В настоящем виде правки рассчитаны на смену данных без смены структур, описанных в файлах jsonComm.

Тогда всё очень просто и быстро работает: в исходном файле отыскиваются единственные образцы вида «ключ» (в двойных кавычках), после чего скриптом имеем доступ к значению — строке, числу или логическому.

Изменение значений выполняется функцией jsonComm.change(h), где h — одноранговый набор пар «ключ»-«новое значение». (В крайнем случае — «ключ»- .)

Что интересно, для .change() файл (строка) не обязан быть приводимым к JSON и к нему не обязательно пытаться применять .unComment(). Это может быть JS-файл, который сначала выполнится (например, только для того, чтобы прочитать из него текущие значения настроек вместо чтения JSON), а затем к нему применится модификация значений. Т.е. .change() — это тоже достаточно автономная функция в сборке.

Академические задачи: смена формата файла

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

● получить комментарии в JSON (функция преобразования — jsonComm.comm2json),
● работа с YAML,
● двусторонние преобразования «jsonComm — YAML».
● то же для «jsonComm — XML».

В силу их невостребованности, для последних поставлены функции-заглушки, и только первая (comm2json) сделана ради академического интереса, для ответа на вопрос — насколько медленнее это будет. Приходится делать replace, в котором захватить параметры комментариев через функцию, а затем символ за символом проверять комментарии и преобразовывать имеющиеся в допустимые для JSON строковые символы.

Краткий ответ — становится медленее в 30 раз и тоже сильно зависит от сложности разбора, количества комментариев. Тестовый пример уложился примерно в 1 миллисекунду, но реальность легко сделает жизнь сложнее. Зато мы получаем первый инструмент для «полностью валидного» последующего преобразования в другие форматы данных (Yaml, XML).

Результаты теста

Посмотрим, как на субноуте средней руки эти 3 функции справляются с небольшим контрольным jsonComm, имеющим всевозможные (конечно, не все) сложности для парсинга. На скриншотах — исходные данные, но в проекте можно найти код этих данных и провести тесты на своём компьютере и браузере. На Firefox 34 (jsonComm.unComment):

На Хроме в этом тесте — вдвое лучшие результаты.

Как выполняется парсинг комментариев (jsonComm.comm2json)? Здесь замена работает через replace(,function).

У Хрома здесь и далее — сопоставимые результаты. Это значит, что его специально оптимизировали на замены строк (.replace()) без функций. В любом случае, первый тест — очень быстро, этот — умеренно.

Строчки форматируются неровно, но здесь это не имеет большого значения, потому что предназначение функции — получить валидный JSON с валидными комментариями. Показать красиво можно и стандартными средствами (.stringify), как показано далее в тесте (скриншот не приведён).

Как изменяются значения ключей (jsonComm.change)? Здесь форма и красивость результата — уже на первом месте, потому что предназначено для чтения конфигов людьми. Правила замены показаны в объекте jCommChanges.

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

Чем больше изменений требуется сделать на том же участке jsonComm, тем медленнее работает скрипт (что логично). Исходя из приведённых объёмов, можно оценить, какой будет скорость на больших JSON. В общем, скорость — достаточно хорошая, если даже для правок идёт речь о единицах миллисекунд.

Как упоминалось, первая функция с компилированным регекспом в несжатом виде занимает менее 1 КБ. Минифицированные первые 3 функции с выбрасыванием нереализованных остальных заглушек — 2.1 КБ (src/jsonComm.min.js).

Новые вклады в проект

Что хотелось бы увидеть в проекте от новых контрибьюторов?

1) Кроме академических разделов, есть элементы парсинга, которые не помешало бы оттачивать в коде, чтобы выделять комментарии точнее (как показывает тестовый вывод в jsonCommTest.htm под заголовком «jsonWithComm», выходная строка .comm2json() не очень совершенна). Впрочем, в JSON.stringify уже есть способы вывести строку красивее, как показывает следующая строка лога под заголовком «jsObjWithComm».

2) Интересно было бы сравнение скорости со скриптовым парсингом.

3) Не отмечаются ошибки неуникального парсинга. Не обрабатываются JSON в виде одного примитива.

4) Плагины для Grunt, Gulp,….

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

Комментирование кода: хорошие, плохие и отвратительные комментарии

«Хороший код — это самодокументируемый код». Вы слышали эту фразу раньше? Я тоже. Более чем за 20 лет написания кода я слышал эту фразу чаще других. Это уже клише.

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

В этой статье мы рассмотрим хорошие, плохие и отвратительные примеры комментирования в коде.

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

Документационные комментарии

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

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

Посмотрите на пример кода из Lodash — популярной библиотеки для JavaScript:

/** * Creates an object composed of keys generated from the results of running * each element of `collection` thru `iteratee`. The corresponding value of * each key is the number of times the key was returned by `iteratee`. The * iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 0.5.0 * @category Collection * @param collection The collection to iterate over. * @param [iteratee=_.identity] The iteratee to transform keys. * @returns Returns the composed aggregate object. * @example * * _.countBy([6.1, 4.2, 6.3], Math.floor); * // => < '4': 1, '6': 2 >* * // The `_.property` iteratee shorthand. * _.countBy(['one', 'two', 'three'], 'length'); * // => < '3': 2, '5': 1 >*/ var countBy = createAggregator(function(result, value, key) < if (hasOwnProperty.call(result, key)) < ++result[key]; >else < baseAssignValue(result, key, 1); >>); 

Если вы сравните эти комментарии с онлайн-документацией, то увидите, что они одинаковы. При написании документационных комментариев убедитесь, что они соответствуют общепринятому стандарту и что они отличаются от уточняющих и поясняющих комментариев в самом коде. Некоторые популярные инструменты и стандарты включают использование JSDoc для JavaScript, DocFx для .Net и JavaDoc для Java.

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

Поясняющие комментарии

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

Зачастую уточняющий комментарий к вашему коду является его отражением. По пояснению можно судить нагружен ваш код или нет. Следует пытаться удалять пояснения в коде, упрощая его, ведь «хороший код — самодокументированный код».

Приведу пример плохого, но забавного пояснения:

/* * Replaces with spaces * the braces in cases * where braces in places * cause stasis. **/ $str = str_replace(array("")," ",$str); 

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

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

Вам действительно хочется приукрасить рифмой свой плохой код, чтобы кодеры ухмыльнулись и проигнорировали его, двигаясь дальше?

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

/* Устанавливает значение 32 для переменной age */ int age = 32; 

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

Обычно это происходит, когда вам нужно добавить контекст к неинтуитивному решению.
Вот хороший пример из фреймворка Lodash:

function addSetEntry(set, value) < /* Не возвращать `set.add`, потому что эта цепочка вызовов не сработает в IE 11. */ set.add(value); return set; > 

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

А иногда тем самым «более умным» кодером можете оказаться вы сами. Поэтому в таких случаях лучше оставлять комментарии к коду, чтобы в будущем сэкономить своё и чужое время и нервы.

Комментарий снизу полностью отражает суть мысли выше:

/** Уважаемый разработчик: Как только ты прекратишь пытаться «оптимизировать» этот код и поймёшь, какую ошибку ты допустил взявшись за это дело, пожалуйста, увеличь номер на счётчике ниже для следующего разработчика: количество_часов_потрачено_впустую_здесь = 42 **/ 

Опять же, комментарий сверху содержит больше юмора, чем пользы. Вам СЛЕДУЕТ оставлять комментарии, предупреждающие других от поиска какого-либо «лучшего решения», если вы сами уже пытались это сделать, но ничего хорошего из этого не вышло. В комментарии следует указать, какое решение вы пытались найти и почему вы решили, что оно не подходит в данной ситуации или не работает.

/* не используйте глобальную функцию isFinite(), потому что она возвращает true для нулевых значений */ Number.isFinite(value) 

Отвратительные комментарии

Мы уже узнали, что такое хорошие и плохие комментарии к коду. Теперь пришло время ознакомиться с отвратительными комментариями.

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

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

/* Этот код — дно, я знаю. Можешь изучать его дальше и назвать меня тупицей. */ 
/* Класс, использующийся для обходного решения — Richard being a f***ing idiot */ 

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

Уважайте себя и других разработчиков и не допускайте подобных комментариев в своём коде.

Как разрешить пользователям публиковать анонимные комментарии в WordPress

Недавно один из наших пользователей спросил, можно ли сделать так, чтобы пользователи оставляли комментарии в WordPress анонимно. По умолчанию пользователи не могут оставлять комментарии в WordPress без ввода своего имени и почтового адреса в форме комментирования. В этой статье мы покажем вам, как разрешить пользователям оставлять анонимные комментарии в WordPress. Мы также покажем, как скрыть поля с именем и почтовым адресом в форме комментариев WordPress.

Псевдоним: идеальное решение

Самый лучший способ разрешить анонимные комментарии в WordPress, снизив при этом объемы спама – подтолкнуть пользователей к применению псевдонимов или никнеймов вместо своих реальных имен.

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

Вы можете отметить это в своей политике комментирования и поместить специальную ссылку на нее над формой комментариев.

В то время как это будет идеальным (и рекомендуемым нами) решением, существуют и другие варианты, позволяющие реализовать анонимность. Однако стоит сразу сказать, что чем выше добавленная вами анонимность, тем больше спама вы будете получать.

Делаем поля ввода имени и почтового адреса необязательными

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

Для начала вам понадобится перейти в раздел Параметры – Обсуждение и снять галочку с поля «Автор комментария должен заполнить поля с именем и почтовым адресом». Теперь вам нужно сохранить изменения, и вы сможете принимать комментарии без имени и почтового адреса.

anonymous-comments

Однако простое снятие флажка не помогло бы вашим пользователям понять, что они могут оставлять комментарии без заполнения данных полей. Вы можете продемонстрировать это путем текста, который укажет, что данные поля являются дополнительными. Мы также рекомендуем удалить поле с URL веб-сайта, чтобы воспрепятствовать спаму. Сделать это можно путем некоторой модификации вашей формы. Просто вставьте следующий код в файл functions.php или в отдельный функциональный плагин:

function wpb_alter_comment_form_fields($fields) < // Modify Name Field and show that it's Optional $fields['author'] = '

' . __( 'Name (Optional)' ) . ' ' . ( $req ? '

'; // Modify Email Field and show that it's Optional $fields['email'] = '

' . __( 'Email (Optional)', 'twentythirteen' ) . ' ' . ( $req ? '

'; // This line removes the website URL from comment form. $fields['url'] = ''; return $fields; > add_filter('comment_form_default_fields', 'wpb_alter_comment_form_fields');

Данный код просто добавляет текст (Optional) рядом с полями имени и почтового адреса в форме комментирования. Также код позволяет удалить поле URL из формы. Если вы хотите оставить поле URL, то в таком случае удалите соответствующую строку из кода. Вот как будет выглядеть ваша форма комментирования после изменений:

name-email-optional

Как полностью удалить поля с именем и почтовым адресом из формы комментирования

Для тех пользователей, которые хотят удалить поля с именем и почтовым адресом из формы комментирования, ниже представлен фрагмент кода, позволяющий это сделать. Поместите данный код в файл functions.php вашей темы:

function wpb_alter_comment_form_fields($fields) < unset($fields['author']); unset($fields['email']); unset($fields['url']); return $fields; >add_filter('comment_form_default_fields', 'wpb_alter_comment_form_fields');

Если ваша форма комментирования отображает текст «Your email address will not be published» («Ваш почтовый адрес не будет опубликован»), то в таком случае вы можете скрыть его путем редактирования файла comments.php. Найдите тег и замените его следующим кодом:

Если вы не можете найти comment_form, то вы все еще можете скрыть данный текст путем добавления следующего CSS-кода в файл style.css вашей темы:

.comment-notes

Вот как будет выглядеть форма комментирования без полей с именем, почтовым адресом и URL:

noname-email-comment

Предостережение по поводу анонимных комментариев

Обратите внимание, что без полей с именем и почтовым адресом ваша форма комментариев будет привлекать большое количество спама. В то время как Akismet и Sucuri способны блокировать некоторые нежелательные IP, мы настоятельно рекомендуем вам поставить CAPTCHA-верификацию для предотвращения основной массы спама.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *