Как я могу разбить большой init (из-за большого количества вычислений), для лучшей читаемости? - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть класс, скажем, 100 свойств (преувеличение). Большинство этих свойств должны быть вычислены на основе пользовательских предпочтений.

Эти свойства не изменятся после инициализации, поэтому я хотел бы запустить вычисления один раз в начале и установить результаты в let properties

Пользователи могут устанавливать десятки предпочтений, и в зависимости от заданной комбинации предпочтений свойства здесь изменятся при инициализации объекта.

let prop1:String
let prop2:String
...
let prop100:String

init(maybeRelevantArg:Int, maybeRelevantArg2:String) {
    var proposedProp1 = ""
    //20 lines of logic to compute proposedProp1, referencing preferences and maybeRelevantArgs
    self.prop1 = proposedProp1

    var proposedProp2 = ""
    //20 lines of logic to compute proposedProp2, referencing preferences and maybeRelevantArgs
    self.prop2 = proposedProp2
}

Вы поймете, в этот момент мои init будут иметь сотни строк, в основном не читаемые.

Я хотел бы разделить эти куски логики на отдельные методы, что-то вроде:

init(maybeRelevantArg:Int, maybeRelevantArg2:String) {
    self.computeAndSetProp1(relevantArg:maybeRelevantArg1)
    self.computeAndSetProp2(relevantArg:maybeRelevantArg2)
}

func computeAndSetProp1(relevantArg:String) {
    var proposedProp1 = ""
    //20 lines of logic to compute proposedProp1, referencing preferences and relevantArgs
    self.prop1 = proposedProp1
}

Таким образом, init гораздо более читабелен, и его легче отлаживать и поддерживать.

Проблема в том, что, очевидно, компилятор не будет рад, что мой init метод явно не инициализирует эти свойства, и я получаю что-то похожее на:

'self' используется до инициализации всех сохраненных свойств

а также внутри computeAndSetProp1() я получу эту ошибку:

нельзя присвоить свойству: prop1 - это постоянная let, 1029 *

Есть ли способ разделить этот большой инициал?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Вы можете сделать функцию computeAndSetProp1() бесплатной (то есть не являющейся частью какого-либо класса), например:

func computeAndSetProp1(relevantArg: String) -> String {
    var proposedProp1 = ""
    //20 lines of logic to compute proposedProp1, referencing preferences and relevantArgs
    return proposedProp1;
}

class someClass: NSObject {
    let prop1 : String
    let prop2 : String
    override init() {
        prop1 =  computeAndSetProp1(relevantArg: "x")
        //...etc.
    }
}

Я бы также порекомендовал посмотреть, можете ли вы обобщить функции computeAndSetProp*, чтобы уменьшить объем кода. Вы всегда можете разместить код на Code Review , чтобы получить больше идей о том, как упростить код.

0 голосов
/ 02 ноября 2018

Один из способов - сохранить параметры init в приватных свойствах let и вычислить их в вычисляемой переменной. Вы также можете использовать приватную (set) lazy var, если хотите, чтобы логика вычислений выполнялась только один раз.

Другая идея может состоять в том, чтобы разбить класс на несколько классов / структур со связанными свойствами, а затем сохранить существующий класс в этих меньших классах / структурах.

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