{"id":13505,"url":"\/distributions\/13505\/click?bit=1&hash=ca3734639136826288c9056e5c8fa03a05e87c4060ae84df200f2c90f5262470","title":"\u0412\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a? \u0410 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0435 \u0447\u0442\u043e-\u0442\u043e \u0432 \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435 \u043a\u043e\u0434\u0430?","buttonText":"\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c","imageUuid":"f5f0e11f-fefd-52f5-8712-82164a59b7ce","isPaidAndBannersEnabled":false}
IW Group

Модуляризация iOS приложений

Вы знаете, что такое модуляризация? В каких случаях стоит применять такой подход, а в каких – нет?

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

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

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

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

  3. Нехватка финансов. При выделении большего количества времени и ресурсов необходимо тратить большее количество финансов.

И здесь мы вспомним о модуляризации. Модуль – это отдельная независимая функционально законченная часть или фрагмент приложения.

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

Теперь давайте же рассмотрим сами виды модулей и их иерархическую структуру.

Иерархически, модули можно разделить на 3 уровня:

Core Modules - содержат удобные расширения, фасады для работы с системными функциями (например, LAConext), различные переиспользуемые UIKit компоненты и т.п. В нашей практике примером реализации такого модуля является отдельный сервис для сбора и обработки данных.

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

App - основное приложение, связывающее все модули и реализующее роутинг между ними.

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

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

  • Ответственность - модули должны быть ответственны и реализовывать только возложенный на них функционал;

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

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

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

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

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

- файл спецификации *.podspec - обязательно;

- файлы README и LICENSE - опционально;

- исходные файлы в виде *.framework, *.xcframework или набора *.swift и *.xib файлов, или любых других - обязательно.

Метод размещения модуля. Основные 2 способа, которые используем мы при размещении модулей в проекте:

- в виде *.xcodeproj непосредственно в проекте;

- в виде отдельной зависимости, подключенной через менеджер зависимостей (мы используем cocoapods).

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

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

  1. Модуль необходимо размещать в отдельном git-репозитории, который обычно создается в приватном пространстве.

  2. Модуль необходимо расширить добавлением файла спецификации *.podspec.

*.podspec – это файл спецификации, описывающий pod (модуль). Содержит в себе информацию о том, откуда должны быть извлечены исходные данные, общее описание модуля, параметры сборки и общие метаданные.

Наглядный пример синтаксиса podspec-файла:

s.name - имя модуля;

s.version - версия модуля;

s.summary и s.homepage - доп. информация (опционально);

s.author и s.license - информация о разработчике и лицензия (желательно);

s.platform - платформа для использования;

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

s.ios.deployment_target - мин. версия платформы, которую поддерживает модуль (опционально);

s.ios.vendored_frameworks - имя фреймворка, который поставляется в модуле;

spec.source_files - путь на файлы, которые поставляются в модуле;

spec.dependency - имя дополнительной зависимости, необходимой для работы модуля (опционально).

Например, spec.dependency ‘Alamofire’, ‘4.9.3’ определяет, что для работы модуля AuthorizationService необходимо дополнительно установить библиотеку Alamofire версии 4.9.3.

Разместив модуль в git-репозитории и настроив для него файл спецификации, мы можем подключить его в наш проект через менеджер зависимостей cocoapods:

pod AuthorizationService, :git => 'https://gitlab/authorizationservice.git'

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

pod AuthorizationService, :git => 'https://gitlab/authorizationservice.git', :tag => ‘1.2.1’ - загрузка определенной версии модуля по tag

pod AuthorizationService, :git => 'https://gitlab/authorizationservice.git', :branch => ‘dev’ - загрузка определенной версии модуля из конкретного branch

pod AuthorizationService, :git => 'https://gitlab/ametov/authorizationservice.git', :commit => ‘45ae420wf’ - загрузка определенной версии модуля по hash commit

Для регулирования версии достаточно выполнить загрузку модуля посредством команды pod install.

Пришло время подвести итоги. Мы пришли к выводу, что модуляризация привносит в проект ряд технических и организационных преимуществ, а именно:

  1. Масштабируемость - разработка каждого модуля ведется отдельно, имеется возможность расширять команды разработки, которые работают над отдельными модулями и не пересекаются;

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

  3. Связность кода, а точнее ее уменьшение. Модули не пересекаются друг с другом, уменьшение связей и соблюдение code style влечет за собой упрощение разработки и уменьшение входного порога для разработчиков.

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

А вы что думаете о модуляризации?

0
Комментарии
Читать все 0 комментариев
null