Комментарии 108
К примеру мне нравится, когда комментарии есть напротив каждой строки также, как и краткое описание класса до его начала.
int calcSum(int[] elements) // Метода для подсчета суммы элементов в массиве
{
int result = 0; // Объявим результирующую переменную result
for (int i = 0; i < elements.Length; i++) // Для каждого i от 0 до длины массива elements
{
result += elements[i]; // Прибавим к result i-тое значение массива elements
}
return result; // Возвратим значение result
}
Хотя бы потому, что конкретные изменения по таску найти сложновато.
Для этого для автоформата legacy обычно делают отдельный коммит.
Это полбеды. Когда еще заботливый форматтер переставляет декларации в файле в "правильном" порядке, какие-либо изменения вообще отследить невозможно, ломается даже "Show Git history for method"
Отсутствие комментов, один вид кавычек, необходимость эти кавычки ставить в ключе, отсутствие trailing comma (это когда нельзя делать так: [1, 2, 3,]
), скудность типов. Это из того, что сразу вспомнилось.
P.S. Вы, возможно, хотели сказать, что JSON не слишком удобен для написания его человеком — что, отчасти, правда, но… наши недостатки — продолжение наших достоинств. Там где удобство чтения/разбора важнее удобства напиcания (то есть почти везде) всё, что вы перечислили — достоинства.
Отсутствие комментов
1. Комментарии свели бы всю красоту лаконичности формата к нулю.
2. Формат является «обрезанным» способом записи объектов в JS и предназначается скорее для общения техники, нежели людей.
3. В JS комментарии были.
4. Пришлось бы изобретать еще одну форму записи.
5. Привело бы к усложнению (и замедлению) парсеров.
6. Поскольку формат свободный (в том смысле, что нет аналога схем xsd и dtd), то ничто не мешает добавить «лишние» данные в качестве комментариев.
один вид кавычек
Единообразие — прекрасно! Кстати, в статье обсуждался этот вопрос, в абзаце про legacy.
необходимость эти кавычки ставить в ключе
Скорее, для совместимости с JS, чтобы не ломать голову ни человеку, ни машине, как интерпретировать ключ.
отсутствие trailing comma
Опять же, для упрощения интерпретации, обход возможных неоднозначностей (не понимать ли запись ",]" как еще один пустой элемент?)
скудность типов
А зачем в данных разнообразие типов? Не думаю, что в JSON очень уж нужно различать знаковые и беззнаковые целые, например.
Т.е. JSON как формат, не слишком нуждающийся в упаковке (скажем, сравните с избыточностью XML) прекрасно справляется со своей функцией краткой записи данных и простоты разбора\генерации, не потеряв при этом в читабельности. Это как раз то, почему он так популярен, вовсе не «Совершенно непригодный для промышленной разработки академический стандарт».
Кроме того, он совсем не мешает жить другим не менее популярным форматам, таким, как HAML\YAML, например. Тем не менее, и они имеют свои преимущества и свои недостатки, а потому и используются совсем не там, где JSON, там бы они не подошли.
Ну и наконец, популярность != засилие, не надо, пожалуйста, вот этого " И как будто так и надо. Пофигизм и безволие."
<html>
<body>
<script type="text/javascript">
//<!--
document.write("Hello World!");
//-->
</script>
</body>
</html>
А ведь недавно куча сайтов так выглядели — и в книжках именно так рекомендовали писать.
Ещё раз: либо комментариев у вас в стандарте и в соответствующих документах нет (а тогда и вырезать нечего), либо они есть — а тогда их под что-нибудь важное приспособят (и тогда они, по большому счёту, перестанут быть комментариями — но мы вроде о практике тут говорим, а не об академических изысках).
Отсутствие комментариев в JSON — это очень важное практичнеское преимущество этого стандарта. Если конкретно в вашей программе вы хотите-таки иметь комментарии — ну так разрешите их, это-то как раз несложно.
Но таки именно то, что куча парсеров не признают комментариев и гарантирует, что всевозможные шаблонизаторы (где комментарии могут быть как раз вполне уместны) вырежут комментарии до того, как файл превратится в конечный JSON, который вы будете отдавать кому-то ещё и «в траффик» они не пойдут — что может быть практичнее?
Кстати о практичеости. Заметьте, что JSON пришёл в мир, где всё уже было «предрешено»: «все идут в XML, всё идёт в XML, везде будет XML». В 2001м, когда JSON появился, уже были и XML-RPC/SOAP и XHTML и куча других вещей. И там было и «разнообразие» и «валидация» и много всего другого. И даже комментарии, кстати.
А потом появился JSON — и прочие языки обмена данными стали почему-то менее популярны. Можно долго спорить — почему это произошло, но говорить о том, что это «академический стандарт» — это уже Оруэлл: JSON был «слеплен из того, что было» и решал практические задачи — какая ж тут академичность?
Вот «хотелки» не решающие ровным счётом ни одной задачи и исходящие из того, что люди будут обладать свободой и при этом будут соблюдать стандарты (ага, щаз: это же люди, а не ангелы) — вот это как раз «академичный подход», не имеющий к практике никакого отношения.
Потому что у вас получается, что если Google переводит GData в 2005м с XML на JSON, то это происходит потому, что JSON в 2016м используются «буквально везде». У нас тут не Океания пока и логика «Океания всегда воевала с Остазией» не работает: всё-таки причина появляется перед следствием. Если в 2005м GData начинает поддерживать JSON — то это происходит потому, что он был удобнее, чем альтернатива, а не потому, что в 2016 JSON используется «буквально везде».
P.S. Используется «буквально везде» — кстати отличный пример практического довода. И хотя он не перешибает всех других доводов (иначе бы и на JSON никто переходить не стал и переход на IPv6 не происходил бы), но он — действительно весьма весом. Когда вы приходите со своими идеями «а давайте миллионы компаний потратят миллиарды долларов, чтобы я смог получить экономию в три секунды и десять центов», то ваши предложения отвергаются не из-за того, что кругом «пофигизм и безволие», а просто потому что людим кругом умеют считать деньги и время. Чего вы, похоже, babylon делать не научился пока.
P.P.S. Кстати форматы далеко не все остаются в неизменном состоянии. В качестве примера — посмотрите на Markdown и его превращение в CommonMark. Вот там совместимость — не была основным достоинством формата и потому расширения было делать проще. Однако в конце-концов это изрядно всех «достало» и стандарт всё же появился. Посмотрим — приживётся ли. А у JSON'а — его простота, лаконичность, неизменность и совместимость (сначала с JavaScript/ActionScript, сейчас — с сотнями, если не тысячами, парсеров) — это основное достоинство. Неудивительно, что идеи отказаться от него в угоду секундной экономии отвергаются! Где вы тут видите «академичность»?
Попробуйте написать проект, где вам нужны даты/timestamp, которых в json нет. Скорее всего ваше мнение изменится довольно быстро.
Целые тут ни при чем совершенно — речь про то, что те типы, которых в языке нет, очень сложно однозначно восстановить при разборе, потому что я JSON нет и метаданных для типа, в том числе. Т.е. без схемы вы не можете понять, это вам пришло число, или дата в виде количества миллисекунд от начала эпохи, пришла строка или опять же дата в формате ISO 8601.
There are a two kind of peopleПростите, это на каком языке?
Возможно, картинка была подготовлена рано утром или поздно вечером. Я тут в обед прочитал, что я написал рано утром на форуме — так у меня там тоже возникли вопросы к себе, насчет того, является ли русский язык мне родным или нет… Было стыдно.
if cond: return
if (cond) return;
и
return if cond;
if (logger.isLoggable(Level.DEBUG))
// level.debug("someDebugMsg");
doSomethingValuable();
Собственно, когда система вышла в production и настройки логгинга были изменены, баг внезапно и вылез.
Что касается конкретно Вашего примера — тут в целом ок, т.к. условие и действие в одну строку.
И вы реально предпочитаете вместо чуть другого стиля кода писать дополнительные тесы дополнительными тесты?
подразумевается, что если это действительно valuable, то оно должно быть покрыто хоть каким-нибудь (unit/integration/acceptance) тестом
Правила без исключений лучше работают.
Ставить фигурные скобки в однострочных выражениях даже в ГОСТ прописано. Знаете почему? ;)
if(cond)
{
return;
}
Хорошо, когда можно сделать go fmt
и никаких споров :)
И Ctrl + Alt + Shit + L в JetBrains IDE с попутным тыканьем новичков в доки по PSR (в стане PHP разработчиков), например.
Наверное go и php (современный) — это единственные языки, где никогда не возникает споров по поводу кодстайла.
Вопрос не верный, не "зачем", а "почему". Потому что PSR основан на самых популярных практиках самых популярных продуктов. Вот и весь ответ, никакого смыслового значения "зачем" в самом стандарте нет. Взяли и основали стандарт на том, что используют большинство.
Если искать смысл в самих корнях, то подобные практики пошли, я почти уверен, из миров java, haxe, c++ и прочих. Где подобное является стандартными вещами (ну в C\C++ несколько стандартов, так что моё утверждение на счёт подобной практики в этом языке лишь частично верное).
Размышления на тему: Положа руку на сердце, может это просто привычка использовать именно этот стандарт во всех языках, которые использовал (haxe, java, js\es, sass, less, php), но мне кажется что подобное лучше выглядит, нежели размазывание одного метода на 100500 строк. "Воздух" добавляется за счёт переносов строк, а законченное по смыслу логическое выражение, включающее этот самый "else" более компактно и лучше бросается в глаза, нежели если скобки переносить на новую строчку. Фиг знает, споры о кодстайле могут продолжаться вечность и "лучшего" всё равно не найти.
А) 10 голосов за
if () {
...
} else {
...
}
Б) 6 голосов за
if () {
...
}
else {
...
}
Так что да, большинство, но очень не хватает их обоснований. По каким причинам этот голос. Потому что у меня есть несколько обоснований относительно варианта Б и слабые обоснования для А.
Есть условный оператор, есть операторы цикла, есть выбор по ключу, есть блок.
Вы же можете написать
for (...)
;
А можете в теле использовать не один оператор action, а блок.
Т.е. получается такая иерархия: лексемы -> выражения -> блоки -> конструкции.
Например, КиР:
3.1 Statements and Blocks…
Braces { and } are used to group declarations and statements together into a compound statement, or block, so...There is no semicolon after the right brace that ends a block.
3.2 If-Else
The if-else statement is used to express decisions. Formally the syntax is
if (expression)
statement1
else
statement2
where the else part is optional.
if (...)
{
...
}
else
{
...
}
Мне лично не такой вариант не нравится (слишком много места пропадает зря из-за чего в GNU проектах любят не использовать фигурные скобки для однострочных выражений — и потом ясно, чем это кончается), но определённая логика тут есть.
Вариант же с «else {» — ужасен просто потому что у вас оказывается две отдельные, никак не связанные друг с другом конструкци: «if» и «else».
Вот «else { blah-blah-blah }» как прикажете понимать? Это вообще что такое? Это куда? Это зачем? Как так вообще можно писать???
Я имею ввиду, что каждый следующий case не является продолжением другого, и один case может существовать без предыдущего. else в свою очередь не может существовать без предыдущего блока.
Цепочка if / elseif / elseif / else похожа на оператор switch, и elseif там тоже не связаны. case не может существовать без switch, catch не может существовать без try, else не может существовать без if.
PS: Писал так в одном проекте, когда ветки if идут отдельными блоками. Вполне нормально смотрится, код в блоках не сливается с предыдущими, особенно если условия длинные.
Тогда и try / catch надо отдельными блоками писать, потому что там catch не связаны между собой.Связаны. Если один оператор
catch
сработал, то другой — уже ничего перехватить не может. Логически — это цепочка обработчиков (хотя внутри, конечно, компилятор может оптимизировать).Цепочка if / elseif / elseif / else похожа на оператор switch, и elseif там тоже не связаны.Связаны — тем же самым способом. Нельзя одну ветку рассматривать в отрыве от других.
case не может существовать без switch
Case
и switch
— это просто "goto
под прикрытием". Он может скакать на любую глубину вложенности (правда не может мимо конструкторов и «наверх»), иерархии меток никакой нету. if
/elseif
/else
и try
/catch
— устроены совсем не так.Как вы предлагаете скобки в чём-то типа следующего расставлять:
switch (i % 8) while (i > 0) {
case 0: x += a[ i-- ];
case 7: x += a[ i-- ];
case 5: x += a[ i-- ];
case 4: x += a[ i-- ];
case 3: x += a[ i-- ];
case 2: x += a[ i-- ];
case 1: x += a[ i-- ];
}
В случае же с if'ом у вас есть две ветки, которые очевидным образом связаны между собой.
Если у вас блок — отдельная сущность
Так не у меня, так определяется стандартом, нет?
О, оказывается, самый логичный и верный на мой взгляд вариант имеет имя — GNU стандарт. Спасибо!
из-за чего в GNU проектах любят не использовать фигурные скобки для однострочных выражений
Ох, и тут совпадение.
Я бы сказал, что это очень старомодный стандарт, потому что легкочитаем без подсветки, в монохроме/на бумаге.
Так не у меня, так определяется стандартом, нет?Ну так стандарт и в выражении
a = b + c;
несколько сущностей выделяет. Это не значит, что нужно в пять строк это писать.Я бы сказал, что это очень старомодный стандарт, потому что легкочитаем без подсветки, в монохроме/на бумаге.Угу — вот только часто получается, что читается и работает — программа по разному. Это — очень большая проблема.
P.S. Вообще, конечно, очень жаль что на проблему, которая, вообще-то, яйца выделенного не стоит, мы тратим столько времени. Причём забавно что в языках типа Make, которые, являются, в других отношениях, весьма убогими
этой
проблемы нет. Естественная расстановка отступов в блоке ifeq
/else ifeq
else/ — существует только одна, а споров о сущности «блоков» нету потому что никаких «блоков» нету. Это одна из вещей, которые в C/C++ сделаны отвратительно — но при этом, почему-то, это кривое и неудобное решение копируется везде и всюду…Ну так стандарт и в выражении a = b + c; несколько сущностей выделяет. Это не значит, что нужно в пять строк это писать.
Это натяжка, ну да ладно.
Угу — вот только часто получается, что читается и работает — программа по разному. Это — очень большая проблема.
В случае с
if <>
{
}
else
{
}
Исполняется так, как читается.
Вообще, конечно, очень жаль что на проблему, которая, вообще-то, яйца выделенного не стоит, мы тратим столько времени
Я просто порадовался, что такой стандарт есть, только и всего.
Это одна из вещей, которые в C/C++ сделаны отвратительно — но при этом, почему-то, это кривое и неудобное решение копируется везде и всюду…
В Паскале аналогично, только в силу обозначения составного оператора(блока) словами, споров вполовину меньше.
В случае сКак я уже сказал — этот стандарт мне не нравится, но я его понимаю. А вот
if <>
{
}
else
{
}
Исполняется так, как читается.
if <...> {
...
}
else {
...
}
я просто не понимаю откуда может взяться и кому может нравится. Выглядит так, как если бы if
был отдельно и else
— отдельно. И вот этого я не понимаю. «Отдельно живущий блок» — это ещё туда-сюда, но «отдельно живущий» else
— это какая-то очень странная сущность.Впрочем в проектах, его использующих, жить всё равно легче. Мне, в общем, всё равно как стоят пробелы (потому что почему-то тот вариант, который нравится мне редко нравится кому-либо ещё) и я ненавижу Style Guide'ы (по той же причине) — но спокойно отношусь к вещам подобным
go fmt
.Просто потому что когда мне дают
go fmt
— то мой код делают хуже понимаемым лично мной, но взамен экономят немножко моё время. Это я ещё могу терпеть. Но когда мне навязывают какой-то Style Guide и не дают инструмента, то это значит, что меня заставляют тратить время и делать работу, которая мне же и сделает хуже! Это — уже перебор.Это абсолютно верная позиция, когда вы над кодом сидите один и никому не показываете. Но когда в команде больше 3х человек — не думаете ли, что подобные принципы немного эгоистичны? И что лучше использовать один стандарт, пнуть себя в мягкое место и переучиться (это тяжело, я прекрасно это понимаю, у каждого есть подобный опыт), который доступен и привычен большинству, нежели свой супер-удобный вариант, доступный только для таких, бесспорно замечательных разработчиков, как вы? =)
Первое — автомат типа
go fmt
способен проверить (а зачастую и исправить), второе — будет постоянным источником споров и разногласий независимо ни от чего.Ну меня просто смутила фраза "ненавижу всяческие стайлгайды", я рад что ошибся в вашей позиции. А стайлгайды, по-моему наоборот хорошо когда есть, главное чтобы он был один. Нравится ли он или нет — не важно, главное чтобы один, иначе холивары и всё такое. Короче, почти что как сейчас в комментах к посту.
return
vs return;
приведение к стандарту просто надо выполнять отдельным коммитом imho.
Я обычно следую правилу, что если приходится править старый код, то форматирование меняю только на уровне отдельных методов, причем если в них изменилась довольно большая доля кода. Т.е. если поправили пару строчек в большом методе — оставляем стиль прежний. Если поправили треть метода или больше — тогда уже можно переформатировать весь метод.
git filter-branch
, чтобы привести всю историю к единому стандарту. Заодно избавились от части конфликтов при слиянии.Минус, конечно, что история меняется, но конкретно в плане исправления стиля — вроде и не страшно.
Описывать всё и вся не вижу смысла — всегда проще договориться и найти пример в существующем коде. Чем большее количество человек работают над одной базой кода, тем строже должен быть стандарт.
не важно какое соглашение о стиле кодирования вы примите, важно чтобы вы его приняли!
PS: Как славно что в PHP есть PSR =) Сколько безсмыленных холиваров этим предотвращено!
Очевидно ли на первый взгляд, что оба блока делают одно и то же?
Не хочу показаться занудой, но shift же изменяет массив.
ИМХО Не так уж важно как пробелы и переводы строк расставлять. Не вижу даже ничего суперстрашного если разные файлы форматированы по разному — все равно все будет понятно. Лучше концентрироваться на сути, например для плюсов: заставлять использовать RAII, создавать новые типы исключений вместо использования системных, порядок инклюдов, запрет using namespace в хедерах, запрет блокирующих вызовов и т.д.
Кривой/неконсистентный стиль можно быстро и массово поправить каким-нибудь clang-format, а затем сделать проверку стиля в CI. Все. Проблема решена. Зачем ей посвящать столько времени и сил в холиварах?
Куда сложнее читать и фиксить спагетти код функции на 400 строк с однобуквенными переменными без комментариев и кучей хаков. Который еще и не работает если пойти чуть в сторону. Вот за что нужно убивать.
Важно наверное стандарты безопастности, а остальное уже на любителя.
1) утвердить какой-то любой стиль для коммитов.
2) наладить процесс так, чтобы участник после взятия мог запустить настроенный под себя beautifier.
3) а перед коммитом запустить beautifier обратно на утверждённый стиль (можно даже запретить коммит, если на сервере beautifier вернул код «ошибки»)
4) при этом опасные преобразования, типа уничтожения скобок, запретить по всей команде.
Нужен ли стандарт разработки?