Модульность является одним из ключевых принципов разработки программного обеспечения с 1960-х годов. Применение этого принципа приносит в программирование много полезного. Модульность способствует эффективному использованию принципа разделения ответственностей, что ведёт к улучшению возможностей по созданию, многократному использованию, компоновке кода.
В наше время применение принципа модульности в проектировании ПО приняло новую форму, воплотившуюся в компонентах. Это — разработка, основанная на компонентах (Component Driven Development, CDD). Современные библиотеки и фреймворки для разработки пользовательских интерфейсов, такие как React, Vue и Angular, а также CDD-ориентированные инструменты наподобие Bit, позволяют создавать приложения, опираясь на модульные компоненты. В распоряжении программиста оказываются паттерны и инструменты, необходимые для разработки компонентов в изоляции и построения композиций компонентов.
Компонент — это чётко очерченный независимый фрагмент интерфейса приложения. В качестве примеров компонентов можно привести такие сущности, как кнопки, слайдеры, окна для вывода сообщений чатов. Понимая особенности CDD и умея применять этот подход к разработке, мы можем использовать компоненты в качестве основы приложений. Это, при создании программных проектов, даёт нам всё то полезное, что означает применение принципов модульного программирования.
Если присмотреться к тому, что происходит сейчас в сфере веб-компонентов, можно заметить, что CDD становится стандартизированным подходом к разработке фронтенда.
Материал, перевод которого мы сегодня публикуем, представляет собой руководство по разработке, основанной на компонентах.
CDD в разработке пользовательских интерфейсов
Работа в Bit: создание компонентов, их изоляция, многократное использование и совместная работа над ними
Попросту говоря, разработка, основанная на компонентах, представляет собой проектирование приложений посредством создания слабо связанных друг с другом независимых блоков кода. У каждого из них есть интерфейс, предназначенный для организации взаимодействия с другими частями системы. Множество компонентов, объединённых друг с другом посредством композиции, формируют модульное приложение.
Например, применение CDD при создании React-приложений означает, что сначала создают компоненты, формирующие основу приложения, а потом приступают к сборке из них более крупных частей приложения, таких как целые страницы и крупные блоки функционала.
CDD соотносится с атомарным дизайном (вот полезный материал на эту тему) и с подходом к разработке клиентских частей веб-проектов, известным как «микро-фронтенд».
CDD помогает разбить процесс разработки большого проекта на более мелкие процессы разработки отдельных компонентов. Каждый компонент проектируется независимо от остального приложения и создаётся с учётом возможности взаимодействия с другими частями системы. Проектирование каждого компонента в виде самостоятельной сущности даёт разработчику множество полезных возможностей.
Эдди Османи изложил некоторые основные преимущества применения CDD. Он оформил их в виде набора принципов, названного FIRST.
Вот эти принципы:
- Ускорение разработки (Faster development). То, что усилия разработчиков направлены на создание отдельных компонентов, позволяет создавать модульные части приложения с узкоспециализированными API. Это означает, что компоненты можно, с одной стороны, разрабатывать быстро, а с другой — то, что при их разработке легче доводить их до необходимого проекту уровня качества.
- Упрощение поддержки (Simpler maintenance). Когда нужно модифицировать или обновить часть приложения, можно расширить или обновить некий компонент, а не заниматься рефакторингом крупной части приложения. Это можно сравнить с медицинской процедурой, с операцией на отдельном органе, заменяющей операцию, которая предусматривает вмешательство чуть ли не во все части организма.
- Улучшение возможностей по многократному использованию кода (Better reusability). Благодаря использованию принципа разделения ответственностей компоненты, в ходе создания из них готового приложения, могут быть повторно использованы или расширены. Это гораздо лучше, чем необходимость снова и снова их переписывать (вот материал на эту тему).
- Улучшение возможностей по применению методологии TDD (Better TDD). В ходе разработки модульных компонентов гораздо легче, чем при использовании других подходов, реализовывать модульные тесты, нацеленные на проверку узкого функционала компонента. В результате оказывается, что проще тестировать и крупные системы, собранные из компонентов. Дело в том, что при использовании модульного подхода разработчику легче понять то, за что именно отвечает та или иная часть системы.
- Укорочение кривых обучения (Shorter learning curves). Когда разработчику приходится разбираться с новым для него проектом — оказывается, что гораздо легче понять сущность и устройство отдельных компонентов, чем вникнуть в тонкости всего проекта.
- Улучшение возможностей по моделированию систем (Better modeling of the system). Когда система создана из модульных компонентов — разработчику становится легче разобраться с общим устройством системы, понять её и научиться воздействовать на неё.
Инструменты CDD
Если разработка основана на компонентах — это означает, что программисту нужны специализированные инструменты. Такие инструменты направлены на создание компонентов, на их тестирование, на организацию общего доступа к ним и на поддержку совместной работы над ними.
В частности — важно разрабатывать и тестировать компоненты в изоляции. Это позволяет обеспечить их работу в виде самостоятельных единиц, которые могут быть использованы в приложении. Кроме того, важна и поддержка многократного использования компонентов, и возможность организации общего доступа к ним. Это позволяет тому, кто работает в составе команды над неким крупным проектом, не изобретать колесо, которое, в виде некоего компонента, уже изобретено кем-то из членов команды.
Вот несколько полезных инструментов, которые помогут вам организовать работу над проектами в стиле CDD. В одном из следующих разделов мы поговорим об архитектурах проектов, рекомендованных при практической реализации принципов CDD.
▍Bit: индивидуальная и командная разработка компонентов
Bit — это опенсорсный инструмент, созданный, по существу, для поддержки практического применения методологии CDD. Вот видео о Bit. Этот инструмент помогает разрабатывать компоненты, организовывать совместную работу над ними и создавать с их помощью веб-проекты.
Речь идёт о том, что средствами Bit можно изолировать компоненты, которые разрабатываются в рамках некоего проекта. Скажем — в рамках приложения или библиотеки. Bit поддерживает инструменты командной строки, он помогает организовать инкапсуляцию компонентов со всеми их файлами и зависимостями. Bit позволяет разрабатывать и тестировать виртуальные представления инкапсулированных компонентов в изоляции.
Это означает, что компонент, созданный в рамках приложения, можно оснастить всеми его зависимостями, инкапсулировать и превратить в сущность, которую можно использовать и тестировать за пределами приложения.
Далее, Bit позволяет упаковывать самостоятельные, инкапсулированные компоненты и организовывать их совместное использование с помощью облачных средств. Это позволяет командам, работающим над проектами, пользоваться всеми теми компонентами, которые выложены в общий доступ. Сообщество Bit насчитывает порядка 50 тысяч разработчиков. Их усилиями созданы тысячи опенсорсных компонентов, доступных всем желающим.
Разработка проектов с использованием инкапсулированных компонентов
Благодаря возможностям облачной платформы команды разработчиков могут устанавливать опенсорсные компоненты в свои приложения. Члены команд, кроме того, могут предлагать авторам компонентов идеи по улучшению компонентов, делая это прямо из своей рабочей среды. Bit расширяет возможности Git по отслеживанию и синхронизации изменений исходного кода компонентов в различных проектах. Это даёт разработчикам возможность управлять изменениями и обновлениями компонентов.
Bit хранит полное дерево зависимостей компонентов. Это даёт разработчику возможность узнать о том, как обновление компонента может повлиять на зависимые компоненты, о том, что в проекте может оказаться «сломанным» при внесении изменений в некий компонент. Это означает, что благодаря Bit в распоряжении программиста оказывается полномасштабная среда для организации разработки, основанной на компонентах, позволяющая создавать компоненты, тестировать их и организовывать совместную работу над ними и их совместное использование.
Облачные возможности в CDD
Ещё одна полезная возможность Bit заключается в том, что эта платформа позволяет командам разработчиков не только работать со своими компонентами, используя единый интерфейс, но и использовать чужие компоненты, выложенные в общий доступ, и взаимодействовать с авторами этих компонентов.
Дизайнеры интерфейсов, представители заказчиков проектов, а также программисты могут, в ходе совместной работы над проектами, пользоваться едиными визуальными инструментами. Это сокращает разрыв между дизайнерами и программистами. Причём, надо отметить, что в этой ситуации выигрывают не только дизайнеры и программисты, но и конечные пользователи приложений, которые сталкиваются с меньшим количеством неоднородностей и ошибок. Вот, вот и вот — несколько материалов, посвящённых разным аспектам использования Bit.
▍Разработка и исследование UI-компонентов: StoryBook и Styleguidist
StoryBook и Styleguidist — это среды для быстрой разработки элементов пользовательского интерфейса средствами React. Оба эти проекта представляют собой отличные инструменты для ускорения разработки компонентов.
StoryBook
StoryBook — это среда для быстрой разработки UI-компонентов. Она позволяет работать с библиотекой компонентов, просматривать различные состояния компонентов, заниматься интерактивной разработкой и тестированием компонентов.
Работа в StoryBook
StoryBook помогает разрабатывать компоненты в изоляции от приложения. Это способствует улучшению возможностей по многократному использованию компонентов, улучшает тестируемость компонентов.
С помощью StoryBook можно просматривать компоненты, хранящиеся в библиотеке, экспериментировать с их свойствами в интерактивном режиме. Изменения, вносимые в компонент, сразу же, без перезагрузки страницы, визуализируются. Здесь можно найти некоторые примеры компонентов, созданных в StoryBook.
Существуют различные плагины, которые позволяют ускорить процесс разработки компонентов с использованием StoryBook. Это позволяет сократить время, проходящее между изменением кода компонента и формированием его визуального представления. Надо отметить, что StoryBook, помимо React, поддерживает ещё React Native и Vue.js.
React Styleguidist
React Styleguidist — это окружение для разработки компонентов. Эта среда содержит сервер разработки, поддерживающий горячую перезагрузку. В ней имеется и интерактивная система управления стилями, выводящая propTypes
компонентов и дающая в распоряжение разработчика редактируемые примеры использования компонентов, основанные на .md-файлах.
React Styleguidist
Эта платформа поддерживает JavaScript ES6, Flow и TypeScript. Она умеет, без дополнительных настроек, работать с Create React App. Styleguidist обладает возможностями по автоматическому созданию документации к компонентам. Это позволяет данной системе играть роль визуального портала документации к компонентам, работой над которыми занимается некая команда.
Если вам интересны проекты наподобие StoryBook и Styleguidist — то вам, возможно, стоит взглянуть и на проект React Live, разработкой которого занимается компания Formidable.
Разница между StoryBook и Styleguidist
В ходе работы со StoryBook программист пишет «истории» (stories) в JavaScript-файлах. При работе со Stuleguidist он пишет «примеры» (examples) в Markdown-файлах. В то время как StoryBook показывает лишь один вариант компонента за один раз, Styleguidist может вывести несколько вариантов разных компонентов. StoryBook отлично подходит для анализа различных состояний компонентов, а Styleguidist — для формирования документации по компонентам и демонстрации возможностей компонентов.
Архитектурные решения, применяемые при использовании методологии CDD
Работа в стиле CDD означает, что при разработке приложений в первую очередь создают компоненты. При этом такие компоненты должны быть как можно более независимыми друг от друга. Это означает, что разработчик не просто создаёт некий «набор компонентов». Он ещё и реализует так называемую дизайн-систему компонентов пользовательского интерфейса.
Компоненты можно создавать как в рамках самого приложения (то есть — в том же проекте, репозитории), так и в формате отдельного проекта (репозитория) — в виде библиотеки компонентов.
Инструменты наподобие Bit позволяют изолировать и инкапсулировать компоненты. Это даёт разработчику широкие возможности по созданию, тестированию, повторному использованию компонентов, позволяет дорабатывать их где угодно — независимо от того, где именно они были созданы.
Если говорить о том, что применение CDD предусматривает разработку компонентов в виде первого шага работы над неким проектом, то это подразумевает и то, что компоненты стремятся делать подходящими для многократного использования. Это позволяет применять их при создании различных приложений. Поэтому разработчику нужно выяснить то, как именно ему нужно поступать для того, чтобы создавать подобные компоненты. Нет ничего хуже, чем потратить полгода на то, чтобы создать библиотеку, которой, в итоге, никто не будет пользоваться. Подобное, к сожалению, происходит со многими командами.
Зачем создавать библиотеку компонентов?
Буду с вами честен: Git-репозитории не были задуманы с учётом возможности хранения в них кода атомарных компонентов, которые планируется совместно использовать в различных проектах. Для решения этой задачи не подходят и менеджеры пакетов. И то и другое создано, что совершенно понятно, для поддержки репозиториев кода. Компоненты же — это не репозитории.
Совместное использование компонента в различных проектах
Именно поэтому, в том случае, если нужно взять компонент из одного приложения и использовать его в другом приложении, требуется создать новый репозиторий. Для того чтобы избавить себя от ненужной работы по созданию отдельного репозитория для каждого подобного компонента, большинство команд создаёт один совместно используемый репозиторий, предназначенный для хранения 20-30 компонентов.
При использовании инструмента вроде Bit, в библиотеке компонентов, как таковой, необходимости не возникает. Подобные инструменты позволяют загрузить компонент из приложения в облако и внедрять этот компонент в другие проекты. Если сравнить такую схему работы с традиционными репозиториями, то можно сказать, что это — нечто вроде сравнения музыкального компакт-диска и Spotify. Правда, если вам близка идея разработки и использования библиотек компонентов — возможности таких платформ, как Bit и StoryBook, позволят вам работать и с библиотеками.
При проектировании библиотеки необходимо принять несколько ключевых решений. Ниже будут рассмотрены некоторые важные принципы, которые вам в этом помогут. Основной смысл этих принципов сводится к тому, что ваша задача заключается в том, чтобы создавать независимые компоненты. Остальные этапы работы над проектом напоминают сборку конструктора Лего. Если же принцип разработки независимых компонентов не соблюдается — в один прекрасный день можно столкнуться с неприятностями. Неприятности начнутся тогда, тогда, когда кому-нибудь понадобится нечто, отличающееся от того, что присутствует в библиотеке. Собственно говоря, когда такое происходит, команды и перестают пользоваться библиотеками компонентов.
Предположим, вы всё же решили создать библиотеку компонентов. Если так — предлагаем вам несколько советов, которые вам в этом помогут.
7 принципов разработки качественных CDD-ориентированных библиотек
- Стандарты. Каких стандартов разработки вы придерживаетесь, создавая библиотеку? Где расположены компоненты? Где находятся тесты? А стили? Каким стеком технологий вы пользуетесь? Например — планируете ли применять TypeScript? Как делятся компоненты? Состоит ли, например, компонент «Таблица» из «Строк» и «Ячеек»? Состоит ли панель с вкладками из отдельных вкладок (те же вопросы можно задать и по отношению к другим подобным сущностям)? Полагаю, вы уже поняли смысл этой рекомендации. Очень важно, кроме того, подключать к процессу формирования стандартов дизайнеров. Это позволит обеспечить то, что библиотека окажется достаточно гибкой и будет соответствовать тем требованиям дизайна, которые могут появиться в будущем.
- Стилизация. Как вы планируете стилизовать компоненты? Будете ли вы связывать с каждым компонентом соответствующий CSS-код? Если это так — что произойдёт в том случае, когда дизайнеру понадобится изменить что-то лишь для отдельного приложения, использующего компонент? Возможно, для улучшения отделения компонентов от стилей стоит использовать библиотеки, реализующие технологию CSS in JS? Может быть, стоит поискать и ещё какой-то подход к стилизации? Например, с помощью Bit можно выделить темы в виде отдельных компонентов. Такие темы можно применять к компонентам, реализующим некую логику. Это позволяет создавать приложения, в которых оформление и логика сочетаются именно так, как нужно разработчику. Перед вами — пример чрезвычайной гибкости систем, построенных с использованием принципа модульности.
- Тестирование. Как вы собираетесь тестировать компоненты, входящие в состав библиотеки? С помощью Jest и Enzyme? К подбору хорошей комбинации инструментов тестирования компонентов нужно подойти со всей ответственностью. Это позволит таким инструментам помочь вам в деле реализации методологии CDD. Неудачный выбор инструментов будет мешать работе. Модульные тесты — это хорошо. Но они должны проверять функциональные API компонентов, а не детали их реализации. Интеграционные и сквозные тесты — это так же важно, как и модульные тесты. Методология TDD хорошо показывает себя при применении в проектах, использующих CDD.
- Процесс сборки кода. Код нужно компилировать. Как вы собираетесь организовать процесс сборки кода для своей библиотеки? Как будут осуществляться релизы? Вы планируете просто копировать код из приложения и вставлять в библиотеку (вероятно, немного его дорабатывая)? Собираетесь ли вы определять конфигурации сборки для каждого компонента (Lerna) и применять соответствующие механизмы к коду перед его публикацией? Планируете ли вы использовать, скажем, уже не раз упомянутый Bit для того, чтобы настраивать процессы сборки, применяемые ко всем (или к отдельным) компонентам? Если вы слишком сильно усложните процесс сборки — заниматься разработкой станет тяжелее, ухудшится модульность проекта. Кривая обучения, необходимая для участия в разработке, станет слишком крутой.
- Управление кодом. Кто является владельцем библиотеки? В достаточно больших организациях часто имеются команды фронтенд-разработчиков и, иногда, архитекторы. Они занимаются созданием продукта, называемого «общей библиотекой». Другие команды фронтенд-разработчиков создают приложения, пользуясь подобными библиотеками. При такой схеме взаимодействия очень важным оказывается использование системы, позволяющей удобно находить нужные компоненты (Bit, Storybook). А ещё важнее, пожалуй, наличие механизма, благодаря которому пользователи компонентов могут предлагать улучшения компонентов. Если подобных механизмов в организации не будет, то команды-пользователи компонентов не захотят связывать свои приложения с библиотекой и ожидать принятия их PR, чего они вполне могут и не дождаться. Не нужно принуждать программистов к чему-либо. Нужно налаживать здоровое сотрудничество. Если к этому не стремиться — никто не будет пользоваться библиотекой. Программисты будут просто копировать и вставлять код, и никто с этим ничего не сделает. Причём, это будет вашей ошибкой. Если вы работаете в маленькой команде — чётко определитесь с тем, кто управляет кодом. Даже если никто не занимается кодовой базой всё время — выделите несколько специалистов, которые будут поддерживать этот код. Остальные будут делать PR — так же, как это происходит в GitHub.
- Нахождение компонентов. Библиотека не принесёт особой пользы в том случае, если программисты не смогут находить необходимые им компоненты, не смогут узнать о том, как эти компоненты работают, и не смогут воспользоваться ими в своём коде. Встроенными возможностями, помогающими разработчикам находить компоненты, обладает Bit. В дополнение к этой платформе (или вместо неё) можно воспользоваться возможностями StoryBook или каким-то собственным решением. Определённую пользу в решении вопросов подбора компонентов и работы с документацией к ним может оказать платформа Codesandbox.
- Организация совместной работы над компонентами. Что происходит в том случае, когда некий разработчик (возможно — из другой команды, или даже из другой страны) нуждается в изменении чего-либо, относящегося к компоненту из вашей библиотеки? Нужно ли ему будет углубляться в создание PR для вашей библиотеки, и, скрестив пальцы, ждать результатов. Для многих разработчиков это слишком сложно, они не будут этим заниматься даже в том случае, если вы попытаетесь как-то на них повлиять. Гораздо лучше будет, если вы задействуете некую платформу, которая упрощает совместную работу над проектами.
Помните о том, что библиотека — это всего лишь некий репозиторий, существующий ради того, чтобы наладить совместное использование компонентов в различных проектах. Библиотеки не особенно хорошо масштабируются, код в них устаревает, они страдают от различных проблем. Возможно, лучше просто организовать прямой доступ к компонентам, предназначенным для совместного использования, с использованием некоей облачной платформы.
Преимущества, которые даёт командам разработчиков применение CDD
Команды, применяющие принцип CDD, получают преимущества в виде ускорения разработки, повышения уровня многократной используемости кода, в виде улучшения TDD и наличия единообразного интерфейса дизайн-системы.
Программисты могут писать код, имея доступ к уже написанным компонентам и совместно заниматься внесением изменений в компоненты. Разработка новых возможностей или приложений сводится к настройке и расширению базовых компонентов. Это, кроме того, способствует предотвращению возникновения ошибок, которые обнаруживаются лишь в продакшне.
Совместное использование кода означает, кроме прочего, сокращение объёмов кода, который нужно поддерживать. Это позволяет программистам сосредоточиться на создании чего-то нового. Когда приложения разрабатывают, опираясь на компоненты, это стандартизирует работу за счёт того, что все пользуются единой базой строительных блоков приложений. Компонентный подход, кроме того, способствует гибкости работы.
Некоторые команды сообщают о том, что их рабочие процессы стали до 60% быстрее благодаря использованию модульных компонентов, основанных на дизайн-системах, реализованных в виде наборов React-компонентов. Некоторые организации обнаружили, что благодаря внедрению CDD они могут удалить примерно 30% кода из своих кодовых баз.
Компонентный подход внедряют такие компании, как Uber, Airbnb, Shopify и другие.
Итоги
Лично я не удивлён тем, что применение CDD повышает эффективность разработки ПО. По словам Брэда Фроста, автора книги об атомарном дизайне, модульность и композиция — это важнейшие понятия в биологии, экономике, и во многих других областях. Модульность в применении к разработке программного обеспечения даёт скорость, надёжность, простоту разработки. Она способствует многократному использованию сущностей, улучшает тестируемость и расширяемость кода. Модульность даёт разработчику возможность применения композиции при создании сложных систем. Всё это очень хорошо влияет на процесс и на результаты разработки приложений.
Уважаемые читатели! Применяете ли вы методологию CDD при работе над своими проектами?
Автор: ru_vds