はじめに
筆者がコーディングやリファクタをするときに意識しているものとして「 引数ラベル 」があります。
これはメソッドの可読性を向上させるために使用され、Swift登場時から仕様として組み込まれている機能です。
ただ、読みはするものの意識的に書くことはない、ということが多いかもしれません。
あくまで所感ですが、各現場で意識的に付与している方は少ないように感じましたので、この機会に使用するシチュエーションやメソッド作成時のポイントなど、筆者の考えを交えて見ていきたいと思います。
サンプル
以下のような numbers
を持つ構造体があるとして、指定した引数の位置にある値を取得するメソッドを作成してみます。
struct Dice {
private static let numbers: [Int] = Array(1...6)
}
引数ラベル: なし(引数のみ)
struct Dice {
...
static func getNumber(index: Int) -> Int {
numbers[index]
}
}
// 呼び出し時: 引数ラベルが表示されるがデフォルトの引数名
let number = Dice.getNumber(index: 1)
print(number) // 2
引数ラベルを書かない通常の書き方です。
「複数あるデータからindexの位置にある値を取得する」ということはなんとなくわかるため、大きな問題はありませんが、読みやすさには少しだけ違和感を感じます。
引数ラベル: あり(
_
: アンダースコア)
struct Dice {
...
static func getNumber(_ index: Int) -> Int {
numbers[index]
}
}
// 呼び出し時: 引数ラベルは表示されない
let number = Dice.getNumber(1)
print(number) // 2
引数ラベル自体を表示しない書き方です。
引数ラベルが表示されないためコードはコンパクトになりますが、getNumber
の引数に「何を指定すればどのような値が取得できるか」がメソッド定義とその処理を確認しないとわかりづらくなっています。
引数ラベル: あり(
at
)
struct Dice {
...
static func getNumber(at index: Int) -> Int {
numbers[index]
}
}
// 呼び出し時: 引数ラベルが表示される
let number = Dice.getNumber(at: 1)
print(number) // 2
引数ラベルを指定する書き方です。
at
自体は、比較的狭い場所や地点を表す時に用いる英単語です。
よく見るところでは、TableViewの持つ cellForRow(at:)
がそのように定義されていますね。
FYI: cellForRow(at:)
引数ラベルの有無による見え方の違い
上記3つを比較すると、(数文字ではありますが)index
と at
では文字数も減りますし、より適切な前置詞の付与により英語としても自然な形で読みやすくなっています。
必ずしも文字数が少なければいいということではありませんが、意味の伝わりやすい単語を指定できるとよさそうです。
一方で、 _(アンダースコア)
を選択すると、引数ラベルが無いことにより、渡すべき値が少し見えづらい気がします。
※サンプルでは構造体の命名がDice(サイコロ)となっているため、なんとなく指定した位置にあるサイコロの目の数値を取得できる気がしますね。
引数ラベルが不要と思われる場合
あると可読性の向上に繋がる便利な機能ですが、常に必要かと問われればそうではありません。
例えば、以下の場合においては引数ラベルを付与する必要はないかもしれません。
メソッド名自体が意味や目的を明確にしている場合
func calculateSum(_ first: Int, _ second: Int) { }
calculate
+ sum
により「合計を求めること」がメソッド名に加え、引数との組み合わせにより明示的に示されているケースです。
引数の型が意味や目的を明確にしている場合
func addItem(_ item: Item) { }
add
+ item
により「アイテムを追加すること」が明確であるため、ラベルは不要であり、_(アンダースコア)
によって、デフォルトのラベルも不要にできそうです。
また、addItem
ではなくadd
で命名する場合は、そのメソッド自体がItem内で定義されることにより更にシンプルになりそうです。
引数の役割がメソッド名に対して自然な選択である場合
func connectTo(destination: URL) { }
connect
+ to
、そして destination
により「目的地(URL)に接続する」ということが明確ですね。
しかしながら、この場合は引数ラベルを付与して、 func connect(to url: URL)
とする方が筆者は好みです。
よく使うパターン
すべてを提示することはできませんが、筆者が使うことの多いものや使ったことのある引数ラベルのパターンを書いてみます。
// 特定の位置にあるデータの情報を取得する場合
// - 複数データを操作する場合
func getData(at index: Index) -> Data
// 特定のデータの情報を取得する場合
// - enumを用いてピンポイントにデータを指定する場合
func getData(of type: HogeType) -> Data
// 特定のアクションまたは目的のために使用する場合
// - キー操作や、類似項目を持つデータをマップする場合など
func getData(for key: String) -> Data
func getData(for data: OtherData) -> Data
// データを取得するためのソースまたは場所を指定する場合
// - URLからデータを取得する場合
func getData(from url: URL) -> Data
// ある特定の操作や機能を実行するための追加情報を提供する場合
// - データを取得するために細かな設定や情報がある場合
func getData(with configuration: Configuration) -> Data
// ある操作を実行するための基準や手段を指定する場合
// - ソート項目を指定する場合
func getData(by options: Options) -> Data
// ある操作に使用される具体的な手段や方法を指定する場合
// - (自身での使用経験はあまり無いですが)ProtocolやAlgorithmなど
func getData(using protocl: Protocol) -> Data
おわりに
当たり前と言えば当たり前ですが、ほとんどのプログラミング言語は英語を使用しています。
そのため、多少なりとも英語に慣れ親しんでおくと、命名時の助けになることが多いなと感じます。
昨今は翻訳ツールも充実していますし、AIに提案すればより適切なサンプルも提示してくれそうですので、命名にはあまり困らない時代になりましたね。
また、「命名」となるとクラスや構造体、プロトコル、プロパティ、メソッド名等に注目しがちですが、Swiftを触る場合は「 引数ラベル 」にも目を向けることで、コーディングやコードリーディングの助けになるかもしれません。
本記事が最適な引数ラベル選びのヒントとなれば幸いです。