Better Code Topics - YamamotoDesu/Yamamoto-Notes GitHub Wiki

可能ならIdentifieableを使う

As it is

struct User: Decodable {
    let id: Int
    // ...
}

struct UserDataSource {
    // 引数はIntであればなんでも受け入れるように見えてしまう。
    func loadUser(for id: Int) -> User {
        // 本来はDBなどから取得したものを返すなど
        // ...
    }
}

let user = UserDataSource().loadUser(for: 1)

To be

struct User: Decodable, Identifiable {
    let id: Int
}

struct UserDataSource {
    func loadUser(for id: User.ID) -> User {
        // DBなどから取得したものを返すなど
        // ...
    }
}

オプショナルよりカラのクロージャを利用する

クロージャを関数のデフォルト引数として定義して省略可能にしたい場合、オプショナルのクロージャにするのではなく、カラのクロージャをデフォルト引数とすることを考えた方が良いでしょう。 その理由のひとつは、オプショナルのクロージャは暗黙的にエスケーピング動作をするためselfの明記を必要としてしまいます。クロージャでselfを明記させられる大きなデメリットは、(必要のある無しに限らず)循環参照を避けるための手段を考慮させられることでしょう。直接的な表現をすると、クロージャでselfを書かされるなら、弱参照にしなければいけないと思い込んでしまうことがデメリットです。 リスト1.30には、具体例としてカラのクロージャを引数とするメソッドと、オプショナルなクロージャを引数とするメソッドを持つ型のソースコードを示します。

struct BoolInteractor {
    // カラのクロージャをデフォルト引数とする
    func perform(closure: (Bool) -> () = { _ in }) {
        closure(Bool.random())
    }

    // オプショナルなクロージャをデフォルト引数とする
    func execute(closure: ((Bool) -> ())? = nil) {
        closure?(Bool.random()) // closure!()にするのはミス
    }
}