Pull to refresh

Comments 217

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

да, но, скажем от одного пробела мозг не взорвется.

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

Насчет джунов — это важная мысль. Дополню статью.

Ну почему же сразу джуны?
Как только дело доходит до отладки и надо поставить брекпоинт — а его, внезапно, все могут ставить на строчку, и "не только лишь все" на отдельные операторы — так и приходит озарение.
Порой и сложное выражение в условии с той же целью хорошо разбить на несколько строк.

Ваш пример с брейкпоинтом. В строке $x=1; $y=1; $z=1; нечего отлаживать. А если вдруг в каком-то сложном случае это будет нужно, ну поставил там перевод строки, да и всё.

Речь как раз о том, чтобы НЕ ЗАНИМАТЬСЯ отдельно вставкой переводов строки. Пусть они сразу там стоят. А для этого лучше, если это правило будет в код-стайле.
Вы же пишете статью "в общем", не указывая язык программирования. Поэтому кроме python/php/javascript это может быть и С/С++, где вставка перевода строки подразумевает последующий билд и перезапуск. И если на локальной машине в любимой IDE это просто, как "два пальца", то на удалённом хосте у клиента, где есть только собранный бинарь и отладочные символы, это уже легко превращается в приключение. Поэтому — лучше заранее. Компилятор пробелы всё равно не считает, отладочные символы с информацией о дополнительных строчках всё равно нужны лишь для отладки — но если это недосмотрели, то раунд ребилда/редеплоя не очень обрадует.

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

Но в каких-то проектах оно может быть лишним

Конечно!
В Вашем примере могу предположить, что это php.
Но, например, в C++ (да может быть и в том же php) в случае, если x,y,z — это не 'new shiny' переменные, а какие-нибудь ссылки на другие сущности, которые через грязные хаки в этот момент кто-то меняет из других потоков — всегда приятно, когда оно оказывается разбитым по строчкам. Если уж код сам по себе настолько плох, но хоть тут есть подстеленная охапка соломки — оно уже поддерживает охоту жить ).

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

Для нужных правил это ок. А для ненужных — непонятно зачем они вообще существуют

UFO just landed and posted this here
Хорошо нам на Джаве.
Достаточно вписать в конец правил — Все остальное должно соответствовать автоформату Идеи. И все. Все случаи покрыты. Не надо городить кучу правил на все мелочи и корнер кейсы.

Сознательно вредительсво не рассматриваем.
UFO just landed and posted this here

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

Все остальное должно соответствовать автоформату Идеи.

Потом приходишь, а отдел сидит на Eclipse...


А потом JetBrains что-то меняет в своих правилах...


Кстати, проверять как будете? У нас вон хук CI на коммит проверяет в некоторых репах, что после автоформаттера код не поменялся. Как с этим быть с подобными требованиями?

Потом приходишь, а отдел сидит на Eclipse...

Я бы развернулся и ушел. У них слишком много тараканов. Писать джава код не в идее нет смысла.

На самом деле пусть пишут хоть в vi. Главное чтобы правила идеи соблюдали. Остальное не важно.

А потом JetBrains что-то меняет в своих правилах...

Как обычно. Все измененное по новым правиласм, все старое лежит как есть.
Это достаточно редкая ситуация.

Кстати, проверять как будете? У нас вон хук CI на коммит проверяет в некоторых репах, что после автоформаттера код не поменялся. Как с этим быть с подобными требованиями?

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

Правила переноса фигурных скобок — да, важны.
А писать declare(strict_types=1) или declare(strict_types = 1) — вот воообще наплевать.

Согласны или нет?
UFO just landed and posted this here

Так если VCS используется, то виноват не тот, кто к правилу раслабленно относится, а тот, кто коммитит содержательные изменения вместе со стилевыми. Ну просто несопоставимо. И если претензии к тому, кто пробелы не так ставит, лично я сочту придиркой (ну, если это не совсем уж кровь из глаз с отягчающими обстоятельствами), то коммит со стилевыми правками вперемешку с содержательными — это уже реально очень крутой продолб.
Я где-то выше уже писал, что если не нравится чей-то не соответствующий общепроектному стиль — то возьми и поправь, и закоммить отдельным коммитом, причем по возможности убедившись, что ни в чьих ветках не будет проблем слияния.

Проблема, полагаю, как раз в автоматическом форматировании. У одного IDE удаляет пробелы, у второго добавляет, а теперь представьте что одному нужно что-то изменить в коде другого.
Нет, потому что единообразие позволяет легче использовать инструменты для решения тех задач, для которых они не были предназначены непосредственно.
Например, grep и sed ничего не знают про грамматику вашего языка программирования.
Но я могу легко написать
sed -i.bak -e 's/declare(strict_types=\([01]\))/declare(experimental_very_strict_types=\1)/g' config*
, и мне не придётся усложнять свои регулярки, чтобы работало и с пробелами, и без.
С тем же успехом я могу настроить vim, чтобы он переходил к концу функции командой /^}$/, найти все функции регуляркой /^func/ и так далее.
Конечно, для решения всех этих задач есть «правильный» способ — взять кусок компилятора, который строит AST, скормить ему код (при этом не забыть аугментировать AST данными необходиыми для обратного преобразования), написать rewriter, а потом обратно сконвертировать в текст. А сочинить команду с grep/sed/perl/awk можно за пару минут.
> А писать declare(strict_types=1) или declare(strict_types = 1) — вот воообще наплевать.
Не плевать. Если мне когда-нибудь понадобится в IDE найти все вхождения, то я хочу не задумываясь один раз набрать в строке поиска «strict_types = 1» (или «strict_types=1», главное чтобы я был уверен, что везде одинаково) и найти сразу за один раз все случаи. А не начинать гадать «а вдруг тут автор захотел выровнять по соседней строке и пять пробелов написал» и перебирать 100500 вариантов.

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

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

В нормальных компаниях код просто не пройдет коммит если линт ругается.
Ну и хук стоит для авто формата
В нормальных компаниях код просто не пройдет коммит если линт ругается.

Как раз недавно была ситуация — надо было заменить реализацию ф-и на заглушку (ну т.е. вместо того, что там было, возвращать некоторую константу, это было актуально, естественно, исключительно для дев-ветки). При этом было линт правило — никаких неиспользуемых аргументов в ф-и! Понятное дело, что замена на заглушку приводила к неиспользуемым аргументам. А удаление аргументов, в свою очередь, приводило к ошибкам типов при вызове этой ф-и (на вызове аргументы-то были). Исправление тех ф-й — опять-таки каскадно приводило к неиспользуемым аргументам и ошибкам типов, в итоге, чтобы удовлетворить линт, коммит на 1 строчку легким движением руки превращается в коммит на несколько сотен строк. Иначе — коммит НЕ ПРОХОДИТ, ведь "в нормальных компаниях код просто не пройдет коммит если линт ругается".
Большая польза от этого всего, действительно, превратить минутную работу в часовое ковыряние в коде.
С другой стороны — время оплатит заказчик, а потому любой подход, который раздувает трудозатраты, полезен.
Если есть возможность проект, который делается год, делать три года — то какой смысл от нее отказываться? Это же просто не выгодно! Так что больше линт-рулзов — хороших и разных! А когда заказчик спросит — чо так долго? можно ему популярно объяснить, что вот смотрите сколько у нас линт-правил, пока все выполнишь… ух!

UFO just landed and posted this here

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

UFO just landed and posted this here
Я работаю на C# и там любое правило можно на время или вообще навсегда отключить аттрибутом SuppressMessage именно в том месте где это надо. Как в других языках не знаю.

Можно, конечно. Но возникает вопрос — зачем вводить правила, и тем более ставить проверку их исполнения во время коммита, чтобы потом их отключать?

UFO just landed and posted this here
Причин может быть много и вполне обоснованных, а не таких как "да надоел мне уже этот ворнинг".

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

UFO just landed and posted this here
Затем, что в одном случае есть причины, чтобы его обходить, а в другом случае его лучше соблюдать.

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


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

UFO just landed and posted this here
UFO just landed and posted this here
но кроме этого?
Невроз. Многие натурально получают наслаждение от исполнения ритуалов. И будут визжать до пены, защищая их от любого разумного человека, пришедшего с вопросом «зачем». Я с такими встречался в реальности, и это страшно (люди плакали, угрожали и т.д.).

Они не могут без правил, например, в каждом файле они начинают реально ЗАДУМЫВАТЬСЯ, как правильно расставить пробелы в «declare(strict_types=1)», и так с каждой мелочью. И для них это реально пытка, когда нет правил на абсолютно всё.
UFO just landed and posted this here
Ещё чтобы не задумываться о каждой мелочи, можно о ней просто не задумываться. У меня получается.
UFO just landed and posted this here
А у вас code review — для подсчёта пробелов? А то я всегда на содержание смотрю в первую очередь. С вашей точки зрения, я делаю что-то не так?
UFO just landed and posted this here

Неисполнение правил, которые мы обсуждаем, обычно упрощает code review. Например, то самое правило, которое было упомянуто в этой ветке (недопуск неиспользуемых переменных) ведет к ненужному раздуванию дифа.


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


А ты сам как думаешь?

Думаю, что лучше отключить.


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

Это аналогия как раз в мою пользу. Я сам решаю прекрасно — чем и где мне есть, никакой линтер за этим не следит. И если я буду есть руками в ресторане — мне даже никто не сделает никакого замечания.


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

Так в том и смысл, что не в отдельном. Наоборот — обычно как раз и надо эти правила нарушать (с неиспользуемыми переменными — точно, что за правило на счет статических методов — не уверен, уточните).

UFO just landed and posted this here
UFO just landed and posted this here
Шарповому линтеру по умолчанию не нравится, если ты делаешь экземплярный метод там где мог бы быть статический.

100% же в линтере есть правило которое говорит, что статический метод нельзя вызывать через экземпляр, с-но когда у вас статический метод становится обычным (или наоборот), то надо менять все call-site. Ну а при обратном изменении (если статический метод становится обычным) менять вызовы придется в любом случае. Типичный пример вредного правила, которое ведет к раздуванию диффа.


но никогда не имел проблем из-за его соблюдения

Так постоянно встречается. Стоит чуть поменять метод (вызвать в нем this) — и привет рефакторингу с заменой всех вызовов.


собственно, вот она проблема линтера — он смотрит только на синтаксис. Линтер не понимает смысла кода (а потому не может отличить "синтаксически статический" метод, в котором просто в силу случайности нету this, от "семантически статического", который должен быть статическим по задумке), не имеет никаких предположений о том, как будет изменяться и т.п.
Линтер банально не обладает (и не может обладать) информацией, которая необходима для принятия решений о том, каким должен быть код. Поэтому и решать он ничего не может. Ну или может, но ошибается регулярно.
Если я не сделал метод статическим, значит, он по смыслу не должен быть статическим. Вне зависимости от мнения линтера по этому поводу. Мне лучше знать, чем линтеру :)


Точно так же ты можешь всегда сам решать — работать за деньги в команде

Неисполнение дебильных линт-рулзов только помогает работать в команде)
Меньше споров и внутреннего недовольства, выше производительность — а значит ниже стресс :)

UFO just landed and posted this here
Но, если честно, то не могу вспомнить случая, чтобы пришлось переделывать статику на нестатику или наоборот — это какое-то слишком уж сильное изменение семантики самого метода требуется.

Ну так метод семантически либо сразу статический, либо нет (это понятно, когда ты его создаешь). Но при этом он может не иметь this и быть по смыслу нестатическим (что регулярно происходит) — тогда линтер ругается, и мы делаем его статическим (хотя понимаем, что статическим он быть не должен). После чего this предсказуемо появляется — и надо переделывать обратно :)


А, опять-таки, задумываться всякий раз делать ли мне метод статическим или экземплярным (когда можно и так и так) я не хочу — мне проще последовать совету линтера

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


Еще меньше споров, недовольства, и стресса будет если не работать вообще :))

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

UFO just landed and posted this here
Не буду сразу утверждать, что такое невозможно, но как-то сложно сразу такое придумать.

Эм, ну практически любой метод без this)
В смысле, на 1 реальный статический метод таких десяток приходится. правда тут конечно еще у вас особенности шарпа — в шарпе нельзя в топлевеле ф-и объявлять (ну, недавно вроде разрешили), а в js статические методы обычно просто выносятся из класса.


тогда линтер ругается, и мы метим конкретно этот метод атрибутом SuppressMessage с комментарием (Justification = "..."), почему мы этот метод все-таки сделали нестатическим.

Так а зачем это делать, если можно просто нестатические методы делать нестатическими, без SuppressMessage?


Мой подход — думать над тем, над чем действительно надо мозгом думать, и сваливать по возможности все остальное на автоматизированные инструменты

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


Какие нервы, какой рейт — у меня IDE сама все форматирует и отклонения от правил по шорткату исправляет

Далеко не все линт-рулзы исправляются. И, с-но, тем которые "больно" соблюдать как раз обычно не исправляются :)
Ну и да — как ваш шорткат исправляет замену обычного метода на статик? Вместе с фиксом всех call-site и диффом на сотню строк?

UFO just landed and posted this here
Мне все равно сложно представить метод, который никак не связан с this, но при этом связан с конкретным экземпляром класса.

Так он сейчас не связан с this. А завтра оп — и будет. Ну банальный пример — у вас есть компонент, который выводит список чего-то, есть метод который генерит разметку для элемента списка. Если в списке нет контролов — и this не будет, т.к. все нужные данные есть в item, который передается в метод аргументом. Но вот завтра бах — и элемент списка надо уметь выделять, поэтому нужен this.setState.


А зачем вообще статические методы?

В жс, по сути — ни зачем, т.к. с тем же успехом можно просто объявить ф-и в отдельном модуле, разве что для декораторов это иногда полезно, т.к. статические члены, емнип, доступны в декораторе. В c# — ну, чтобы объявлять ф-и, которые "как бы не в классе", топлевел-объявлений-то там нет.


В чем неправильно-то? Использовать статические методы?

Нет, неправильно принимать решение о том, какой метод делать статическим, основываясь на советах линтера — который, условно говоря, в 50% не прав.


"Ctl + ." -> "Make static"

Ну т.е. автоматом это не фиксится, надо руками делать.


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

Так и зачем это нужно, если можно просто вырубить данное правило и не страдать?


Смотрите, я вам говорю: "у нас проблема", вы в ответ: "ну, вот у нас есть такие решения, вроде и не сложные, а еще можно сделать так и так". Окей, но смысл в том, что проблемы вообще могло бы не быть, и тогда ее не пришлось бы решать — достаточно просто вырубить правило и все.


ЗЫ: еще один кейс, кстати — если вам ваш статический метод захотелось перегрузить в подклассе. При этом тут ваще жопа — ведь исходный метод может быть вообще в другой сборке, к которой у вас нету доступа. И статический он там только из-за линтера, да). Отдельный вопрос — покажет ли линтер ошибку, если данный метод является частью реализации интерфейса? В случае тсовского линтера я прям уверен, что все равно покажет)

Ну конкретно в этой ситуации добавление исключения в линтер это нормально


// this is a mock
// eslint-disable-next-line no-unused-vars
function fetchData(params) {
   return mockData;
}

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

UFO just landed and posted this here

это вы всем отделом не могли придумать или загуглить как игнорировать аргументы в обход линтера? Что за язык/линтер то хоть? Даже интересно гуглится ли решение за 5 минут

В Unix системах нет разницы между чтением файла из файловой системы, с девайса или потока. Эта строка в файлах нужна, чтобы узнать, что достигнут конец «данных» при чтении из входного потока — обычно это EOF. Когда ты открываешь стрим на APPEND, то он находит EOF, стирает и пишет с того места, в конце опять поставит EOF. Да, сейчас за тебя тебя много что делает современные тулы, но как быть со старыми?

Ну так сейчас уже не CPM-овские времена с расстановкой 0x1A в неиспользуемом месте последнего сектора файла. Так что нет там никакого стирания EOF, просто к концу дописывают. Правда, если последняя строка не заканчивается переводом строки — то может сконкатенировать последнюю старую строку с первой новой.

Другие люди будут привычны к другим правилам и их мозг всё равно будет взрываться. Тот же пример с CFO и FRC в статье.
И даже сам через 2 года уже может будешь писать по другим стандартам (не потому что даже развиваешься, а потому что стандарты изменяются) и тоже старый код всё равно будет взрывать мозг.
Поэтому согласны с автором статьи. Фанатизма должно быть по минимуму. Проблемы форматирования решаются бьютифайером, включая даже стандарты именования переменных (getJson vs getJSON). Оговаривать же надо только то, что не только не решается, но и приводит к проблемам (FRC vs CFO). Остальное — пусть каждый… как он хочет.

Но всякие там правила вроде «не больше одного оператора в строке» вполне себе нужны, особенно если в команде есть джуны. Да и вообще, весьма хорошая практика иметь единый стиль оформления кода во всей компании, это просто удобно. Программистам же на самом деле это ничуть не мешает. Эти правила никак не усложняют написание кода, но впоследствии заметно упрощают его чтение и сопровождение.
Такие мелочи просто приводить к единому стандарту в момент отправки кода.
Нам, например, намного проще настроить у себя ИДЕшку на стандарт
void main() {
}

и прикрутить бьютифайер к моменту отправки кода, чем каждый раз насиловать себя тратя лишние строки
void main()
{
}

и так далее по тексту.
Писать надо так, как удобно. А вот коммититиь надо уже по стандарту.
void main() {
}
я бы такой стиль запретил.
Нет симметричности, не понятно где что начинается и заканчивается.

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

жаль только большинство бьютифаеров еще фиг настроишь нормально… Например постоянная проблема — они умеют скобку либо всегда переносить, либо всегда оставлять. Переносить только если аргументы многострочные — до этого бьютифаеры не додумались (

звучит как повод оставить issue на гитхабе вашего бьютифайера. Где можно проголосовать за эту фичу?
Правила переноса фигурных скобок важны.
А вот важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?
я уверен, что вы сходу даже не заметили разницу
Важно! Так же важно, как и уважать читателей своего кода или поста на хабре.
Вроде накопипастил коммент 10 раз, мир не рухнул.
Страшно представить, как выглядит ваш код

image
божественный аргумент
Аргумент — это утверждение, приводимое в подтверждение другого утверждения.
Я не приводил аргументов — всего лишь сделал утверждение.
Это базовые поняти логики.
Программирование основано на логике.
Дальше развивать тему не считаю нужным.

Суть поста 'Заставь дурака богу молиться...' Конечная цель нашей работы работающее приложение удовлетворяющее требованиям заказчика. Если правила упрощают эту задачу ОК. Есть правила усложняющие задачу (например англоязычное наименование всех без исключения сущностей).

Я тоже поначалу не понимал, зачем нужны все эти правила — ведь и так вроде работает!
Сейчас, когда спустя 3 года, я правлю свой собственный старый код, я плачу кровавыми слезами и думаю — «ведь говорили же мне умные люди — делай нормально, почему я их не послушал?!»
Еще раз. Есть важные правила, есть не важные. Перенос фигурных скобок важен.

А вот важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?
Ты ревьювил чужой код? Такое ощущение, что нет. Когда тебе нужно быстро отревьювить мержреквест на пару сотен изменений, любой лишний пробел тормозит твое внимание. В этом случае куда важнее единый стиль у всех, чтобы взглянув на начало конструкции ты уже понимал, что она из себя представляет.
Я десятилетиями ревьювю код. Почти во всех инструментах есть галочка «игнорировать пробелы».

Но дело вообще не в этом. Часто есть какие-то ситуации, когда код хочется сделать не по правилу. Но перфекционизм зачастую работает против здравого смысла.
UFO just landed and posted this here
UFO just landed and posted this here

Офигеть, спасибо. А то бывает после автоформатирования старых файлов 99% изменений приходится на пробелы в начале строки. ┬─┬ノ( º _ ºノ)

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

А лучше — само пусть делается

Количество пробелов в начале строки — важное правило

А вот важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?
А вот это уже и решает команда. С одной стороны, без пробелов строка выглядит компактнее. С другой стороны, пробелы помогают отделить знак, что может помочь найти ошибку, если она есть. Язык тут тоже имеет значение. Я предпочитаю ставить пробелы. Но этот подход должен быть однообразным во всем коде, чтобы было легче быстро читать исходники.
а насколько конкретно сложнее читать исходники, если жесткого правила не будет?
Зависит от конкретного человека. Для меня это будет примерно на 20% сложнее.

Я надеюсь, вы понимаете, что PSR — это всего лишь стандарт, ему можно следовать, а можно и не следовать, но его нельзя написать "нестандартизированно", "неконкретно" и т.д. На него проще смотреть, как на формальное (именно поэтому MUST капсом, это из RFC пришло) описание конвенции по работе с кодом, принятой некоторым сообществом добровольно.


Если хотите, придумайте свой стандарт, в котором можно будет ставить лишний пробел. Уберите "неважные" правила из линтера и т.д. Получайте удовлетворение от решения задач и вместе с ними ворох лишних правок в коммите, когда кто-то нажмет Reformat Code в своей любимой IDE, настроенной на свой вкус. Так можно будет легко разобраться, что относится к задаче, а что — просто форматирование существующего кода. Еще будут веселые войны за положение скобочек, табы\пробелы и так далее, и эти войны будут скрывать реальные опечатки, косяки, баги.

UFO just landed and posted this here

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


У кого-то наступает выгорание от того, что линтер просит поменять порядок импортов? Толи ещё будет, когда к такому человеку придет бизнес с хард дедлайном!

Тут сразу вопрос, а чо ж он не поменяет, если знает, что именно надо поменять и где?

Линтер не поменяет, потому что поменяет форматер. Он для того и придуман, чтобы вообще о таких мелочах не думать и вручную не править

Ну дык вот он и есть, правильный подход. Я как увидел prettier и узнал про коммит-хуки, вообще расслабился

import IShouldBeThird from './third';
import IShouldBeSecond from './second';

import IShouldBeFourth from './fourth';
import IShouldBeFirst from './first';

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

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

Но ведь с комментарием та же ерунда будет: линтер не знает почему этот комментарий был поставлен.

Но он хотя бы не удалит пустую строку

Да фиг с ней, с пустой-то строкой — она и правда не так важна. А комментарий, оторванный от прокомментированного блока — это ведь ещё хуже чем отсутствие комментария.

Действительно, сейчас проверил, если комментарий был на предыдущей строке, то он оторвется, а если на текущей, то норм. Получается, что нужно делать как-то так, если важно откомментировать конкретную строку:


import component from './component'; // import this component

Но если в целом, чувствительные к порядку импорты – это code smell, и лучше таким не увлекаться.

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

При чем тут контроль версий?

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

Есть важные правила, а есть неважные.

Важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?

Кроме того, все дифф-смотрелки умеют игнорировать пробелы
А кто запустит этот скриптик?
varanio не переживайте, у вашего стиля написания миллионы последователей, поэтому у него есть даже специальное название — индусский код. У кого кровь из глаз течет, происходят прочие катастрофические события с разумом, а кто то благоденствует и спит спокойно :-)
Есть и еще одна причина выбирать максимально строгие правила — убрать правило можно всегда, а вот добавить после килотонн написанного кода уже бывает поздно.
Да, бывают (псевдо)перфекционисты, которые следуют правилам без понимания, но это быстро исправляется вежливой беседой с правильно задаваемыми вопросами… ну или само как-то с опытом приходит.

И добавлю еще пару выкриков в пустоту:
— разделение проверки код стайла и самого код ревью — очень хорошая вещь.
— мало договориться о правилах, нужно к каждому правилу дописывать его обоснование. Чтобы не было «какие-то законы, которые придуманы фиг пойми для чего»
> разделение проверки код стайла и самого код ревью — очень хорошая вещь.
ну, код стайл проверяют линтеры обычно, еще до код ревью

но и на код ревью может всплыть куча лишних писанных и не писанных правил

Помнится, как на первом курсе жутко бомбило от начертательной геометрии. Ах, гостовый шрифт, дурацкие рамки, формат А3 и выше — какой чёрт вообще это придумал?!


Помнится, как к четвёртому курсу было отвращение к оформлению КД на курсовую, предметом которой был электронный узел со схемой и платой с элементами. Ах, да кому нужна документация в цифровом веке? Делаешь плату, кидаешь герберы на завод, а они в обмен на деньги тебе платы миллионами отгружают. Оформить спецификацию? Упаси бог, кому вообще это может быть нужно, кроме пытающих студентов преподов?!


Итак, четвёртый год работы идёт. Электронные узлы для ракет воздух-воздух, комплекты модернизации для ЗРК, носимые портативные умные "устройства" — всё это уже обыденно и не вызывает животного страха перед бездной неизведанного. А самое главное — просветление. Просветление от дурости, что искусственно была помещена в голову наследниками лучшего в мире образования (с)


Я понял, что свят тот человек, что придумал хотя бы гостовый шрифт (хотя я гоняю Isocpeur) да и вообще ЕСКД. Проект, блок, плата или даже чёртов кабель без оформленной нормально документации — это адская срань, головная боль и лучи поноса на его разработчика от того, кто столкнулся с его творением. Да, не каждому нравится заниматься творчеством будучи в рамках хотя бы правил оформления ЕСКД, но никому не будет нужен твой пусть трижды крутой труд, если он писан левой ногой, которую ещё во Вьетнаме пожгло напалмом. Я открываю док из 1960-х и вижу труды человека на одном языке со мною говорящего. И это круто. И пусть там совсем другие подходы к объекту разработки в принципе, ты сразу в теме.


Не круто — открывать чей-либо труд и видеть там кривую-косую кучу смердящего самопала, ведь автору так виднее и красивее. Мнений, конечно, столько, сколько же и людей, потому моё мнение о статье выражается в одном слове после длинного интро. Нытьё.

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

UFO just landed and posted this here

Тест:
'l' которая tolower('L')
'|' которая 1/2 OR == '||'

Вторая на пару пикселов длиннее — ещё надо всмотреться. Я бы сказал, что тест провален.

Отлично, вы описали важные правила. А есть неважные, например, угол наклона с точностью до градуса
Я понял, что свят тот человек, что придумал хотя бы гостовый шрифт (хотя я гоняю Isocpeur)

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

Главное что не два шрифта вперемешку

UFO just landed and posted this here

Чииайте внимательно. Про говнокод речи вообще не идет. Некоторые правила важны. Некоторые нет.


Ухудшение читабельности на 0.00001% не вредит ни проекту, ни коллегам

UFO just landed and posted this here
Еще раз. Есть важные правила, а есть неважные.

Важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?

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

Добавлю. Я не программистка, но периодически приходится что-то по мелочи написать на незнакомом мне языке, например VB.Net или Lisp. Я всегда сразу ищу гайды, как принято на этом языке оформлять код, в каком стиле именовать переменные (например в .NET частенько ПолностьюПишутЗачемНужнаЭтаПеременная :)) ). Без этого мне некомфортно, приходится задумываться, а как бы лучше оформить. А когда есть правила: "делай раз, делай два", мне сразу гораздо легче программировать. Это экономит внимание и нервы.

Есть важные правила, а есть неважные.

Важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?

Кроме того, все дифф-смотрелки умеют игнорировать пробелы

Есть некоторое количество простых правил, которые минимизируют количество ошибок, которые в принципе могут быть совершены — например, "окружать скобками любое, даже самое тривиальное выражение". Как я говорю, "Выражение без скобок — это как винтовая лестница без перил: могу ли я ее построить? Могу, без базара. Могу ли я подняться по ней? Да не проблема. Буду ли я чувствовать себя в безопасности, делая это? Нет, нет и ещё раз нет!!!"


Как вы понимаете

скобки предохранят от ситуации a = b * c, где c раскрывется (либо макросом, либо при невнимателным джуном при рефакторинге) в d + e, в результате чего получается выражение a = b * d + e, когда на самом деле нужно былоa = b * (d + e)

Вы когда-нибудь задумывались над тем, что ситуаций, от которых можно бы "соломки подстелить" — в принципе бесконечное количество, и от всех вы не застрахуетесь?


Вы, конечно, можете сказать, что лучше быть застрахованным от какого-то числа ситуаций, чем от нуля ситуаций. Но встаёт вопрос о цене, которую вы за это платите. Вы же не тратите 100% своего времени на то, чтоб себя подстраховать? А собственно почему? Тратя всё ваше время вы застрахуетесь от большего количества ситуаций, чем если бы, например, тратили на это 99% времени и 1% на собственно разработку.


И вот когда вы это всё обдумаете, надеюсь, вам станет понятно, почему писать "вот это спасёт меня от вот таких проблем" — это, мягко говоря, пустая схоластика, если у вас нет конкретных данных о том, сколько ресурсов вы затратите на страховку (даже если это всего лишь "скобки расставить"), и сколько ущерба вам в среднем наносят подобные ситуации (без всякого "допустим, на проект придёт джун с IQ 30 и всё сломает").

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

скобки предохранят от ситуации a = b * c, где c раскрывется (либо макросом, либо при невнимателным джуном при рефакторинге)

в Сих нет такой проблемы — тупо c пишешь как макрос, только сразу правильно (скобки ВНУТРИ макроса) и все едет дальше на ура и без каких-либо проблем с раскрытием )
А вот писать a = b * (c) в коде — явная глупость.

UFO just landed and posted this here
Так не пишите. Язык вроде не заставляет это делать.

Язык-то не заставляет, а вот некоторые стайл-гайды...

Это повод их поправить. Заставлять людей писать болерплейт код везде это явно через чур.

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

Это не перфекционизм. Это очень запущенный энтерпрайз.
У меня были некоторые случаи, когда я писал простенькие вещи (чисто для себя из эстетических соображений) «правильно», а не «как проще» и сам себе думал: «А на кой мне это делать? Почему бы не срезать угол, не нагородить костыль, не захардкодить, не пропустить проверку валидности аргументов...» А потом через месяц оказывалось что надо что-то срочно поменять и оказывалось, что то правильное решение, которое я считал избыточным, сейчас сэкономило мне кучу времени и сил.

Хм, а про что, по-твоему, I в SOLID? Как инвертировать зависимость без выноса интерфейса?

Разумеется, я имел ввиду D, а не I.

UFO just landed and posted this here

Ну, буква D в SOLID — это не DI, а DIP, она вообще не про внедрение зависимостей, а как раз про написание интерфейсов.


Однако, ответ от этого не меняется: DIP предписывает выделять интерфейсы при формировании абстракций, но никак не заставляет формировать абстракции. Нет абстракции — не нужно и интерфейс выделять.

UFO just landed and posted this here

SOLID — это скорее про архитектуру, а не про код. И интерфейс на все не нужен, он нужен, в частности, там, где надо, собственно, инвертировать зависимость.
Долго расписывать, советую почитать про это в первоисточнике — у Роберта Мартина в книге «Чистая архитектура», там в конце есть даже несколько страниц относительно архитектуры в типичных спринговых приложениях. Вообще интересная книжка, сам не так уж прям давно читал, получил удовольствие.

UFO just landed and posted this here
Я думаю, что, по меньшей мере, название этой книги говорит о чем она.
И не совсем понял при чем там монолиты из 2005-тых? Описанные там принципы можно применять хоть в монолитах из 2005, хоть в микросервисах 2021.

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

UFO just landed and posted this here
Не уверен, что понимаю, про что вы, но я писал об абстракциях именно в контексте DIP, где они противопоставляются деталям [реализации].
UFO just landed and posted this here
В общем случае это применимо ко всему тому, что вы перечислили. Но так как в случае с сервисами/кластерами абстракции будут являться не интерфейсами, очевидно, что я имею ввиду пекеджи.

>>Я предположу, вы хотели сказать, что зависимости должны быть в отношении слоёв приложения. Где внутренний слой доменная модель, которая ни от чего не зависит.
Да, это именно из той самой книжки Мартина. Но нет, я имел ввиду именно то, что написал. Два модуля: с бизнес-логикой и с логикой доступа к данным. Для этого примера все равно как организована сама бизнес логика, скажу даже еще более страшную вещь: не обязательно должна быть модель домена.
UFO just landed and posted this here
В каком смысле спорное заявление? Перефразирую немного: без вынесения интерфейсов, в классах с бизнес-логикой пришлось бы импортировать классы из модуля с доступом к данным, что означало бы, что бизнес логика зависела бы от логики доступа к данным.
И тут совершенно не важно, используется Repository или нет.
UFO just landed and posted this here
UFO just landed and posted this here

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

Верно. Первое правило как раз на эту тему: отсутствие перевода строки в конце файла, это лишний шум при diff'ах. Второе правило ускоряет анализ изменений.
В команде разработчиков FreeBSD, был легендарный человек Bruce Evans aka bde, который линтил почти все коммиты в ядро — пару раз мне прилетало от него за какую-то мелочь, и так же как автор, пытался с ним спорить. И оба раза был вынужден признать, что да, даже эти мелочи важны для проекта, над которым работают десятки людей.
Причем, на то время был лишь один разработчик, который бурно огрызался на каждое замечание от bde, но это просто особенность характера, т.к. в публичной дискуссии сразу было видно, что все его доводы о необходимости нарушения style(3) не больше, чем детский лепет, по сравнению с железобетонными аргументами bde.

Так может, просто заменить почти всю ту толстую пачку правил, которые это обеспечивают, на ровно одно правило — в коммите можно править чужой стиль только в том случае, если в этом коммите правится только стиль, и в описании коммита явно написано, что это правка стиля?
И, кстати, если кто-то бездумно жмет "Reformat code" в IDE и потом коммитит весь получившийся трэш ради тщательно спрятанной в нем одной строчки содержательных изменений — он должен перестать это делать, потому что это сильно мешает коллегам.

в коммите можно править чужой стиль только в том случае, если в этом коммите правится только стиль, и в описании коммита явно написано, что это правка стиля?

Вы с легаси кодом не работали? Делаешь тикет. И понимаешь что надо поменять пару строчек вот в этом файлике который лет 5 никто не трогал.
А он не закомитится с несоблюденим стайлгайда. Надо или приседать с ветками черрипиками и прочим или просто написать комментарий к реально измененным местам. Прямо в комменты в вашей системе код ревью.
Если там несколько строк, то менять все сразу всем удобнее и быстрее.
А он не закомитится с несоблюденим стайлгайда.

Это условие несовместимо с наличием нарушающего стайлгайд легаси.


На практике нет ничего проще же: делается два коммита, в первом правится стиль, во втором содержание. Если таких файлов много — fixup commit и интерактивный rebase в режиме autosquash в помощь, никаких приседаний не нужно.

Это условие несовместимо с наличием нарушающего стайлгайд легаси.

Увы, на практике такое сплошь и рядом. Легаси который был до стайлгайда лежит себе. А начнешь править приходится переделывать чтобы стайлгайд соблюдался.

На практике нет ничего проще же: делается два коммита, в первом правится стиль, во втором содержание. Если таких файлов много — fixup commit и интерактивный rebase в режиме autosquash в помощь, никаких приседаний не нужно.

По сравнению не делать ничего это все равно приседания. А еще бывают обязательные код ревью. Это еще и время тогда занимает.

Я именно про простейшие случаи. Когда в файле где правится стиль правится исправления минимальны. А не когда весь коммит это вперемешку стиль и куча кода. Тогда да по очереди. Оно того стоит.
UFO just landed and posted this here
Запретить self assign техническими способами. Неудобно, но сработает.
Как привыкнет через полгодика снова разрешить. Это иногда надо для всяких технических коммитов.
UFO just landed and posted this here
Вы же сами написали зачем. Если это не гений мирового уровня, то обоснование отличное.
Раз его код постоянно падал и переписать оказалось проще чем поддерживать, на гения он не тянет.

Код звезд в котором я копался был достаточно хорош. Читается и правится без особых проблем. И не падет, по крайней мере постоянно.
UFO just landed and posted this here
UFO just landed and posted this here
Пфф, запросто — стайлгайд ввели после последнейй правки этого файла.

Если его ввели просто на словах — ну и пофиг на него. Если стоит автоформатер или даже проверка при коммите — значит, надо взять автоформатер и прогнать через него весь проект 1 раз.


Разбивать по коммитам смысла нет никакого — в мерж-реквесте все правки всё-равно будут вместе.

Все известные мне инструменты позволяют просматривать отдельные коммиты, что полезно как раз в таких вот случаях.

Если его ввели просто на словах — ну и пофиг на него. Если стоит автоформатер или даже проверка при коммите — значит, надо взять автоформатер и прогнать через него весь проект 1 раз.

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

Автоформатер по всему коду прогонять страшно. Там такое бывает… Лучше не трогать от греха.

Все известные мне инструменты позволяют просматривать отдельные коммиты, что полезно как раз в таких вот случаях.

Можно, но неудобно. Написал код — поправил стиль — написал код — дописал тесты — переписал код — а тут еще на стиль ругается поправил.
За коммитами в ветке никто не следит. Там обычно мусор.
Все равно все сквошится при мердже.

Руками сделать любую историю коммитов потом можно. Но это опять приседания просто так.

Вот именно поэтому я и не люблю энфорсинг чего угодно на уровне коммит-хуков, и поэтому же не люблю непрошенные или слишком легко делаемые "reformat code". Если это небольшая локальная правка в легаси-файле — то надо просто поправить, придерживаясь стиля, принятого в этом конкретном файле. Даже если это неудобно и нужно руками в нужных местах пробелы добавлять. А не выдавать коммит, в котором мешанина.

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


В итоге подключили prettier, сделали один большой супер-коммит с переформатированием всего и зажили нормально

Есть важные правила, а есть неважные.

Важно ли, писать declare(strict_types=1) или declare(strict_types = 1)?

Кроме того, все дифф-смотрелки умеют игнорировать пробелы

"В конце каждого файла должен быть перевод строки. А если не будет, то кто умрёт?"


  • некоторые скрипты, грепающие это безобразие
    В конце текстового файла действительно лучше оставлять новую строку
Автор упустил из виду самый важный, на мой взгляд, вопрос — Вам одному мешает этот якобы чрезмерный перфекционизм или он раздражает всю команду? Если второе, то что мешает собраться командой, потратить полчаса и пересмотреть стандарты? Если первое — то тот факт, что так думаете только вы, то, возможно, не стоит навязывать это мнение коллегам. Ведь объективных аргументов в Вашей статье, по сути, нет…
Из личного опыта — проработав почти 10 лет в компаниях Amazon и Google, могу сказать, что более драконовских и детальных кодинг стайлов, чем в этих компаниях, я не встречал. Но лично для меня принять это никогда не было проблемой, т.к. я очень люблю кодинг стандарты. Какие-то детали в них мне не нравились, но это адекватная плата за единообразие, без которого половина проектов могла бы загнуться — текучка невероятная, люди постоянно переходят из команды в команду, над проектом может работать по 10+ человек, у всех свои в голове заморочки как надо правильно. В этой ситуации стандарты — это спасение, если надо что-то быстро найти в огромном коде.
Будь моя воля, я бы еще чуть стандартизировал не только код но и кодинг паттерны, ибо есть любители навертеть не пойми что и ссылаться на какой-то паттерн из интернета — будто бы факт наличия статьи в нете (или просто даже поста на StackOverflow) автоматически доказывает правильность.
Мне кажется гораздо продуктивнее ослабить требования к процессу (лично я не люблю SCRUM) и максимально ужесточить требования к кодингу — но это, наверное, тема для отдельной дискуссии.

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


В современных IDE, например Phpstorm, можно настроить автоформатирование при сохранении.
У меня так уже несколько лет работает, как и у половины коллег. Поэтому специально придерживаться стандартов не нужно — IDE это делает за программиста.

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


Правила должны иметь практический смысл.


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


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


Создание разумных правил — сложная задача, об этом можно много написать.

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


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

Главная нужность правил в линтерах — когнитивная предсказуемость и соответственно непонижение скорости чтения кода. Думать о нужности правил здесь бессмысленно. Главное что они есть какие-то — табы/пробелы, пофигу. Главное, что у всех едино.


Дисциплина сделала из банды армию.

Когда в проекте начинают прикручивать линтер и всякие там подобные штуки — я точно знаю, пора искать другой проект :)


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


Короче говоря, когда коту делать нечего — он яйца лижет.

UFO just landed and posted this here
линтеры нужны, вопрос в том, что в них проверяется, не ерунда ли это

Это был сарказм, конечно.


Но я видел много людей кого заботили пайплайны, но гораздо меньше заботило — а стоит ли здравый смысл за этими пайплайнами.


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


Вместо обучения программистов был забанен оператор...


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

UFO just landed and posted this here

Я бы опасался сидеть рядом с человеком, который понимает, что надо чистить зубы и одеваться, но самому ему лень это все помнить, поэтому он нанял еще парочку людей, один из которых постоянно за ним прибирает и причесывает, а второй — следит что первый все правильно сделал :)


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

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

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

UFO just landed and posted this here

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


На самом деле, в 99% это такая соломка, в случае чего можно всегда сказать: "мы все делали по бест практис, а не взлетело — так это не мы..."

Любой инструмент уместен в своём классе задач.

Не кажутся нужными какие-то правила в линтере? Ну так обсудите в рамках компании/проекта/команды и поменяйте набор правил, в чем сложность? Вроде нынче любой линтер позволяет контролировать только то, что хочется. При этом вполне может оказаться, что в ходе обсуждения Вы осознаете, зачем эти правила были введены.

Это кстати частая проблема принятых когда-то решений, что решение осталось, а история, как, кем и зачем оно было принято — нет. У той же Atlassian есть прекрасная традиция в культуре компании — все принятые решения фиксируются не только в части «что решили», но и «кто, зачем, какие факторы были учтены» и т.д.

Да бесполезно обсуждать установившийся карго культ. Последним неустранимым аргументом будет "работает — не мешай"

Маленькие дети читают только печатные буквы и с расставленными знаками ударения.
Потом учатся писать и читать рукописный текст.
Потом поэты и писатели начинают играть с правописанием и разметкой текста.
А потом рукописи и черновики ценятся больше, чем печатный прилизанный текст :)
Поэты и писатели сначала учатся соблюдать правила, и только потом — артистично их нарушать.
Пример с одиночным перформингом некорректный.
Ты пишешь огнем не потому, что пишешь как нравится, а потому, что пишешь из абстракций в голове.
А все правила код стиля и оформления, как и архитектура, паттерны и прочее, не нужны чтобы писать, они нужны, чтобы читать. Причем, обычно не тебе.
Впрочем соглашусь в том, что это не значимый вопрос. Скорее важно, как большинство в команде привыкло, чем конкретный стандарт. Но договориться стоит.
а по поводу пересмотра правил… это действительно необходимо, но возможно только в том случае, если можно понять почему они введены. если нет какой то доки или описания, приходится соблюдать потому что понятия не имеешь что отвалится, если будет по другому.

это про правила в целом. а вопрос про форматирование решается автолинтером, который правит код по сочетанию клавиш.

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


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

включать строгий режим опциями компилятора


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

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

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

вам мешает неудачно выбранный конкретный стайл-гайд или сам факт наличия какого-то стайл-гайда?

Как правило, мешает конкретный. Думаю, если я потрачу достаточно времени, я сумею записать алгоритм того как я оформляю код в виде стайл-гайда (и с этого момента этот гайд начнёт мешать кому-то ещё).

да, понимаю, о чём вы. я думаю, это издержки любой командной работы (и тоже важное отличие от пет-проджектов) — кое-где приходится идти на компромиссы, что само по себе не всегда приятно. вряд ли существует стайл-гайд (или любые другие соглашения), который на 100% совпадал бы со встроенными хотелками всех членов команды. но тут, если вы понимаете, ради чего вы идёте на эти уступки, то вам ок. а если не понимаете — то пишете пост на хабр типа того, который мы с вами комментируем.
другими словами, автор говорит нам: «договариваться с людьми — больно». а ему в комментах отвечают, мол, действительно больно, но это лучше, чем не договариваться вовсе.
Другими словами, бОльшая часть комментирующих вообще не поняла, о чём текст. Вместо этого вцепилась в один кусок, выдрав его из контекста, нафантазировав ему другой контекст, и спорит с ним.

varanio, соболезную.
UFO just landed and posted this here

ну, как обычно в интернетах — любое ваше слово может быть использовано против вас (((

Как я это проясню, если люди игнорируют статью, её название (_соответствующее_ содержанию) и содержание?

Статья называется «Радикальный перфекционизм в коде». С самого начала автор ясно даёт понять, что считает, что это плохо. Приводит доводы и примеры, обосновывает. Статья НЕ про код стайл, и не про конвенции в целом, а про одержимую упорость, и почему это плохо. В статье нет особой иносказательности, она короткая, без воды, по делу. Её несложно понять, нужно просто не фокусироваться на одной единственной теме из неё.
UFO just landed and posted this here
Т.е. если повыкидывать ненужные, на взгляд автора, правила из линтера, то линтер потянет всякий смысл.
Вы тут делаете серьёзное допущение, что линтер в принципе необходим (нет).
А оппоненты, включая меня, пытаются объяснить, что правила эти введены не потому, что так правильно. А чтобы минимизировать diff при командной работе.

Есть огромная куча правил, которые не уменьшают, а увеличивают дифф!


А оппоненты, включая меня, пытаются объяснить, что правила эти

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


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

Это все исключительно от недостатка опыта. Если вы научитесь бегло читать код на разных синтаксически ЯП, то такие вещи просто перестанете замечать. И даже не сможете после прочтения ответить на вопрос: "а как были расставлены атрибуты в этом коде?"

UFO just landed and posted this here
примеры в студию.

Ну вон я выше приводил пример правила, которое вместо fun = () => { return something; } требует писать fun = () => something. Оно увеличивает дифф. Собственно, те правила, выполнение которых наиболее "больно", как раз и обладают следующим свойством: они вынуждают при небольших правках кода делать существенно большие правки, чтобы удовлетворить линтер. Именно такие правила людей и бесят. И, достаточно очевидно, что такие правила будут вести к росту диффа.
Если же правило не ведет к росту диффа — то оно обычно (хотя тут есть исключения — например правила по упорядочиванию методов и т.п.) не требует сколько-нибудь существенных затрат на свое соблюдение и, скорее всего, вообще работает через автомформат. Такие правила в данном контексте обсуждать нет смысла.


Вы не можете понять простую вещь, читать мне все равно, что атрибуты на новой строчке, что на разных. Бегло не бегло — ерунда какая-то. Мне главное надо, чтобы было одинаково у всех.

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


Чтобы автоматическое форматирование у меня и у моего коллеги работало одинаково

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


Алсо, проблема "мусора форматирования" в коммитах на самом деле сама тут в комментах сильно преувеличена.

UFO just landed and posted this here
Есть огромная куча правил, которые не уменьшают, а увеличивают дифф!
примеры в студию.

Пример: выравнивание аргументов вслед открывающей скобке. Тогда код типа


old_warehouse.registerArtifact(foo,
                                                  bar,
                                                  baz,
                                                  false);

превращается в


warehouse.registerArtifact(foo,
                                            bar,
                                            baz,
                                            false);

не знаю, влезет ли у вас в экран показа, у меня уже в предпросмотре оно начинает врапить код.


Но смысл в том, что изменение строчки вызова меняет следом несколько следующих за ней.


И вот такие правила — это уже диверсия.

Странно, что большинство не осилили идею статьи. Я не так давно пришел к тем же выводам, что и автор.
Не знаю, правильно ли я услышал посыл автора, поэтому, чтобы не было разночтений, сформулирую мысль так: «давайте включать голову, а не просто следовать придуманным другими людьми правилам». Если автор имел в виду именно это, то тут особенно и рассуждать не о чем.

Правила, обычно, придумываются для решения каких-то своих задач. Но это не гарантирует, что в вашем проекте эти правила принесут больше пользы, чем вреда. Важно, чтобы программист, если он нарушает какие-то правила, конвенции или паттерны проектирования мог объяснить, зачем он так делает. Если это объяснение из серии «мне так больше нравится», то бог ему судья, но если это из серии «потому что в данном конкретном случае мой вариант лучше по причинам A, B, C, D…» — то низкий поклон.
Может я повторюсь и кто-то сверху уже писал об этом, но пример с трусами не корректный. Ведь по факту, работник без одежды приносит неудобства не компании, а работникам, а значит и снижает их эффективность. Также, и с жёстким code style, мы не можем угадить всем и берём best practices чтобы угадить большинству, чтобы большинство не имело дискомфорта при работе с кодом.
  1. В конце каждого файла должен быть перевод строки. А если не будет, то кто умрёт?
  2. Нельзя делать несколько statements на одной строке. Если я напишу $x = 1; $y = 1; $z = 1;, то читабельность ухудшится на 0.00001% и можно закрывать техотдел?
  3. Declare statements MUST contain no spaces and MUST be exactly declare(strict_types=1). Ох, как всё серьёзно. Ни одного пробела, причем слово MUST капсом, чтобы все понимали степень ответственности. Если вставить где-нибудь пробел, то на код ревью никто код же прочесть не сможет!

  1. Строка умрёт. Перевод строки — это её часть: нет перевода — нет строки. Если бы это было не так, соответствующий символ назывался бы разделителем строк (да, иногда перевод строки так и называют, но, в основном, в контексте текстовых процессоров и HTML)
  2. Это необходимо, чтобы в diff'ах при добавлении или удалении было понятно, что именно было добавлено или удалено без привлечения продвинутых навыков пристального вглядывания. Читабельность кода действительно ухудшится незначительно, а вот читабельность diff'ов — очень заметно
  3. Тут с той же степенью уверенности не скажу, могу лишь предположить, что это необходимо, чтобы поиск таких деклараций не требовал навыков составления регулярных выражений

P.S. можно было привести больше правил и собрать на комментариях материал для статьи, объясняющей необходимость/полезность конкретных правил. А можно было хотя бы что-то почитать и самому всё выяснить
UFO just landed and posted this here
Тут уже многие высказались, но не смог пройти мимо.
Если правило придумали, значит оно нужно было. Если кому-то кажется, что правило безсполезно, то, он может просто не знает где оно нужно?

В конце каждого файла должен быть перевод строки. А если не будет, то кто умрёт?

Многие Linux дистрибутивы поумирают. И многие программы сломаются. Конфиги часто разбиваются на отдельные файлы и складываются в /etc/что-нибудь.d/ и дальше обычной склейкой генерируется полный конфиг.
Или если есть препроцессинг исходного кода (в случае объединения файлов).
У меня на реальном java-проекте ребята имели 10+ properties файлов, которые объединялись в разных комбинациях. И в каждом файле в конце стояли дурацкие коменты «оставьте здесь пустую строчку». Пустая строка, кстати, не нужна, если бы разобрались в проблемах

Нельзя делать несколько statements на одной строке. Если я напишу $x = 1; $y = 1; $z = 1;, то читабельность ухудшится на 0.00001% и можно закрывать техотдел?

Давайте быть честными. Не «x y z», а
«size_t keyword_scan_len = GetScanKeyword(h, keywords); size_t keyword_scan_index = 1; TYPE *pi = (TYPE *)(void *)(parmi)». А когда прелетит изменение в этой строке, надо ещё всматриваться и искать, что конкретно поменялось? index? pi? len? А еслиGetScanKeyword надо было после поставить? Даже если есть строгая практика отделения объявления от присвоения, всё равно, названия переменных и их типов могут быть многобуквеннымми, а их значение константой " int c = THE_SEVENTY_EIGHT_PRIME_NUMBER".

Declare statements MUST contain no spaces and MUST be exactly declare(strict_types=1). Ох, как всё серьёзно. Ни одного пробела, причем слово MUST капсом, чтобы все понимали степень ответственности. Если вставить где-нибудь пробел, то на код ревью никто код же прочесть не сможет!

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

— Современные ide оснащены автоформатированием кода и если не будет стандарта во всём, то каждый коммит будет порождать тонны мусора.
— Когда оформление стандартизировано, я могу выполнять массовые исправления кода (по паттерну), рефакторинг в лоб и т.п.

Ну и наконец, вы подменили понятия. Не дресскод с людьми надо сравнивать, а с чем-нибудь таким же массовым или бумажным:
1. Представьте, что все официальные документы пишутся не от шаблона а от балды: заявление, договоры. А вы тут бухгалтер — разбирайтесь.
2. Вы купили 10 гаек на 12 но они все под разные ключи. А у некоторых не та резьба. А вы крутите эти гайки — наслаждайтесь.
3. Деньги печатаются в разных цветах, разных размеров и форм. И с разным расположением надписей. И вы работаете кассиром — добро пожаловать в персональный ад.

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

Многие Linux дистрибутивы поумирают. И многие программы сломаются. Конфиги часто разбиваются на отдельные файлы и складываются в /etc/что-нибудь.d/ и дальше обычной склейкой генерируется полный конфиг.

Мне кажется, речь шла о файле с исходным кодом. Их-то кто склеивать будет?


Да и в случае с конфигами проще баг исправить чем линтер настраивать :-)


Давайте быть честными. Не «x y z», а […]

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


Причём в том же С++ строчка int x = 1, y = 1, z = 1; многими стайл-гайдами признаётся допустимой, ведь точка с запятой всего одна...

Мне кажется, речь шла о файле с исходным кодом. Их-то кто склеивать будет?

Вот же знаменитый пример. Там правда переводы строк все равно удаляют, но тем не менее.


https://stackoverflow.com/questions/1873983/what-does-the-leading-semicolon-in-javascript-libraries-do


но мне вот хотелось бы услышать аргументы за обязательное разделение инициализации трех переменных

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


Гораздо проще изначально писать декларации на новой строке.

Мне кажется, речь шла о файле с исходным кодом. Их-то кто склеивать будет?

sqlite именно так и компилируется.


Да и в случае с конфигами проще баг исправить чем линтер настраивать :-)

Неизвестно, какие тулзы будут в следующий раз. Править все?


Ну и не знаю, где какой линтер… вот uncrustify штука глючная, но задали ей nl_end_of_file = 1 и она поставила всё. Думаю, для всех языков есть что-то аналогичное, а если нет, precommit hook может помочь.


Причём в том же С++ строчка int x = 1, y = 1, z = 1; многими стайл-гайдами признаётся допустимой, ведь точка с запятой всего одна...

Основная проблема возникает из-за C стиля описаний, когда кто-то вместо "int x, y;" напишет "int x, y;" (а особенно при макросе NULL как 0 — пройдёт без проблем "int x = NULL, y = NULL;").


А ещё переменные надо комментировать.


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

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

А от выкладывания на гитхаб он перестанет быть сугубо для русскоязычных людей и русскоязычных программистов?


И да, почему те "полезные утилиты и скрипты", а также редакторы кода, не ломаются от русскоязычных строковых литералов (которые мало кто запрещает), но ломаются от русскоязычного идентификатора?

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

И да, почему те «полезные утилиты и скрипты», а также редакторы кода, не ломаются от русскоязычных строковых литералов (которые мало кто запрещает), но ломаются от русскоязычного идентификатора?
Строковые литералы спрятаны в кавычки, на самый примитивный вариант обработки которых авторов скриптов, обычно, хватает.
Корректную же обработку не-ASCII символов вне их — там где идентификаторы, лексемы и прочая головная боль — никто не гарантирует, если всё остальное не Unicode.

(и, кстати сказать, ломаются на ура — вы просто не встречали самых примитивных скриптов, которые создаются для обрабоки конкретного набора данных, с какими-нибудь RegExp'ами для поиска чего-нибудь нужного. Отлаживать их — та ещё головная боль.).
Sign up to leave a comment.

Articles