HabHub
HabHub copied to clipboard
Принципы написания кода
https://page.hyoo.ru/#!=k2y40h_6ol2cg
Прочитав очередные вредные советы про стандарты оформления кода (раз, два, тысячи их), я не смог удержаться, чтобы не поделиться своими измышлениями на эту тему. Долгие годы я вынашивал в своём подсознании чувство "что-то тут не так". И вот, пришло время определиться с тем, что не так, и почему. Рискуя быть закиданным тухлыми бананами, я всё же пишу эту статью тут, а не в своём личном блоге, потому, что это очень важная тема и хочется, чтобы как можно большее число разработчиков поняли её суть и, возможно, пересмотрели свои взгляды на жизнь.. кода.
Стандарты кодирования
Типичные проблемы многих таких стайл-гайдов: 1. Плохо обоснована их целесообразность 2. Они декларируют конкретные правила, вместо принципов. 3. Эти правила плохо обоснованы и нередко построены на противоречащих принципах.В упомянутой статье всё обоснование необходимости стандартизации заключается в:
Хорошее руководство по оформлению кода позволит добиться следующего: 1. Установление стандарта качества кода для всех исходников; 2. Обеспечение согласованности между исходниками; 3. Следование стандартам всеми разработчиками; 4. Увеличение продуктивности.1. [тут располагается картинка про ещё один стандарт] "Стандарт нужен для того, чтобы был стандарт" - не обосновывает его наличие. 2. В любом более-менее крупном проекте всегда будет куча кода, не соответствующая текущим веяниям моды оформления: изменения стайл-гайда со временем, легаси код, код сторонних библиотек, автогенерированный код. Это неизбежно и не так уж и плохо, как на первый взгляд может показаться. 3. То же что и первый пункт. 4. Уже теплее, но опять же, не обосновывается почему продуктивность от этого должна вырасти, и главное - на сколько.
По своему опыту могу сказать, что самое худшее решение - привыкнуть писать и читать код в каком-то одном стиле, от чего любой код написанный "не по правилам" будет вызывать раздражение, тревогу, гнев и желание навязывать окружающим свои привычки. Куда полезнее научиться воспринимать исходники, игнорируя оформление. И для этого наличие разнооформленного кода даже полезно. Я не говорю, что надо расслабиться и писать всё в одну строку, но, чтобы так не делать, есть куда более практичные причины, чем "стандарт нужен, чтобы всё было стандартно".
Как написать грамотный стандарт:
- Определился с целями
- Сформулировать принципы и провалидировать их на соответствие целям
- Сформулировать минимум правил, для реализации этих принципов
Итак, попробуем
Цель: снизить стоимость поддержки путём наложения на себя и команду ограничений.В чём заключается поддержка:
- написание нового кода
- изменение существующего, в том числе и автоматическая
- поиск нужного участка кода
- анализ логики работы кода
- поиск источника неверного поведения
- сравнение разных версий одного кода
- перенос кода между ветками
Какие принципы помогут достичь поставленной цели:
1. Строки файла должны быть максимально независимы.
Причина проста: если при изменении одной строки требуется изменение других, то это повышает риск конфликтов при слиянии веток. Каждый конфликт - это дополнительное иногда значительное время на его разрешение.Несмотря на то, что эта простая идея проскакивает в одном из правил упомянутой в начале статьи, в другом же правиле мы видим явно противоречащую рекомендацию:
Также тут можно заметить лишний семиколон (semicolon, точку с запятой). Единственная причина его появления в этом месте - слепое следование правилам стайл-гайда, не понимая его принципов. В многострочных правилах, это действительно необходимо, чтобы добавляемые в конец строки не приводили к изменению уже существующих. Например:
2. Не сваливать все яйца (код) в одну корзину (файл/директорию).
Если вам кажется, что в коде не хватает так называемых "секций", то скорее всего вы подобрались к верхнему порогу восприятия, когда, уже сложно находить нужные его участки. В этом случае естественным желанием является создание оглавления. Но оглавление в виде комментариев в начале файла не сравнится с оглавлением в виде списка файлов в директории. Располагая код в иерархии файловой системы вы довольно неплохо можете упорядочивать всё прибывающее число сущностей. Примерно то же самое вы скорее всего делаете и в рантайме, располагая код в иерархии неймспейсов, так что нет никакой причины иметь для одной сущности разные пространства имён: в рантайме и в файловой системе. Проще говоря, имена и иерархия директорий должна соответствовать именам и иерархии пространств имён.Часто можно встретить размещение файлов в нескольких больших корзинах: "все картинки", "все скрипты", "все стили". И по мере роста проекта, в каждой из них появляется иерархия, частично одинаковая, но и с неизбежными отличиями. Задумайтесь: а так ли важен тип файла? Пространства имён куда важнее. Так зачем нужны эти типизированные корзины? Не лучше ли все файлы одного модуля хранить рядом, в одной директории, какими бы ни были их типы? Тем более, что типы могут меняться. Сравните:
3. Язык программирования - принципиально не естественный язык.
В отличие от письменной речи, которая читается строго последовательно, программный код на современных языках программирования представляет из себя двухмерную структуру. В них зачастую нет, например, необходимости ставить точки (семиколоны) в конце предложений:5. Полные и одинаковые имена одной сущности в разных местах
Поиск по имени - довольно частая операция при работе с незнакомым кодом, поэтому важно писать код так, чтобы по имени можно было легко найти место, где оно определяется. Например, вы открыли страничку и обнаружили там класс "b-user__compact". Вам нужно узнать как он там появился. Поиск по строке "b-user__compact" ничего не выдаёт, потому, что имя этого класса нигде целиком не встречается - оно склеивается из кусочков. А всё потому, что кто-то решил уменьшить копипасту ценой усложения дебага://my/user/user.js
My.User.prototype.blockId = 'user'
My.Block.prototype.skinId = 'my-block-compact'
//my/user/user.js
My.User.prototype.blockId = 'my-user'
//my/user/user.styl
.b-user {
@extends .b-block;
color: red;
}
//my/user/user.styl
.my-user {
@extends .my-block;
color: red;
}
/*my/user/user.css*/
.b-user {
color: red;
}
/*my/user/user.css*/
.my-user {
color: red;
}