Swift - Dependency Injection для класса, доступ к которому осуществляется глобально - PullRequest
0 голосов
/ 28 апреля 2019

Я переключаю свой стек CoreData на использование внедрения зависимостей, и пока он начинает собираться вместе, я застрял, пытаясь передать контекст управляемого объекта в один из моих классов.Это класс со многими методами, которые используются многими другими классами и называется ApplicationData().Доступ к нему осуществляется следующим образом, который определен вне определения класса:

var AppData = ApplicationData()

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

AppData.uploadRecords()

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

1 Ответ

1 голос
/ 29 апреля 2019

Существует три типа DI, которые чаще всего используются:

  1. инъекция во время инициализации - через параметр init
  2. инъекция через свойство - объявление свойства readwrite, которое устанавливаетсяизвне
  3. внедрение во время вызова - путем передачи зависимости каждому методу, который должен его использовать (кажется, вы думали об этом)

Теперь, если вы используете раскадровки,# 1 довольно сложно достичь, так как у вас нет контроля над инициализатором контроллера.

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

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

Я бы порекомендовал компромиссное решение: объявите свойство как readwrite, это позволит внедритьэто извне, но дайте ему значение по умолчанию.Таким образом, производственный код будет работать, как и раньше, и модульные тесты могут легко внедрить свой объект:

class MyClass {
    // can be injected from outside
    // defaults to the current state
    // value namespaced to avoid name clashes, in case the global variable gets
    // renamed to lower camel case
    var appData = MyApplication.AppData
}
...