Перейти к содержимому

С помощью чего разработчики управляют версионирование приложений

  • автор:

Инструмент автоматизации управления версиями

Всегда было интересно, что такое версии продукта и как ими управлять? Как автоматизировать управление версиями разработки? Прошу под кат.

Меня зовут Роман. Я разработчик в очень интересной компании Softeq, где каждый человек — вдохновитель.

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

Версионирование

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

image

Семантическое версионирование

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

Рассмотрим, каким образом формируется номер Семантической версии.

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

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

Проект был успешно реализован. Через некоторое время у заказчика возникла идея по развитию данной технологии автоматизации бизнеса. В предстоящих планах были совершенно новые сервисы: формирование команды строителей, внутренняя социальная сеть, внутренний обмен документами и прочее. Разработчики проявили высокую компетентность, и через некоторое время архитектура проекта была спроектирована для решения и новых, и старых задач. Новая архитектура проекта внесла обратно несовместимые изменения. Повысилась Major версия проекта.

Полная картина выглядит так, но с ней вы сталкиваетесь редко.

Итак, мы представляем, что же такое версии продукта. Но как ими управлять?
Давайте рассмотрим инструмент автоматизации управления версиями.

Versionings

Управление версиями производится при помощи командной строки:

versionings --semver=[ | patch | prepatch | minor | preminor | premajor | prerelease | major] --branch=[ | any-hyphen-case-less-100-characters-string] [--push] 

Актуальная версия продукта хранится как в ./package.json файле проекта, так и в Git тегах и ветке повышения версии. Автоматизация имеет возможность интеграции с различными сторонними инструментами — управление версиями производится через CLI команду.

Давайте рассмотрим пример повышения версии продукта.

Действия

Ведется разработка проекта актуальной версии 2.5.3. Разработка нового сервиса проекта ведется в ветке crm-user-service. Завершилась разработка сервиса, закоммичены все изменения и принято решение о повышении минорной версии:

versionings --semver=minor --branch=user-service --push 

Результат

  1. Новая ветка: version/minor/v2.6.0—user-service
  2. Изменение версии в ./package.json : 2.5.3 ->2.6.0
  3. Commit новой версии продукта в веткe version/minor/v2.6.0—user-service
  4. Push новой ветки с реализацией сервиса и повышенной версии продукта.
  5. Создание Pull Request для ветки version/minor/v2.6.0—user-service, которая содержит реализацию сервиса и повышенную версию продукта

Замечания

  • Инструмент автоматизации ориентирован на Unix среду
  • Пример проекта для построения библиотеки является абстрактным, для общего представления версионирования.

Всем продуктивного настроения и отличного дня!

Управление версиями и релизами мобильных приложений с использованием Gitflow и Semantic Versioning.

Управление версиями и релизами мобильных приложений — важнейший аспект разработки, позволяющий командам разработчиков эффективно взаимодействовать, управлять изменениями и своевременно предоставлять пользователям обновления. В этой статье мы рассмотрим подход, сочетающий два мощных инструмента — Gitflow и Semantic Versioning — для достижения оптимального контроля версий в мобильных приложениях.

james-harrison-UVMPVIRCF5w-unsplash | Управление версиями и релизами мобильных приложений с использованием Gitflow и Semantic Versioning.

Что такое Gitflow

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

Основными ветвями Gitflow являются master и develop. Ветка master представляет собой стабильную, беспроблемную версию приложения, а ветка develop используется для разработки новых функций и исправлений.

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

Semantic Versioning

Semantic Versioning (семантическое версионирование) — это система нумерации версий, которая помогает стандартизировать обозначение изменений в вашем приложении. Она состоит из трех чисел, разделенных точками: MAJOR.MINOR.PATCH. Например, 1.0.2.

MAJOR — увеличивается, когда внесены несовместимые изменения API.
MINOR — увеличивается, когда добавлены новые функции, совместимые с предыдущими версиями.
PATCH — увеличивается, когда внесены обратносовместимые исправления ошибок.

Semantic Versioning помогает избегать конфликтов при обновлении приложения для пользователей, так как оно позволяет четко определить характер изменений в новой версии.

Интеграция Gitflow и Semantic Versioning

Интеграция Gitflow и Semantic Versioning позволяет разработчикам легко отслеживать изменения кода и автоматически определять версии приложений в зависимости от характера этих изменений. Это упрощает процесс разработки и повышает его прозрачность.

Когда команда разработчиков завершает работу над новой функцией или исправлением, они могут создать соответствующий патч или ветку функций в соответствии с Gitflow. Затем они увеличивают версию приложения в соответствии с принципом Semantic Versioning и сливают изменения в соответствующую ветку (например, develop или master).

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

-Создать ветку функций или исправлений.
-Внести необходимые изменения в код.
-Обновить версию приложения в соответствии с семантическим версионированием.
-Доработать ветку и объединить ее с целевой веткой.
-Запустить автоматизированный процесс сборки и развертывания новой версии.

Автоматизация и CI/CD

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

Среди популярных инструментов CI/CD можно назвать Jenkins, Travis CI, CircleCI и GitLab CI/CD. Они позволяют настраивать и автоматизировать процессы выпуска в соответствии с вашими потребностями.

Интеграция CI/CD с Gitflow и Semantic Versioning позволяет автоматически повышать версии приложений при создании новых релизов, запускать тесты и развертывать приложения на целевых платформах с минимальными усилиями.

Мониторинг и обратная связь

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

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

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

Документация и коммуникация

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

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

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

Непрерывное совершенствование

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

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

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

Материал подготовлен командой appfox.ru

Кодовая база (Codebase): основа вашего программного проекта

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

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

Что такое кодовая база

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

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

Структура

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

  1. Модульность: разделите код на логические модули или компоненты, чтобы облегчить понимание и поддержку кода. Каждый модуль должен отвечать только за определенную функциональность или задачу.
  2. Консистентность: следуйте установленным соглашениям и стандартам кодирования в вашей кодовой базе. Это облегчит чтение и понимание кода другим разработчикам, а также сделает его более поддерживаемым.
  3. Документация: включите комментарии и документацию к коду, чтобы объяснить его назначение, использование и особенности. Это поможет не только вам, но и другим разработчикам, которые могут работать с вашей кодовой базой.
  4. Разделение ответственности: каждая часть кода должна отвечать только за свою конкретную функцию или задачу. Избегайте создания избыточного кода или перекрывания функциональности между различными компонентами.

Версионирование

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

Существует множество систем контроля версий, таких как Git, Mercurial, SVN. Они позволяют фиксировать изменения в коде, создавать ветки разработки, сливать изменения и управлять репозиториями.

Пример использования системы контроля версий Git для версионирования кодовой базы:

  1. Инициализация репозитория: создайте новый репозиторий Git с помощью команды `git init`. Это создаст пустой репозиторий, который будет отслеживать изменения в вашей кодовой базе.
  2. Добавление файлов: добавьте файлы вашей кодовой базы в репозиторий с помощью команды `git add `. Вы можете добавить файлы по одному или использовать шаблоны для добавления всех файлов в определенном каталоге.
  3. Фиксация изменений: зафиксируйте изменения в вашей кодовой базе с помощью команды `git commit -m «Описание изменений»`. Коммиты представляют собой снимки состояния вашей кодовой базы в определенный момент времени.
  4. Ветвление и слияние: используйте команды `git branch` и `git merge` для создания и объединения веток разработки. Ветвление позволяет вам работать над различными функциональностями или исправлениями багов параллельно и затем объединить изменения в главную ветку.

Зависимости и библиотеки

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

Пример использования зависимостей и библиотек:

  1. Установка зависимостей: используйте инструмент управления зависимостями, такой как npm для JavaScript или pip для Python, чтобы установить необходимые библиотеки. Например, команда `npm install ` установит пакет из реестра npm.
  2. Импорт и использование: вы можете импортировать и использовать функциональность, предоставляемую библиотеками, в вашем коде. Например, в JavaScript вы можете использовать `import` для импорта модуля из установленной зависимости.
  3. Управление версиями: убедитесь, что вы управляете версиями зависимостей, чтобы обеспечить совместимость и предотвратить возникновение конфликтов. Используйте файлы `package.json` или `requirements.txt`, чтобы явно указать версии зависимостей.

Инструменты и процессы

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

  1. Среды разработки: используйте среды разработки, такие как Visual Studio Code, IntelliJ IDEA или Eclipse, для удобной работы с кодом, отладки и автозаполнения.
  2. Системы непрерывной интеграции: настройте системы непрерывной интеграции, такие как Jenkins, Travis CI или GitLab CI, чтобы автоматически собирать, тестировать и развертывать вашу кодовую базу при каждом изменении кода.
  3. Статический анализ кода: используйте инструменты статического анализа кода, такие как ESLint или SonarQube, для обнаружения потенциальных проблем в вашем коде, таких как ошибки стиля, потенциальные уязвимости или неэффективные конструкции.
  4. Автоматизированное тестирование: напишите автоматизированные тесты, чтобы обеспечить корректное функционирование вашего приложения и предотвратить появление ошибок. Используйте фреймворки для модульного тестирования, функционального тестирования или тестирования пользовательского интерфейса.

Заключение

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

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

Шесть принципов, которые помогут лучше писать модули для iOS-приложений

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

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

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

1. Ограничьте поверхность API

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

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

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

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

Еще одна проблема с большой поверхностью API — в том, что она дороже: поверхность нуждается в обслуживании. Кроме того, чем больше поверхность, тем выше вероятность появления ошибок. А исправление ошибок обходится дорого.

Следствие: предоставить единственный способ выполнения операции

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

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

  1. Вводит клиента в заблуждение. Какой из альтернатив ему придерживаться?
  2. Может привести к ошибкам, которые необходимо исправить.
  3. Вводит двойные стандарты. В следующий раз, когда придется внедрять какую-либо функцию, мы потратим время на то, чтобы выбрать реализацию. Кроме того, так удваивается объем работы.

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

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

2. Отдавайте должное семантическому версионированию

Семантическое версионирование — это стандарт, используемый в промышленной разработке для аннотирования конкретной версии SDK. Он основан на трех числах, разделенных точками: M.m.p.

  1. Первое число — M — обозначает основную (мажорную) версию библиотеки.
  2. Второе число — m — обозначает младшую (минорную) версию библиотеки.
  3. Третье число — p — обозначает патч-версию библиотеки.

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

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

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

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

3. Предоставляйте информативные сообщения об ошибках

Представьте, что нам нужно использовать тип, определенный в библиотеке. Этот тип имеет отказоустойчивый инициализатор. Какую альтернативу вы предпочитаете: инициализатор init , который возвращает nil при сбое, или инициализатор который выдает ошибку, сообщающую вам, почему произошел сбой?

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

struct PInt enum Error: Swift.Error case notPrime 
>

var value: Int

// ПЛОХО: Вызывающая функция не знает, почему происходит сбой инициализации
init?(maybeValue: Int) guard PInt.isPrime(maybeValue) else return nil
>
self.value = maybeValue
>

// ХОРОШО: Если инициализация сбоит, вызывающая функция знает, что ей необходимо передать простое целое число
init(value: Int) throws guard PInt.isPrime(value) else throw Error.notPrime
>
self.value = value
>

// Взято и адаптировано из источника: https://en.wikipedia.org/wiki/Primality_test#C#
static func isPrime(_ value: Int) -> Bool if [2, 3].contains(value) return true
>

if value <= 1 || value % 2 == 0 || value % 3 == 0 return false
>

for i in stride(from: 5, through: Int(sqrt(Double(value))), by: 6) if value % i == 0 || value % (i + 2) == 0 return false
>
>

return true
>
>

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

Следствие: никаких падений

Как следствие, внутренний модуль никогда не должен намеренно вызывать падений (crash). Да, некоторые случаи структурно недоступны, и может возникнуть соблазн для упрощения кода воспользоваться ! или fatalError .

Я предлагаю избегать таких решений по крайней мере по двум причинам:

  1. Нет ничего неприятнее, чем видеть, как “падает” твое приложение и обнаруживать, что это происходит из-за сторонней библиотеки.
  2. Усложняется тестирование вашего кода. Невозможно чисто протестировать ветку кода, которая содержит fatalError .

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

func fatalError( 
_ message: @autoclosure () -> String = String(),
file: StaticString = #file,
line: UInt = #line
) -> Never

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

4. Всегда уважайте клиентское приложение

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

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

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

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

class SDKNavigationDelegate: NSObject, UINavigationControllerDelegate  
weak private(set) var navigationController: UINavigationController?
weak private(set) var appDelegate: UINavigationControllerDelegate?

init(navigationController: UINavigationController) self.navigationController = navigationController
self.appDelegate = navigationController.delegate
super.init()
navigationController.delegate = self
>

func unload() self.navigationController?.delegate = self.appDelegate
>

// MARK: - Реализация делегата
func navigationController(
_ navigationController: UINavigationController,
didShow viewController: UIViewController,
animated: Bool
) guard self.viewControllerFromLibrary(viewController: viewController) else self.appDelegate?.navigationController?(
navigationController,
didShow: viewController,
animated: animated
)
return
>

// выполняется какой-нибудь специфичный для SDK код
>

// MARK: Помощник
private func viewControllerFromLibrary(viewController: UIViewController) -> Bool let sdkBundle = Bundle(for: Self.self)
let vcBundle = Bundle(for: type(of: viewController))

return sdkBundle === vcBundle
>

>

В этом примере мы можем видеть, как обернуть UINavigationControllerDelegate .

Во-первых, понадобится пара свойств для отслеживания navigationController и appDelegate . Они должны быть weak , чтобы избежать циклических ссылок. После сохранения этих объектов в свойствах можно безопасно изменить delegate .

Метод unload необходимо вызывать, когда SDK вот-вот будет сброшена/закрыта. В этом методе мы просто заменяем текущий делегат тем, который ранее сохранили.

Наконец, в методах делегата мы:

  1. Проверяем, действительно ли нужно выполнять какую-то операцию в SDK.
  2. Если нет, то вызываем исходный метод appDelegate и позволяем приложению вести себя так, как если бы SDK не было.

5. Всегда проверяйте входные данные

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

Мой любимый способ убедиться в этом — использовать четко определенный тип, например creditCardNumber , который включает некоторую проверку при инициализации и выдает информативную ошибку, если что-то пойдет не так (согласно третьему принципу).

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

struct CreditCardNumber typealias StringLiteralType = String 

enum Error: Swift.Error case empty
case wrongNumberOfCharacters
case characterMustBeDigts
>

let number: String

init(number: String) throws guard !number.isEmpty else throw Error.empty
>

guard number.count == 16 else throw Error.wrongNumberOfCharacters
>

guard number.allSatisfy(\.isNumber) else throw Error.characterMustBeDigts
>

self.number = number
>
>

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

У этого подхода есть еще два преимущества:

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

6. Пишите четкую и краткую документацию

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

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

Хорошая документация включает в себя:

  • Что делает метод.
  • Каковы его параметры.
  • Что он возвращает.
  • Какие ошибки он выдает и когда он это делает.
  • Любые конкретные детали, которые могут быть полезны клиенту: например, сложность.

Заключение

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

  1. Ограничьте поверхность API и предоставьте только один способ выполнения операции.
  2. Соблюдайте семантическое версионирование.
  3. Предоставляйте информативные сообщения об ошибках — и никогда не допускайте падений.
  4. Всегда уважайте приложение клиента.
  5. Проверяйте входные данные.
  6. Пишите содержательную документацию.

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

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

  • Почему разработчики не должны пользоваться MacBook Pro?
  • Тонкости представления нижнего всплывающего экрана в iOS 15
  • Скрытые нововведения в iOS 15

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *