今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

Swiftコードのネストされた命名規則

Swift コードでのネストされた命名規則#

Swift では、他の型とのネストされた命名をサポートしていますが、専用の命名キーワードはまだありません。以下では、型のネストを使用してコードの構造を最適化する方法を見ていきます。

ほとんどの Swift 開発者は、実際の名前を持つ型を構造上の名前として使用することに慣れています。例えば、PostTextFormatterOption(投稿をフォーマットするための Text Formatter 型のオプション)です。これは、Objective-C や C で培った恐ろしい命名の習慣が Swift に持ち込まれたためかもしれません。

以下では、上記で述べた型を例にして、Post、PostTextFormatter、PostTextFormatterOption の実装を見てみましょう:

struct Post {
    let id: Int
    let author: User
    let title: String
    let text: String
}

class PostTextFormatter {
    private let options: Set
    
    init(options: Set) {
        self.options = options
    }

    func formatTitle(for post: Post) -> String {
        return post.title.formatted(withOptions: options)
    }

    func formatText(for post: Post) -> String {
        return post.text.formatted(withOptions: options)
    }
}

enum PostTextFormatterOption {
    case highlightNames
    case highlightLinks
}

次に、上記の型を Post のネスト型として使用した場合に何が起こるかを見てみましょう。

struct Post {
    class TextFormatter {
        enum Option {
            case highlightNames
            case highlightLinks
        }

        private let options: Set

        init(options: Set) {
            self.options = options
        }

        func formatTitle(for post: Post) -> String {
            return post.title.formatted(withOptions: options)
        }

        func formatText(for post: Post) -> String {
            return post.text.formatted(withOptions: options)
        }
    }

    let id: Int
    let author: User
    let title: String
    let text: String
}

上記のネスト型の大きな利点は、一目で型間の構造と関係がわかることです。また、冗長な初期化コードが減少し、より短く読みやすくなります(options パラメータの型が Set<PostTextFormatterOption> から Set< Option > に変更されます)。

呼び出し階層もより簡潔で明確になります - Post に関連するすべてが Post.namespace になります。投稿のテキストのフォーマットは次のようになります:

let formatter = Post.TextFormatter(options: [.highlightLinks])
let text = formatter.formatText(for: post)

ただし、ネストされた型を使用することには無視できない欠点もあります。コードが「逆さま」に見えるためです。親型の実際の内容が一番下に押し込まれてしまいます。この問題を修正してみましょう。ネストされた型のコードを上記から下記に移動します(区別しやすくするために、いくつかの MARK も追加します)。

struct Post {
    let id: Int
    let author: User
    let title: String
    let text: String

    // MARK: - TextFormatter
    class TextFormatter {
        private let options: Set

        init(options: Set) {
            self.options = options
        }

        func formatTitle(for post: Post) -> String {
            return post.title.formatted(withOptions: options)
        }

        func formatText(for post: Post) -> String {
            return post.text.formatted(withOptions: options)
        }

        // MARK: - Option
        enum Option {
            case highlightNames
            case highlightLinks
        }
    }
}

ネストされた型を上にするか下にするかは、純粋に個人の好みです。私は親型の内容を上に置くのが好きです - 同時にネストされた型の利便性も享受できます。

実際には、Swift では他のいくつかの方法で命名やネストされた型を実現することができます。

拡張を使用したネストされた型の実装#

もう 1 つのネストされた型の実装方法は、拡張を使用することです。この方法では、実装と呼び出しの際に階層関係を保ち、各種型を明確に分離することができます。

以下のようになります:

struct Post {
    let id: Int
    let author: User
    let title: String
    let text: String
}

extension Post {
    class TextFormatter {
        private let options: Set

        init(options: Set) {
            self.options = options
        }

        func formatTitle(for post: Post) -> String {
            return post.title.formatted(withOptions: options)
        }

        func formatText(for post: Post) -> String {
            return post.text.formatted(withOptions: options)
        }
    }
}

extension Post.TextFormatter {
    enum Option {
        case highlightNames
        case highlightLinks
    }
}

typealias の使用#

typealias を使用することもできます。元のコードに typealias を追加して、ネストされた型のようなコードを実現します(実際にはネストされた型ではありません)。この方法は実装上はネストされた階層関係を持たないものの、冗長なコードが減少し、ネストされた型を使用する場合と同様の呼び出し方法になります。

以下のコードです:

struct Post {
    typealias TextFormatter = PostTextFormatter

    let id: Int
    let author: User
    let title: String
    let text: String
}

class PostTextFormatter {
    typealias Option = PostTextFormatterOption

    private let options: Set

    init(options: Set) {
        self.options = options
    }

    func formatTitle(for post: Post) -> String {
        return post.title.formatted(withOptions: options)
    }

    func formatText(for post: Post) -> String {
        return post.text.formatted(withOptions: options)
    }
}

enum PostTextFormatterOption {
    case highlightNames
    case highlightLinks
}

最後に#

ネストされた型を使用すると、エレガントな構造と階層を持つコードを書くことができ、さまざまな型間の関係がより明確になります - 実装上も呼び出し上もです。

ただし、実装方法の違いによって、さまざまな課題や副作用が発生する可能性があるため、適切な実装を選択することが重要だと思います。美しいコードを作るために。

あなたはどう思いますか?上記のテクニックのうち、どれを好みますか?または他の方法がありますか?ご意見やご質問は、Twitter@johnsundellまでお寄せください。

お読みいただきありがとうございました!🚀

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。