Я не принимал участия в разработке методологии БЭМ или популярных сегодня схем именования БЭМ-сущностей (БЭМ-сущностями называют блоки, элементы и модификаторы — «кирпичики» для построения внешнего вида HTML-страниц по методологии БЭМ). Но у меня есть некоторые предположения о том, что могло учитываться при разработке этих схем именования. Данная статья имеет некоторую связь с предыдущей моей статьей на Хабре, которая называется «PowerShell: классическая схема именования в БЭМ и регулярные выражения».
Ограничение диапазона возможных символов
Вообще, при разработке какого-либо синтаксиса, как мне кажется, чем меньше символов используется, тем легче потом изучить этот синтаксис, написать парсер, меньше может быть совершено ошибок при использовании этого синтаксиса и так далее. По идее, это верно и при разработке схем именования для методологии БЭМ.
Отсюда — использование в именах БЭМ-сущностей ограниченного диапазона возможных символов из символов, доступных в Юникоде: [a-zA-Z0-9_-]
или даже [a-z_-]
(в последнем случае используются буквы только в нижнем регистре, а арабские цифры не используются).
Некоторые возмущаются, почему при этом используется только латиница, а не, к примеру, и/или буквы русского алфавита. Главная причина этого в том, что сейчас английский язык в среде программистов (и не только) является языком международного общения. Исходя из вышеописанного принципа ограничения символов, выбираем только один язык общения. Исходя из того, что английский — язык международного общения в среде программистов, выбираем латиницу.
Далее в этой статье в примерах я буду использовать буквы русского алфавита, но это лишь для наглядности, так как данная статья рассчитана на русскоязычных.
Разделители
В названиях БЭМ-сущностей, если исходить из расшифровки аббревиатуры БЭМ, может максимально присутствовать три части: часть с названием блока, часть с названием элемента и часть с названием модификатора.
В имени класса CSS, являющемся именем блока, присутствует только часть с названием блока. В имени класса CSS, являющемся именем элемента, присутствует две части: часть с названием блока и часть с названием элемента. В имени класса CSS, являющемся именем модификатора блока, присутствует две части: часть с именем блока и часть с именем модификатора. В имени класса CSS, являющемся именем модификатора элемента, присутствуют все три части: часть с именем блока, часть с именем элемента и часть с именем модификатора.
Чтобы разделять эти разные части в одном имени, нужны разделители. Очевидно, что разработчики схем именования для методологии БЭМ откинули возможность использования экранирования символов, чтобы не усложнять синтаксис. Поэтому символы, используемые для имен БЭМ-сущностей, разделили на две группы: символы для названий частей имен БЭМ-сущностей и символы для разделителей. Поскольку экранирования символов не предусмотрено, эти две группы символов не должны пересекаться.
Для разделителей, понятно, нельзя использовать пробельные символы (пробел, символ горизонтальной табуляции, символы новой строки), так как они запрещены в именах классов CSS на уровне языка HTML.
Традиционно вместо пробельных символов в программировании в именах используются символ подчеркивания _
или символ дефиса-минуса -
.
Количество разделителей
Исходя из принципа ограничения диапазона используемых символов, описанного выше, было бы логично использовать только один из этих разделителей, например:
первая_вторая_третья
Тогда парсер различал бы эти части так: до первого разделителя — имя блока (первая часть), после первого разделителя до второго разделителя — имя элемента (вторая часть), после второго разделителя — имя модификатора (третья часть).
Но использовать один-единственный разделитель не получится из-за того, что при этом невозможно будет отличить имя модификатора блока от имени элемента, например:
блок_модификатор
блок_элемент
Человек в этом примере легко отличит имя модификатора блока от имени элемента потому, что человек понимает смысл (семантику) слов, используемых для составления этих имен. А простой парсер (мы не хотим усложнять парсер, так как это усложнит работу с разрабатываемым синтаксисом) ориентируется только на разделители. Из-за того, что в обоих этих именах один и тот же разделитель, парсер не сможет понять, где здесь имя модификатора блока, а где — имя элемента.
Таким образом, нам нужно, как минимум, два разделителя, например:
первая_вторая-третья
блок-модификатор
блок_элемент
В примере выше в качестве двух разделителей использованы символ подчеркивания _
и символ дефиса-минуса -
.
Удвоение символа разделителя
Как я понимаю, разработчики схемы именования для методологии БЭМ хотели иметь возможность использовать в любой части имени БЭМ-сущности по нескольку слов. Если ограничение диапазона возможных символов синтаксиса позволяет использовать прописные и строчные буквы алфавита, можно отделить несколько слов в имени перепадом между строчной и прописной буквами, начиная каждое новое слово в имени с прописной (большой) буквы, например:
частьСИменемБлока
частьСИменемЭлемента
частьСИменемМодификатора
ЧастьСИменемБлока
ЧастьСИменемЭлемента
ЧастьСИменемМодификатора
Этот метод именования известен в программировании как «верблюжий регистр» (по-английски «CamelCase»).
Однако, если диапазон возможных символов ограничен только строчными (маленькими) буквами алфавита, то использование верблюжьего регистра для разделения слов в имени невозможно. Поэтому, как я понимаю, было решено использовать для разделения слов в именах разделитель из одного символа (например, символ подчеркивания _
или символ дефиса-минуса -
).
Чтобы не было путаницы между разделителями слов в частях имени БЭМ-сущности с разделителями самих частей, разделители частей пришлось сделать из удвоенных символа подчеркивания __
и/или символа дефиса-минуса --
.
Два типа модификаторов... или один?
Учитывая всё вышеописанное, на Западе распространилась схема именования для методологии БЭМ, которая использует для разделения частей имени БЭМ-сущности два разделителя: двойное подчеркивание __
(для отделения части с именем блока от части с именем элемента) и двойной дефис-минус --
(для отделения части с именем модификатора).
При этом диапазон возможных символов для имен включает и строчные, и прописные буквы латиницы: [a-zA-Z0-9_-]
.
Это позволяет в частях имен БЭМ-сущностей использовать по желанию хоть «верблюжий регистр» (CamelCase), хоть «змеиный регистр» (snake_case), хоть «шашлычный регистр» (kebab-case):
имяВВерблюжьемРегистре
имя_в_змеином_регистре
имя-в-шашлычном-регистре
Эти три способа именования популярны в программировании. «Верблюжий» регистр называют так из-за сходства имени в таком написании с горбами верблюда («горбами» считаются перепады между строчными и прописными буквами в имени). Имя в «змеином» регистре похоже на из_ви_ваю_щую_ся
змею. Имя в «шашлычном» регистре похоже на шампур с на-ни-зан-ны-ми
на него словами (символы дефиса-минуса похожи на выглядывающий из-под мяса шампур, а отдельные слова — на кусочки мяса).
При этом нужно понимать, что разделители слов в частях имени БЭМ-сущности выполняют лишь декоративную функцию, то есть они облегчают чтение имен для человека, но для парсера не имеют значения. Для парсера эти разделители слов никак не выделяются из частей имен БЭМ-сущностей.
Например, следующее имя модификатора элемента (внутри частей имени БЭМ-сущности используется шашлычный регистр):
часть-с-именем-блока__часть-с-именем-элемента--часть-с-именем-модификатора
парсер разделит на три части:
часть-с-именем-блока
часть-с-именем-элемента
часть-с-именем-модификатора
Такая схема именования не дает парсеру возможности выделить два типа модификаторов, а позволяет только один тип модификаторов.
В «классической» схеме именования от компании «Яндекс» предполагается два типа модификаторов: булевый и ключ-значение. Для того, чтобы в модификаторе типа «ключ-значение» парсер отделил ключ от значения, требуется еще один разделитель. В классической схеме именования три разделителя: __
, _
и _
. (Как я понимаю, разделитель --
решили не использовать потому, что его использование может конфликтовать с синтаксисом комментариев в языке HTML.)
Классическая схема разрешает два вышеуказанных типа модификатора, но не разрешает в частях имени БЭМ-сущностей верблюжий регистр и змеиный регистр (разрешается только шашлычный регистр). Верблюжий регистр отбрасывается из-за ограничения диапазона возможных символов только строчными (маленькими) буквами. Змеиный регистр отбрасывается из-за того, что одиночные символы подчеркивания используются для разделения частей имени БЭМ-сущности.
Заключение
Эти соображения у меня появились, когда я изучал возможности расширения «BEM Helper» для редактора «Visual Studio Code». В этом расширении есть возможность задать через настройки только два разделителя: elementSeparator
(отделяет часть с именем блока от части с именем элемента, по умолчанию __
) и modifierSeparator
(отделяет часть с именем модификатора, по умолчанию --
).
То есть вообще игнорируется возможность третьего разделителя, нужного для отделения ключа от значения в части с именем модификатора типа «ключ-значение». (Об этом сообщено автору этого расширения на сайте «GitHub».)
Кроме этого, в качестве первых двух модификаторов не могут использоваться одиночный символ подчеркивания или одиночный символ дефиса-минуса по описанным в статье причинам (нельзя будет использовать змеиный регистр и/или шашлычный регистр в частях имен БЭМ-сущностей, об этом тоже есть отдельное сообщение автору этого расширения на сайте «GitHub»).
Я вообще не нашел в интернетах ни одного инструмента, работающего с классической схемой именования, кроме «родного» пакета инструментов от «Яндекса».
В принципе, я не очень понимаю, зачем нужны два типа модификаторов. Мне кажется, модификатор типа «ключ-значение» можно без проблем заменить булевым из нескольких слов. Например, в классической схеме именования (парсер разделит на четыре части):
блок__элемент_ключ_значение
блок
элемент
ключ
значение
В схеме именования с возможностью использования разных регистров в частях имени БЭМ-сущности (парсер разделит на три части):
блок__элемент--ключ_значение
блок
элемент
ключ_значение
Во втором случае часть ключ_значение
используется как единое целое (в змеином регистре), то есть как в имени булевого модификатора. В данном случае разделитель _
используется в декоративных целях (для удобства чтения человеком), парсер его не видит.
Мне кажется, третий разделитель в имени БЭМ-сущности может пригодиться, если предполагается какое-то использование значения модификатора типа ключ-значение при автоматизации разработки сайта.