既存のオブジェクトに拡張子を追加するSwiftファイルに名前を付けるためのベストプラクティスは何ですか?


165

言語仕様に記載されているように、拡張機能を使用して既存のSwiftオブジェクトタイプに拡張機能を追加することができます。

その結果、次のような拡張機能を作成することが可能です。

extension String {
    var utf8data:NSData {
        return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    }
}

しかし、そのような拡張子を含むSwiftソースファイルの最良の命名規則は何ですか?

以前extendedtype+categoryname.m、Objective-Cガイドで説明されいるように、この規則はObjective-Cタイプに使用するものでした。しかし、Swiftの例にはカテゴリ名String.swiftがなく、それを呼び出すのは適切ではないようです。

だから問題は:上記のString拡張子が与えられた場合、迅速なソースファイルは何と呼ばれるべきですか?


4
これはコードレビューの質問ではありません-この特定の例については気にしません。迅速な命名規則が何であるかを知りたいのです。
AlBlue、2014年

2
命名規則はありません。私たちが続けなければならない唯一のことは、常にClassName+ExtensionName形式に従っているObjective-Cのカテゴリであり、あまりにも多くの人々がまだ使用しているとは思えません。その上、クラスと拡張機能を一緒に定義する代わりに、またはFooAbleTypesインスタンスのようにファイルにわかりやすい名前を付けて、集合的に定義するのではなく、それは不格好だと思います。
CodaFi 2014年

4
ありません何の命名規則は、まだ。ここに考えがあります:すべてのグローバル拡張を1つのにまとめExtensions.swiftます。そうすれば、それらを追跡できなくなり、コードベースの初心者はすぐにそれらに気づくでしょう。そして、私は彼らが必要としているファイルにワンオフ拡張プライベートを維持することを好むだろう。
アンドリュー・

1
Andrewが言うように、標準的な命名慣習はまだありません-したがって、この質問は、新しく形成されたコミュニティーがいくつかの提案されたアイデアに来ることができるように、具体的に意見を得るために求められました。
AlBlue

1
私の意見では、単一のextensions.swiftファイルを使用する方法です。内部の構造を整理し(独自の方法で)、必要なものを簡単に見つけます。単一のファイルは、さまざまなプロジェクトからコピーまたはリンクするのが簡単で、忘れ物はありません。
ヨースト、2016

回答:


202

私が見たほとんどの例は、Objective-Cアプローチを模倣しています。上記の拡張の例は次のようになります。

String+UTF8Data.swift

利点は、命名規則により、それが拡張であること、およびどのクラスが拡張されているかを簡単に理解できることです。

を使用したExtensions.swift場合の問題StringExtensions.swiftは、ファイルの内容を見ずに名前でファイルの目的を推測できないことです。

xxxable.swiftJavaで使用されているアプローチを使用すると、メソッドのみを定義するプロトコルまたは拡張機能で問題なく機能します。しかし、繰り返しになりますが、上記の例では属性を定義しているため、UTF8Dataable.swift文法的にはあまり意味がありません。


1
命名規則によって何が拡張されているかは推測できますが、IHMOは不必要な複雑化です。大量の<name> + <extention> .swiftファイルではなく、プロジェクトごとに通常使用する単一のextensions.swiftファイルを保持します。ファイルは内部で構成されており、拡張された特定のクラスを簡単に見つけることができます。
Yohst 2016

18
この回答<name> + <extention> .swiftは、Xcode 8でコアデータのNSManagedObjectサブクラスを作成するときに、Xcodeが実際に行う方法です。例:Foo + CoreDataProperties.swift。
ジェリークリノック2016

4
拡張機能が複数のメソッドを実装している場合はどうなりますか?
AlexVPerl 2017年

2
できるだけ説明的にしてください。たとえば、フィルターを適用するためのさまざまな機能を含むImageの拡張機能がある場合は、Image + Filters.swiftという名前を付けます。拡張機能の関連グループには異なるファイルを使用しても問題ありません。関連するものをグループ化し、無関係なものは分離します。人生は良くなります。
picciano 2017

の規則を使用している場合、たとえば、ExtendedType+Functionality.swiftすべてのString拡張子をフォルダーの下の独自のサブフォルダー(StringまたはまたはString Extensions)にソートすることは良い習慣Extensionsですか?または、Extensionsフォルダの下の同じレベルにすべての拡張ファイルを保存する方が良いですか?
ノアワイルダー

8

Swift規約はありません。単純にする:

StringExtensions.swift

拡張するクラスごとに1つのファイルを作成します。すべての拡張子に単一のファイルを使用すると、すぐにジャングルになります。


8
これは特に再利用できるようには見えません。
ケラー

1
と比べて?
Mike Taverne、2016年

3
単一の(または明確に関連性のある)目的を果たすクラス拡張の単一(または密結合)ファイルと比較して。「StringExtensions」のようなものは、汎用の文字列のサニタイズからアプリ固有のロジックまですべてを含むことができるように聞こえます。Cocoaの命名規則は、実装ではなく機能に依存しています。「StringExtensions」は後者を示すと主張します。命名規則はさておき、私は確かにObjCで受け入れられた答えを好みますが、Swiftではモジュールのためにさらに優れたアプローチのように見えます。
ケラー

2
それは理にかなっている。私は、再利用が問題にならない単一のアプリについて考えていました。たとえば、拡張機能として使用したい無関係な文字列関数がいくつかあるとします。1つのファイルを作成してそこにすべての関数を配置するか、関数ごとに1つのファイルを作成します。その場合、私は単一ファイルの単純さが好きです。しかし、あなたの推論は健全です。ありがとう。
Mike Taverne 2016年

ここで追加されたものがすべての文字列に自然に適用される場合(つまり、例として「trimRight()」)、これは完全に理にかなっています。それがよりユースケース固有のものである場合(つまり、「formatAccountNumber()」)、ファイルは「Strings + AccountFormatting.swift」である必要があり、ファイルが乱雑にならないように実際に使用される場所のみにスコープする必要があります。 「文字列」は他の場所でAPIを表示します。
マークA.ドノホー

1

StringExtensions.swift追加するファイルが多すぎてファイルをString+utf8Data.swiftandのようなものに分割するまで、私は好みますString+Encrypt.swift

もう1つ、類似のファイルを1つに結合すると、ビルドがより高速になります。Optimizing-Swift-Build-Timesを参照してください


1
同じことに対して2つのファイル命名規則があります。それは悪いことだと思います。
意味の問題

@ meaning-matters場合によります。この2つの命名規則はよく知られており、Apple Documentsによって推奨されています。好きなようにしてください。
DawnSong

ネーミングとコード[フォーマット]のバリエーションを制限することにより、より多くのプログラマーが優雅さを追求してくれることを願っています。
意味の問題

@ meaning-mattersエレガンスには2つの側面があります。これは、Cのような言語で中かっこをどのように記述するかについて、物議を醸す古典的な問題のようなものです。それは取るに足らないことなので、ほとんどの人が同意するまで、1つを選択して必須にする必要はないと思います。
DawnSong

私は一貫性の優雅さを意味しました:拡張子に名前を付ける1つの方法を使用するか、中括弧を配置する1つの方法を使用します。それから、さまざまな中括弧スタイルの可読性には測定可能な違いがあると思います。だから、それは「つまらない」とはまったく思いません。
意味の問題

0

チームが合意した一般的およびその他の拡張機能のセットがある場合は、Extensions.swiftがKeep-It-Simpleの第1レベルのソリューションとして機能するようにまとめます。ただし、複雑さが増すか、拡張機能が複雑になるにつれて、複雑さをカプセル化するための階層が必要になります。そのような状況では、次の例を使用して練習することをお勧めします。

と呼ばれるバックエンドと会話するクラスがありましたServer。2つの異なるターゲットアプリをカバーするように大きくなり始めました。一部の人々は大きなファイルが好きですが、論理的には拡張子で分割されます。私の好みは、各ファイルを比較的短く保つことなので、次の解決策を選択しました。 ServerもともとCloudAdapterProtocolそのすべてのメソッドに準拠し、実装しました。私がしたことは、下位のプロトコルを参照するようにして、プロトコルを階層に変えることでした:

protocol CloudAdapterProtocol: ReggyCloudProtocol, ProReggyCloudProtocol {
    var server: CloudServer {
        get set
    }
    func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void)
}

Server.swift、私が持っています

import Foundation
import UIKit
import Alamofire
import AlamofireImage

class Server: CloudAdapterProtocol {
.
.
func getServerApiVersion(handler: @escaping (String?, Error?) -> Swift.Void) {
.
.
}

Server.swift次に、サーバーを設定してAPIバージョンを取得するためのコアサーバーAPIを実装します。実際の作業は2つのファイルに分割されます。

Server_ReggyCloudProtocol.swift
Server_ProReggyCloudProtocol.swift

これらはそれぞれのプロトコルを実装します。

これは、他のファイル(この例ではAlamofireの場合)にインポート宣言を含める必要があることを意味しますが、私の見解ではインターフェースを分離するという点でクリーンなソリューションです。

このアプローチは、外部で指定されたクラスだけでなく、独自のクラスでも同様に機能すると思います。


0

なぜこれは議論でさえあるのですか?すべてのサブクラスを_Subclasses.swiftというファイルに配置する必要があります。私はそうは思いません。Swiftにはモジュールベースの名前間隔があります。よく知られているSwiftクラスを拡張するには、その目的に固有のファイルが必要です。UIViewExtensions.swiftであるファイルを作成する大規模なチームがあり、それが目的を示さず、開発者を混乱させ、ビルドしないプロジェクトで簡単に複製される可能性があります。Objective-Cの命名規則は適切に機能し、Swiftに実際の名前間隔ができるまでは、これが最善の方法です。


私の場合、 'placeIn(UIView)'メソッドなど、すべて/すべてのUIViewクラスに対してそのファイルで定義された拡張が意味をなすのであれば、UIViewExtensions.swiftと呼ばれるファイルを持つことは完全に理にかなっていると思います。それが用途固有である場合(つまり、アプリの一部のみ、たとえばカスタムビューの装飾について)、UIView + CustomDecoration.swiftを実行します。ポイントは、 'UIViewExtensions目的がすべてのUIViewの一般的な拡張機能である場合、目的を表さない.swift
Mark A. Donohoe

0

あちこちにコメントを追加するのではなく、1つの回答ですべてのコメントをここに表示します。

個人的には、拡張性のあるオブジェクトのAPI表面を乱雑にすることなく、優れた使いやすさと明確さの両方を提供するハイブリッドアプローチを採用しています。

たとえば、andのように、任意の文字列で使用できるようになっているものであれば何でも使用できます。StringExtensions.swifttrimRight()removeBlankLines()

私のような拡張機能を持っていた場合しかし、formatAsAccountNumber()それは考えていないそのファイルに行く「口座番号」は、自然に任意の/すべての文字列のみのアカウントのコンテキストで理にかなっているに適用されるものではありませんので。その場合は、私が呼ばれるファイルを作成しますStrings+AccountFormatting.swiftでも多分かStrings+CustomFormatting.swiftformatAsAccountNumber()実際にそれをフォーマットするには、いくつかの種類/かの方法がある場合、関数。

実際、最後の例では、私は最初にそのような拡張機能を使用しないよう積極的にチームを説得しました。AccountNumberFormatter.format(String)代わりに、StringAPIサーフェスにまったく触れないようにする必要がないため、代わりにそのようなものを奨励します。例外は、その拡張子を、それが使用されているのと同じファイルで定義した場合ですが、それでも、独自のファイル名はありません。


0

私は+それが拡張機能を含んでいるという事実に下線を引くことを好む:

String+Extensions.swift

ファイルが大きくなりすぎた場合は、目的ごとに分割できます。

String+UTF8Data.swift

String+Encrypt.swift

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.