Skip to content

Принципы разработки библиотеки о2

Vladimir Grinenko edited this page Apr 10, 2015 · 1 revision

Простота использования

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

Минимализм

Следует делать пересечение, а не объединение потребностей, создавать минимально необходимый набор функциональности. Когда возникает вопрос, как сделать, лучше выбрать тот вариант, который решает задачу меньшим количеством кода, меньшим набором БЭМ-сущностей, проще в поддержке и т.д. Необходимо стремиться сокращать API и писать лаконичный код.

Покрытие тестами

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

Консистентность

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

Разделение API на приватное и публичное

Приватное API блока не используется снаружи этого блока. Публичное API следует делать, по возможности, минималистичным и не выставлять наружу лишнее. Важно указывать в документации способ использования публичного API — в BEMJSON, в JS или обоими способами. Публичное API можно менять только при необходимости с выпуском новой мажорной версии. В рамках одной мажорной версии публичное API не должно меняться (должны соблюдаться правила семантического версионирования http://semver.org/).

Явное лучше неявного в JS API

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

Шоткаты в BEMJSON API

Явное лучше неявного. Однако, в некоторых случаях допустимо использование шоткатов в API. Абстрактные куски BEMJSON следует передавать только там, где это допустимо (например, когда какая-то сущность является враппером/контейнером по своей семантике). Для сложных блоков, где генерация контента является внутренним API, следует создавать шоткаты и игнорировать поле content. Это уменьшает объем входящего BEMJSON и позволяет безболезненно менять внутреннее устройство сложных блоков.

БЭМ-предметная область

БЭМ-события vs. события на изменение модификаторов Всё, что может выражаться через БЭМ-сущность, должно выражаться через БЭМ-сущность. Вместо подписки на БЭМ-событие другого блока, следует подписываться на установку модификатора этого блока.

Модификаторы vs. кастомные поля

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

Мобильные платформы и адаптивная вёрстка

В библиотеке реализуется поддержка мобильных платформ. Адаптивная вёрстка, напротив, не используется. Библиотека должна работать во всех поддерживаемых браузерах. Код на уровне common и desktop должен хорошо работать на touch-устройствах.

Композиция vs. наследование vs. делегирование

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

Автоматизация процессов

По возможности следует автоматизировать все повторяющиеся действия, такие как инлайниг картинок, расстановка префиксов, копирование стилей и т.д.

Bleeding edge

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

Оптимизация

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

Тонкая настройка

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

Селекторы в контексте темы

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

Явные умолчания

Умолчания — это внешнее API. Они должны быть явно задекларированы и не должны ломаться. Изменение умолчаний — мажорное изменение, поэтому к внедрению умолчаний в библиотеке следует относиться с осторожностью. Неявные умолчания в библиотеке приводят к рискам в их поддержке. Любые изменения умолчаний ломают обратную совместимость.

==========================================================================

Дизайнерские гайды (см. пункт "Минимализм")

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

Инкапсуляция (нужно нормально сформулировать)

Некая богатая область инкапсулируется в какую-то отдельную часть и используется без знания подробностей её реализации. Общий код выражается в виде самостоятельных блоков и используется в других блоках вместо копирования и повторной реализации функциональности (пример про блоки control и control-group из bem-components). Блок взаимодействует только с подмешанными и вложенными блоками, но не лезет наружу и в соседние блоки.

Обработка ошибок (вообще непонятно)

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

BEMJSON API: узкое API (см. пункт "Минимализм")

Не оверпроектируем API, не придумываем кейсы, не подкладываем в коде какие-то решения для всех возможных кейсов. Лучше рассматривать преценденты каждый раз отдельно, придумывать какую-то расширенную версию API, явно спрашивать у пользователя, как именно он хочет использовать блок, явно это учитывать и программировать, чем делать это про запас. Чтобы все эти прецеденты заранее не предусматривать, мы делаем все наоборот — по минимуму. Нужно принимать набор параметров максимально простым, предусмотренным способом. При этом помним про консистентность при придумывании названий кастомных полей. Мы не делаем библиотеку, которая позволит выразить любые странные кейсы — все это можно реализовать перекрытием шаблонов/скриптов на своем уровне. Копим прецеденты, пока они не наберут критическую массу и тогда мы будем думать о том, чтобы добавить это в библиотеку. Сами не сочиняем, единичных пользователей не удовлетворяем. Если желающих много — мы фичу добавим. Мы специально сужаем API для того, чтобы только допустимое было возможно.

*** (унести в contribution guide) Мы направлены не на расширение, а на сохранение границ. Когда к нам приходят с новым блоком/фичей, мы задаем вопрос: а точно ли этот блок нужен в библиотеке? А точно ли такая вариативность нужна этому блоку? Не лучше ли сделать отдельный блок в своей отдельной библиотеке?

Clone this wiki locally