Если я правильно понимаю, что IO C, это означает, что любой фреймворк или модуль, который вы конфигурируете, чтобы управлять вашими функциональными возможностями, должен иметь возможность управлять вашим кодом в случае необходимости (Ref: Martin Flower IO C Блог ). Это означает, что управление основано на фреймворке.
Я просматривал замечательный блог Future and Promises in Combine . Блог в самом начале говорит, что обработка асинхронного поведения обратными вызовами или замыканиями нарушает IO C. Я вроде не согласен с этим утверждением, но просто хочу уточнить мое понимание.
Сценарий:
Я создал TestFramework
, который обрабатывает некоторые функциональные возможности для пользователя платформы.
public class TestFramework {
typealias UpdatedFrameworkData = (FrameworkData?) -> Void
var giveUpdatedValues: (() -> UpdatedFrameworkData)?
init() { }
private func someAction() {
var updatedValuesCallback = giveUpdatedValues?()
updatedValuesCallback = { [weak self] updatedFrameworkData in
// Perform some action
}
}
}
Теперь у меня есть класс, который использует эту платформу
class FrameworkUser {
let framework: TestFramework = TestFramework()
var updatedValuesCallback: TestFramework.UpdatedFrameworkData?
init() {
setupBinding()
}
private func setupBinding() {
updatedValuesCallback = framework.giveUpdatedValues?()
}
private func getUpdatedData(completion: @escaping TestFramework.UpdatedFrameworkData) {
// Return some data
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.updatedValuesCallback?(self.getFrameworkData())
}
}
private func getFrameworkData() -> FrameworkData? {
nil
}
}
Каркасу иногда может потребоваться работать с обновленными данными, а не с устаревшими данными. Если вы наблюдаете, мой фреймворк все еще может контролировать функциональность того, когда получать обновленные данные через прослушиватель, предоставленный пользователем. Пользователь предоставляет данные посредством асинхронного обратного вызова в платформу.
Итак, в этом случае я не достигаю IO C с помощью обратных вызовов или я что-то упускаю?
РЕДАКТИРОВАТЬ:
Я сделал небольшую ошибку в приведенном выше коде привязки установки. Пользователь по-прежнему вызывает платформу для предоставления обновленных значений.
Я внес следующие изменения в свой код выше, чтобы выяснить, что асинхронная обработка программы обратными вызовами действительно нарушает принципы IO C. Описанный выше метод setupBinding()
неверен в том, как он связывается с обратным вызовом Framework. Это должно было выглядеть примерно так:
private func setupBinding() {
framework.giveUpdatedValues = {
return getUpdatedData() // This won't work
}
}
Чтобы следовать принципам IO C, пользователь должен привязать свой код к обратному вызову платформы. Вышеприведенный код просто не будет работать, потому что вы не можете просто вернуть экранирующее закрытие из функции, и это закрытие будет выполнено через некоторое время.