Вольный перевод статьи «Should we use a coding standard?» из блога «Virtuous Code» Avdi Grimm. Мнение автора оригинальной статьи может не совпадать с мнением редакции.
Примечание переводчика: лично я согласен с автором.
Avdi, должны ли мы использовать стандарт разработки?
Да.
Какой стандарт нам использовать?
Не думаю, что есть какой-то один «правильный» стандарт. Каждый проект должен выработать свой стандарт на основе своих нужд и предпочтений разработчиков.
Думаю, что разнообразие стилей в сообществе хорошо. Это хорошо даже для большой организации.
Когда я работал в такой организации, у нас была пара рекомендованных стандартов для любого используемого нами языка. Но окончательный выбор стандарта для каждого нового проекта оставался на совести тимлида.
Я думаю, что выбор стандарта для каждого конкретного проекта — хорошая детализация. Таким образом, у каждого отдельно взятого репозитория и каждой команды может быть отдельный стандарт.
Как нам выбрать стандарт разработки?
Многие сообщества языков программирования уже выработали общие стандарты. К примеру, если вы пишете код на C, вы можете выбрать стандарт разработки GNU. Или если вы разрабатываете на Ruby, вы можете использовать стандарт сообщества, поддерживаемый Божидаром Бацовым: Bozhidar Batsov’s community-influenced standard.
Эти стандарты — плод мыслей и дебатов сообщества. Поскольку соглашения, входящие в эти стандарты, основаны на решении большинства, это хорошая точка отсчета.
Но некоторые решения в этих стандартах — глупые и неправильные!
Истина. Поэтому я и говорю, что стандарты сообщества — хорошая отправная точка. Когда у вашей команды есть четкие возражения по определенным соглашениям в стандартах — наступает время для модификации стандарта под свои нужды.
Наша команда разделилась пополам в выборе определенного пути! Как я могу убедить другую половину?
Будем честны: очень маловероятно, что команда действительно разделилась пополам. Обычно есть один-два человека с одной стороны и примерно столько же с другой, остальная же команда не выбирает ни одну сторону.
Хорошо, так как мне убедить этих людей по другую сторону баррикад?
Уверенность другой стороны могут поколебать хорошо обоснованные, реальные примеры того, что ваш вариант изящнее раскрывает суть кода, лаконичнее пишется или лучше показывает опасные места.
Это не так, просто мой стиль красивее. В любом случае, это более идиоматичный подход.
После многих лет знакомства с разными стандартами разработки я могу сказать, что сильнее всего на отношение к стандарту влияет знакомство с этим самым стандартом. Даже не помню, сколько раз я приходил в проект со стандартом, который я просто ненавидел, но после шести недель работы переставал об этом беспокоиться. Иногда я даже использовал его как новый стандарт для собственных проектов.
Например, когда я начинал разрабатывать на C++, я выравнивал фигурные скобки так, чтобы можно было посмотреть выше и сразу увидеть открывающую скобку в той же колонке:
int main(int argc, char** argv)
{
std::cout << "Hello, world!";
}
Позже я встретился с кодом в стиле GNU/GNOME, где открывающая скобка стоит на строке с объявлением метода. Аргх!
int main(int argc, char** argv) {
std::cout << "Hello, world!";
}
Я пожал плечами и продолжил. Вариант в GNU-стиле даже показался мне предпочтительнее.
Мне встречалось множество примеров кода вроде «А против Б», где вариант Б представляли объективно красивее варианта А. Большую часть времени мне было сложно увидеть разницу, которую автор полагал очевидной.
В Ruby популяризованное Rails соглашение о выборе между фигурными скобками и do...end, основанное на количестве строк кода внутри блока, немного глупо. Мне говорили, что одна из причин такого соглашения в том, что do...end на одной строке объективно выглядит ужасно:
h.fetch(:some_key) do raise ":some_key is required" end
Лично я не вижу ничего плохого в этой строке. Объективные эстетические суждения плохи в качестве правил.
Стоит помнить, что «стандартный» синтаксис языка обычно немного странный в начале. Например, в каждом основанном на C языке мы обозначаем «сообщение» или «аттрибут» примерно так:
farm_boy.fetch_me_that_pitcher()
Так как это слова на английском, давайте рассмотрим это с точки зрения английского языка.
Точка обычно указывает конец предложения, или разделитель между целой и дробной частью числа. Здесь она стоит на том месте, где обычно мы ставим запятую:
"Farm boy, fetch me that pitcher"
Или двоеточие:
"Farm boy: Fetch me that pitcher!"
Тем временем слова отделяются друг от друга символом, которого новички вообще не знают. Я уже даже не хочу думать о кавычках.
Окей, хорошо, стиль субъективен. Но некоторые вещи действительно делают код проще, или ошибки заметнее!
Да, думаю это так.
И мой тимлид делает неверный выбор!!
Возможно, что у вас действительно есть хорошие, целостные, ориентированные на качество кода аргументы в пользу определенного стиля. И вопрос выбора стандарта действительно может развести вас и вашу команду по разные стороны баррикад.
Есть один важный вопрос, который необходимо задавать себе, ратуя за выбор определенного стиля кода. Это настолько важно, что я напишу его отдельной строкой.
Как дорого проекту обойдется ваша правота?
Давайте посмотрим: вы полностью правы насчет выбора стиля или практики разработки. Ваши оппоненты неправы и глупы.
Но спросите себя, сэкономит ли ваша правота достаточно, чтобы компенсировать:
- Потраченные часы всей команды на совещания касательно стиля, которые не заканчиваются ничем толковым?
- Потерю хороших отношений как результат столкновений лбами на этих совещаниях?
- Цену огромных цепочек в почте с обсуждениями плюсов и минусов разных стандартов?
- Злость и гнев вашей команды, когда они будут вынуждены следовать стилю, который им не нравится, но который им в итоге навязали?
Некоторые стандарты разработки стоят всего этого. Но я рекомендую хорошо подумать, прежде чем бросаться в бой.
Стандарты разработки предохраняют от дурных привычек, но в чем их главный плюс?
Стандарты разработки дают программистам, особенно неопытным, определенную защиту от дурных привычек, но я не считаю это главным преимуществом. Для меня главный выигрыш от стандартов — это последовательность.
Сравним два блока кода на Ruby:
# Block #1
output = []
while word = input.shift
unless STOP_WORDS.include?(word.downcase)
output << word
end
end
# Block #2
output = input.map(&:downcase) - STOP_WORDS
Очевидно ли на первый взгляд, что оба блока делают одно и то же? Более важно: очевидно ли, что несмотря на аналогичную функциональность, блоки имеют мелкое, но важное различие?
Реальная ценность стандарта разработки в том, что он делает похожие вещи похожими, а разные — разными. Такая последовательность помогает команде быстрее понимать суть написанного кода. В свою очередь это означает, что они могут работать на более высоком уровне абстракции большую часть времени.
Как это понимать для легаси-кода? Должны ли мы обновлять каждый файл в проекте под новый стандарт?
Одним словом — нет. Не вижу никакой пользы в том, чтобы потратить часы на обновление каждого файла в проекте строчка за строчкой согласно новому стандарту разработки. Это не стоит тех затрат времени и усилий, и может принести новые баги в легаси-код.
Что, если я вношу изменение в легаси-код? Должен ли я обновить весь файл, раз уж я за него взялся?
Мой ответ отличается от общепринятого мнения и порой удивляет людей.
Ответ — нет. Обновление стиля легаси-кода потребует времени, создаст большой diff и увеличит шанс случайной регрессии.
Значит ли это, что я должен использовать новый стиль только в новых или измененных участках кода?
Давайте конкретизируем вопрос. Представьте, что это кусок легаси-кода:
STOP_WORDS = [
'i',
'we',
'if',
'and',
'the'
]
Предположим, ваша задача — добавить слово «they» в список. И по новому стандарту разработки все строки должны обрамляться двойными кавычками.
Нужно ли обновить весь список в процессе добавления нового слова?
STOP_WORDS = [
"i",
"we",
"if",
"and",
"the",
"they"
]
Или применить новый стандарт только для добавленной строки?
STOP_WORDS = [
'i',
'we',
'if',
'and',
'the',
"they"
]
Как я говорил раньше, для меня ценность стандарта — сохранение последовательности. Последовательность важна на уровне проекта, но она важна и на уровне файла. Поэтому я не думаю, что стоит следовать новому стандарту, когда вы обновляете файл, написанный по старому стандарту. Напротив, если в файле уже есть последовательный стиль оформления, вам стоит постараться выдержать его.
Это значит, что если слова в списке обрамлены одиночными кавычками, вы должны добавить новое слово в одиночных кавычках.
STOP_WORDS = [
'i',
'we',
'if',
'and',
'the',
'they'
]
Если вы часто обновляете файл с легаси-кодом, тогда мне кажется хорошей идеей запланировать обновление конкретно этого файла по новым стандартам. Но не думаю, что стоит превентивно обновлять малоиспользуемые файлы. И я не поддерживаю локально несогласованные изменения только ради того, чтобы оставаться в рамках стандарта.
___
Что думаете о стандартах разработки? Какие стандарты применяете? Рассказывайте.
Автор: GeekBrains