Ответ 1
Дядя Боб Чистая архитектура абсолютно применима к iOS, Swift и Obj-C. Архитектура является языковой агностикой. Дядя Боб сам кодирует в основном на Java, но в своих разговорах он редко упоминает Java. Все его слайды даже не показывают никакого кода. Это архитектура, предназначенная для любого проекта.
Почему я так уверен? Потому что я изучал MVC, MVVM, ReactiveCocoa и Clean Architecture в течение 2 лет. Я, как чистая архитектура, лучше всего. Я протестировал его, переведя 7 образцов Apple на использование чистой архитектуры. Я использовал этот подход исключительно более года. Он работает лучше каждый раз.
Некоторые из преимуществ:
- Найти и исправить ошибки быстрее и проще.
- Извлеките бизнес-логику из контроллеров представлений в интеракторы.
- Извлечение логики представления из контроллеров представления в презентаторы.
- С уверенностью меняйте существующее поведение с быстрыми и поддерживаемыми модульными тестами.
- Напишите более короткие методы с единой ответственностью.
- Разделить зависимости классов с четкими установленными границами.
Мы также добавили компонент маршрутизатора, чтобы мы могли использовать несколько раскадровки. Больше конфликтов.
Тестирование единиц записи значительно упрощается, потому что мне нужно только проверить методы на границах. Мне не нужно проверять частные методы. Кроме того, мне даже не нужны какие-то насмешливые рамки, потому что писать свои собственные макеты и заглушки становится тривиальным.
Я написал свой опыт за последние 2 года, изучая архитектуру iOS в Clean Swift. Я также собрал некоторые шаблоны Xcode для создания всех компонентов Clean Architecture для сохранения тонны времени.
ОБНОВЛЕНИЕ. Чтобы ответить на вопрос Vizctor Albertos об инъекции зависимостей в комментарии ниже.
Это действительно большой вопрос и требует подробного ответа.
Всегда помните VIP-цикл. В этом случае метод doSomethingOnLoad()
не является граничным методом. Скорее, это внутренний метод, вызываемый только внутри CreateOrderViewController
. В модульном тестировании мы тестируем ожидаемое поведение устройства. Мы даем входные данные, наблюдаем выходы, затем сравниваем результаты с нашими ожиданиями.
Да, я мог бы сделать doSomethingOnLoad()
приватный метод. Но я решил не делать этого. Одна из целей Swift заключается в том, чтобы разработчикам было проще писать код. Все граничные методы уже перечислены во входных и выходных протоколах. Нет необходимости засорять класс внешними частными модификаторами.
Теперь нам нужно проверить это поведение: "CreateOrderViewController
должен что-то делать с загрузкой с данными запроса", так или иначе? Как мы тестируем это, если мы не можем вызвать doSomethingOnLoad()
, потому что это частный метод? Вы вызываете viewDidLoad()
. Метод viewDidLoad()
является граничным методом. Какая граница? Граница между пользователем и контроллером просмотра! Пользователь сделал что-то с устройством, чтобы загрузить его на другой экран. Итак, как же мы тогда вызываем viewDidLoad()
? Вы делаете это так:
let bundle = NSBundle(forClass: self.dynamicType)
let storyboard = UIStoryboard(name: "Main", bundle: bundle)
let createOrderViewController = storyboard.instantiateViewControllerWithIdentifier("CreateOrderViewController") as! CreateOrderViewController
let view = createOrderViewController.view
Просто вызов свойства createOrderViewController.view
вызовет вызов viewDidLoad()
. Я узнал этот трюк давным-давно от кого-то. Но Наташа Робот также недавно упомянула об этом.
Когда мы решаем, что тестировать, очень важно только проверять граничные методы. Если мы тестируем каждый метод класса, тесты становятся чрезвычайно хрупкими. Каждое изменение, которое мы делаем для кода, приведет к разрыву многих, многих тестов. Из-за этого многие люди отказываются.
Или, подумайте об этом так. Когда вы спрашиваете, как издеваться CreateOrderRequest
, сначала спросите, является ли doSomethingOnLoad()
граничным методом, для которого вы должны написать тест. Если нет, то что? В этом случае граничный метод фактически viewDidLoad()
. Вход "когда этот просмотр загружается". Результатом является "вызов этого метода с помощью этого объекта запроса".
Это еще одно преимущество использования Clean Swift. Все ваши граничные методы перечислены в верхней части файла с явно указанными протоколами CreateOrderViewControllerInput
и CreateOrderViewControllerOutput
. Вам не нужно искать в другом месте!
Подумайте, что произойдет, если вы проверили doSomethingOnLoad()
. Вы издеваетесь над объектом запроса, а затем утверждаете, что он равен ожидаемому объекту запроса. Вы издеваетесь над чем-то и сравниваете это. Это как assert(1, 1)
вместо var a=1; assert(a, 1)
. Какой смысл? Слишком много тестов. Слишком хрупкий.
Теперь, когда вы делаете mock CreateOrderRequest
. После того, как вы подтвердите правильность, CreateOrderRequest
может быть сгенерирован компонентом контроллера вида. Когда вы тестируете граничный метод CreateOrderInteractor
doSomething()
, вы затем обманываете CreateOrderRequest
с помощью инъекции зависимостей интерфейса.
Короче говоря, модульное тестирование - это не тестирование каждой единицы класса. Речь идет о тестировании класса как единицы.
Это сдвиг мышления.
Надеюсь, что это поможет!
У меня есть 3 серии статей в Wordpress на разные темы:
- Углубленный просмотр каждого компонента Clean Swift.
- Как разбить сложную бизнес-логику на рабочих и служебных объектов.
- Написание тестов в архитектуре iOS Clean Swift
Какой из них вы хотите услышать больше в первую очередь? Должен ли я поднять серию на тестирование?