Обратный вызов нарушает инверсию контроля - PullRequest
1 голос
/ 18 апреля 2020

Если я правильно понимаю, что 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, пользователь должен привязать свой код к обратному вызову платформы. Вышеприведенный код просто не будет работать, потому что вы не можете просто вернуть экранирующее закрытие из функции, и это закрытие будет выполнено через некоторое время.

1 Ответ

0 голосов
/ 19 апреля 2020

Замыкание и протокол семантически идентичны, даже если они синтаксически различны. Если замыкания нарушают IO C, то и протоколы тоже. Поскольку пример IO C в classi c использует протокол, это означает, что замыкания, будучи семантически одинаковыми, не нарушают его.

Чтобы показать, что они одинаковы:

protocol FrameworkDelegate { 
    func myFunc(data: Int)
}

class Framework {
    weak var delegate: FrameworkDelegate?

    func example() {
        delegate?.myFunc(5)
}

против

class Framework {
    var delegate: ((Int) -> Void)?

    func example() {
        delegate(5)
    }
}

Единственное различие между двумя приведенными выше примерами кода состоит в том, какой объект гарантирует, что delegate не деиницируется. В обоих случаях пользователь Framework определяет , что происходит , в то время как тип платформы определяет, когда будет вызван «метод делегата».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...