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

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

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

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

Есть ряд причин, по которым общая кодовая база полезна. Это сокращает вероятность дублирования кода, но, в частности, вы можете извлечь из этого пользу;

Наличие одной реализации вашей основной логики

Создавая библиотеку для своего основного бизнеса или логики отображения (например, библиотеки компонентов), вы получаете единый источник достоверной информации о том, как будет вести себя ваша услуга или продукт, что обеспечивает согласованное взаимодействие пользователей и разработчиков.

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

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

Вы можете быстро создавать и обновлять приложения

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

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

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

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

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

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

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

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

Вы можете снизить риски обновления на разных уровнях

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

С другой стороны, если риск обновления является внутренним, например, при обновлении основной библиотеки, вы можете убедиться, что ваш формат управления версиями подразумевает то, что представляют собой изменения (например, семантическое управление версиями), но также, если будет обнаружена ошибка, которая повлияет на последующие проект, то разработчики этого проекта могут легко создать тестовый пример, чтобы предоставить команде библиотеки, чтобы помочь им воспроизвести его. Это значительно ускорит время разрешения.

Общая кодовая база — не идеальное решение. Есть несколько вещей, о которых следует помнить при принятии решения о внедрении общей кодовой базы, чтобы убедиться, что в конечном итоге это не нанесет больше вреда, чем принесет ценность.

Затраты на управление зависимостями

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

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

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

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

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

Вы не можете использовать лучшие инструменты для работы

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

Это особенно очевидно на стороне бэкенда, где команды разработчиков часто используют технологические стеки, которые обеспечивают безопасность типов и прирост производительности за счет более низкого уровня, чем язык, такой как JavaScript.

В конечном счете, это очень зависящая от контекста проблема, и вам придется принять решение о том, перевешивают ли повторное использование кода и последовательный опыт разработки эти проблемы.

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

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

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

JavaScript может показаться языком, который «просто работает где угодно», но на самом деле это нюансы, и есть несколько методов, которые необходимо использовать, чтобы гарантировать, что вы не споткнетесь на этих нюансах.

Создавайте изоморфные библиотеки

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

Примером этого может быть то, как обрабатывать чтение файла в среде выполнения браузера, NodeJS и React Native.

В используемом вами браузере вы получаете объект File из ввода загрузки файла в форме, которую затем необходимо прочитать с помощью FileReader, но в NodeJS вы можете просто использовать библиотеку fs для чтения. В React Native вы в конечном итоге используете что-то вроде react-native-fs или expo-file-system для чтения файла, но есть одна оговорка.

В то время как браузер и NodeJS имеют встроенную функциональность base64, в React Native ее нет, что означает, что вам нужно использовать библиотеку или создавать собственную реализацию.

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

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

Разбейте функциональность на разные библиотеки

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

Легко попасть в ловушку, добавляя все больше и больше ответственности в библиотеку, оправдывая ее тем, что она находится на соответствующем уровне, но вы не должны смотреть на «уровень», а вместо этого смотреть на то, чего библиотека хочет достичь. .

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

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

Используйте семантическое управление версиями и закрепите свои зависимости

Если вы какое-то время использовали JavaScript, вы, вероятно, заметили влияние плохо управляемого управления версиями, в основном из-за того, что npm не закрепляет зависимости автоматически, вместо этого позволяя извлекать новые второстепенные версии и версии исправлений, но не новые. основные версии.

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

Чтобы противодействовать этому, вы можете закрепить свои зависимости. Это означает, что нужно удалить префиксы ^ и ~ в версиях package.json и вместо этого просто использовать те версии, которые, как вы знаете, работают.

Подкрепите это фиксацией и использованием файла package-lock.json и созданием артефактов развертывания, и вы снизите большую часть риска, связанного с неопределенностью, вызванной подходом npm по умолчанию.

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

В Semantic Versioning изменения основного, дополнительного значения и значения исправления (например, отформатированные как major.minor.patch ) указывают тип внесенных изменений:

  • Major — это означает, что в новой версии есть критические изменения, и вы должны убедиться, что ваш код полностью работает с этой новой версией.
  • Незначительный — это означает, что новая версия имеет новые функции, но эта функциональность обратно совместима, поэтому вы сможете использовать ее без каких-либо нарушений.
  • Исправление. Это означает, что в новой версии есть некоторые исправления ошибок и улучшения, но они обратно совместимы, так что все должно быть в порядке.

Пишите тесты и документацию

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

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

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

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

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

Существует ряд библиотек документации JavaScript, но jsdoc, по-видимому, чаще всего используется для превращения комментариев кода в удобочитаемый веб-сайт и имеет поддержку плагинов, таких как поддержка уценки, и jsdoc-mermaid, которая позволяет использовать графики для иллюстрации концепций.

Первоначально опубликовано на https://averment.digital 22 сентября 2020 г.