ВНЕДРЕНИЕ ЗАВИСИМОСТИ ДЛЯ OBJECTIVE-C И SWIFT, С ТАЙФУНОМ

ЧТО ТАКОЕ ВНЕДРЕНИЕ ЗАВИСИМОСТИ?

Поначалу у многих возникают проблемы с освоением внедрения зависимостей. И я думаю, что часть проблемы в том, что это на самом деле настолько просто, что мы склонны искать что-то более сложное. «Конечно, должно быть что-то еще?!», так сказать. Итак, имея это в виду, представьте, что вы пишете приложение, которое предоставляет отчеты о погоде. Вам нужен облачный сервис (извините за каламбур 😉 ) для предоставления данных, и сначала вы выбираете бесплатный поставщик отчетов о погоде, но в будущем вы хотели бы интегрировать службу погоды с большей точностью и большим количеством функций. Таким образом, как и все хорошие объектно-ориентированные разработчики, вы создаете протокол WeatherClient и изначально подкрепляете его реализацией, основанной на бесплатном онлайн-провайдере данных.

БЕЗ ВНЕДРЕНИЯ ЗАВИСИМОСТИ У ВАС МОЖЕТ БЫТЬ КОНТРОЛЛЕР ПРЕДСТАВЛЕНИЯ, КАК ЭТО:

-(id) init
{
 self = [super init];
 if (self)
 {
 //The class using some collaborating class builds its own assistant.
 //it might be one of several classes using the weatherClient. 
  _weatherClient = [[GoogleWeatherClientImpl alloc] initWithParameters:xyz];
 }
 return self;
}

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

_weatherClient = [GoogleWeatherClient sharedInstance];

С любым из вышеперечисленных подходов, чтобы протестировать ваш контроллер представления, вам теперь нужно одновременно протестировать его сотрудничающий класс (погодный клиент), и это может стать сложным, особенно когда ваше приложение становится более сложным. Представьте себе тестирование класса A, зависит от класса B, зависит от класса C, зависит от… Не очень весело! Конечно, вы можете исправить синглтон с помощью макета или заглушки, но для этого потребуется заглянуть внутрь кода, чтобы найти зависимости. Помимо времени, которое лучше было бы потратить на что-то другое, это в конечном итоге становится тестированием «стеклянного ящика», а не тестированием «черного ящика». Не лучше ли иметь возможность протестировать внешний интерфейс класса, не беспокоясь о том, что происходит внутри? И вы должны помнить об удалении патча в конце тестового случая или рисковать странными поломками других тестов, где трудно определить, в чем может быть реальная проблема. Таким образом, с внедрением зависимостей вместо того, чтобы объекты создавали своих собственных соавторов, мы передаем их экземпляру класса через инициализатор или установщик свойств.

И ТЕПЕРЬ ЭТО ПРОСТО СТАНОВИТСЯ:

-(id) initWithWeatherClient:(id<WeatherClient>)weatherClient
{
 self = [super init];
 if (self)
 {
     _weatherClient = weatherClient;
 }
 return self;
}

ЭТО ВСЕ, ЧТО ОНИ ПОДразумевают под словом «инъекция»?

Да, это так. Прямо сейчас вы можете подумать: «Боже! Довольно причудливое название для чего-то такого простого. Что ж, ты будешь прав. Но давайте посмотрим, что произойдет, когда мы начнем применять этот подход: допустим, вы идентифицируете некоторые жестко запрограммированные сетевые конфигурации в своем GoogleWeatherClient и исправляете это, вместо этого передавая их через метод инициализации. Теперь, если вы хотите использовать этот класс в качестве соавтора в новом классе, скажем, ViewController, то сам ваш GoogleWeatherClient может быть либо жестко зашитой зависимостью, либо внедренной. Чтобы снова получить преимущества внедрения зависимостей, мы повторяем процесс, подтягивая класс и вместе с его собственными зависимостями. И мы продолжаем применять до тех пор, пока у нас не будет логического модуля или «сборки».

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

ПРЕИМУЩЕСТВА ВНЕДРЕНИЯ ЗАВИСИМОСТИ

  • Мы можем заменить другого актера для выполнения данной роли. Если вы хотите перейти от одной реализации класса к другой, вам нужно изменить только одно объявление.
  • Удалив тесную связь, нам не нужно понимать всю проблему сразу, можно легко развивать дизайн нашего приложения по мере развития требований.
  • Классы легче тестировать, потому что мы можем предоставить простые макеты и заглушки вместо конкретных соавторов. Или настоящие соавторы, но настроенные для использования в тестовом сценарии.
  • Это способствует разделению интересов и четкому договору между классами. Легко увидеть, что нужно каждому классу для выполнения своей работы.
  • Мы можем компоновать архитектуру приложения, используя заглушки — простейшую возможную реализацию роли — так, чтобы мы могли быстро увидеть сквозной сценарий использования. Сделав это, мы можем возложить на других членов команды ответственность за заполнение этих заглушек для реальных реализаций, и они могут делать это, не ломая приложение во время работы и не влияя на других членов команды.

ВАШИ ВАРИАНТЫ ВНЕДРЕНИЯ ЗАВИСИМОСТИ

Если вы продолжите использовать паттерн «Внедрение зависимостей» (при условии, что вы не один из оставшихся «плоскоземельцев», которые верят, что Objective-C каким-то волшебным образом смягчает потребность в здравом смысле: «О, я не занимаюсь внедрением зависимостей, Я использую крутые кластеры классов!»), то в основном есть два варианта:

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

Итак, если идти по маршруту фреймворка, то за последние три года в мире Objective-C было довольно много действий. На самом деле сейчас существует около 15 фреймворков внедрения зависимостей, многие из которых идут по стопам Google Guice. Авторы проделали большую работу (особенно хорошо возражение). Однако мне нужен подход, который позволяет следующее:

ЦЕЛИ И ОСОБЕННОСТИ ПРОЕКТИРОВАНИЯ

  • Неинвазивный. Никаких макросов или XML не требуется.
  • Использует мощный инструментарий времени выполнения ObjC.
  • Никаких волшебных строк — поддерживает рефакторинг IDE, завершение кода и проверку во время компиляции.
  • Обеспечивает полную модульность и инкапсуляцию деталей конфигурации. Пусть ваша архитектура расскажет историю.
  • Зависимости объявляются в любом порядке. (Порядок, который имеет смысл для людей).
  • Упрощает использование нескольких конфигураций одного и того же базового класса или протокола.
  • Поддерживает внедрение контроллеров представления и интеграцию с раскадровкой.
  • Поддерживает как инициализатор, так и внедрение свойств, а также управление жизненным циклом.
  • Мощные функции управления памятью. Предоставляет предварительно настроенные объекты без дополнительных затрат памяти на синглтоны.
  • Поддержка циклических зависимостей.
  • Худой. Занимает очень мало места, поэтому подходит для устройств с ограниченным процессором и памятью.
  • Всего весит всего 3000 строк кода. Проверено в боевых условиях — используется во всех видах приложений из Appstore.

ПРИМЕР

Вы можете изучить образец Typhoon на языке Objective-C. здесь.

ВЫВОД

Внедрение зависимостей — это полезный шаблон проектирования, и для него полезно иметь вспомогательную библиотеку. Сегодня есть несколько очень хороших чистых библиотек Swift Dependency Injection, между тем, Тайфун используется в более чем 6000 приложений. Некоторые из них включают Amex, Accor Hotels, Audible.com, Etihad, easyJet, Grindr, Hootsuite, Lazada, Kobo, Shalom и Singapore Airlines.

Удачного кодирования 😃

Похожие записи

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

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