[Swift API Guidelines] 英語で自然に読めるように心がけた命名

はじめに

こんぬづは、池尻大橋駅の近くにあるという中華料理屋の激辛麻婆豆腐がとてもウマ辛だった田中です。渋谷界隈のエンジニア御用達らしいので、お近くにお立ち寄りの際はぜひ。

IMG_1234

さて本題ですが、最近自分の考えるSwiftのclassやstruct、関数などの命名に疑問を感じています。その疑問を解消すべく、Swift.orgAPI Design Guidelinesを読むことにしました。そしてせっかくなので読んだ内容をブログ化してみました。

今回はその中のStrive for Fluent Usageより。

この記事の内容はAPI Design Guidelinesから一部抜粋して筆者の解釈で和訳・意訳したものになります。参考になれば幸いです。

英語で自然に読めるように心がけた命名

英語として読める名前付けをする

↓良い例。

x.insert(y, at: z)          “x, insert y at z”
x.subViews(havingColor: y)  “x's subviews having color y”
x.capitalizingNouns()       “x, capitalizing nouns”

↓悪い例。

x.insert(y, position: z)
x.subViews(color: y)
x.nounCapitalize()
  • x.insert(y, position: z): 英語において位置を指定するのにpositionは使わない
  • x.subViews(color: y): colorだけだと情報が足りない。フレーズにならない
  • x.nounCapitalize(): 英語においては動詞-目的語の語順

また、よりその関数と関連度が高く、中核となる要素は引数の順書を最初にもってくるようにする。理由は第二引数以降が英語として流暢にならないから。これは仕方ない。

AudioUnit.instantiate(
  with: description, 
  options: [.inProcess], completionHandler: stopProgressBar)

イニシャライザーとファクトリーメソッドの呼び出しは第一引数名にフレーズを含めない構成にする。 例) x.makeWidget(cogCount: 47)

↓は良い例。

let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)

↓は悪い例。第一引数名を英語の文法に則った形で書こうとしている。

let foreground = Color(havingRGBValuesRed: 32, green: 64, andBlue: 128)
let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)

下記は特例で、型変換のための引数である例。このパターンの時はそもそも引数名を書かない。

let rgbForeground = RGBColor(cmyForeground)

副作用に応じたメソッドの名前付けをする

  • 副作用の無いものは名詞句とする。 e.g. x.distance(to: y), i.successor()
  • 副作用のあるものは命令形の動詞句とする。 e.g. print(x), x.sort(), x.append(y)
  • Mutatingな関数には命令形で、対してNonmutatingな関数には"-ed"や"-ing"などの接尾辞をつける
Mutating Nonmutating
x.sort() z = x.sorted()
x.append(y) z = x.appending(y)
  • Nonmutatingの変形の命名には過去分詞を用いましょう。
/// `self`をreverseする
mutating func reverse()

/// `self`をリバースしたコピーを返す
func reversed() -> Self
...
x.reverse()
let y = x.reversed()
  • メソッド名にすでにオブジェクト名を持っている場合は"-ed"を使うと文法的におかしくなってしまう。その場合、Nonmutatingな変形については"-ing"をつけて現在詞を用いる
/// `self`から全ての改行を削除する
mutating func stripNewlines()

/// 全ての改行を削除した`self`のコピーを返す
func strippingNewlines() -> String
...
s.stripNewlines()
let oneLine = t.strippingNewlines()
  • 処理が自然な名詞形で記述されている場合、Nonmutatingな関数にはその関数のMutatingな形のものに"form"という接頭辞を付けた名詞形をとる
Nonmutating Mutating
x = y.union(z) y.formUnion(z)
j = c.successor(i) c.formSuccessor(&i)

その他

  • ファクトリーメソッドには"make"を接頭辞につける。 例) x.makeIterator()
  • Nonmutatingな関数を使う時は、Boolメソッドとプロパティの使い方は受け取り側に関するアサーションとして読む。 例) x.isEmpty, line1.intersects(line2)
  • それが何であるかを表現するプロトコルの場合、名詞として命名する。 例) Collection
  • それが能力をもつことを表現するプロトコルの場合、接尾辞に-able, ible, -ingを使う。 例) Equatable, ProgressReporting
  • その他の型、プロパティ、変数、定数は名詞として命名する

まとめ

全体としてSwiftエンジニアは「英語ができなければいけない」ということかと読み取りました。とはいえこの記事でも取り扱ったSwift特有のパターンを覚えたり、エンジニアならば馴染みのある英語がわかればなんとかなりそうです。私はこれまで文で意味を成さない曖昧な名前をつけてきましたが、API Guidelinesはそれを考え直す良いお手本のように感じました。

他の言語だとどうなんだろう?

宣伝

私が主宰を務めさせていただいているAKIBA.swiftも今月で一周年を迎えるということで、記念にTシャツを作りました!Tシャツの詳細は今度の一周年勉強会で!

IMG_6935IMG_6937

「勉強会Tシャツの出来が思ったよりも良くてドヤ顏をするエンジニアのイラストです」

17626199_1244929118908733_145481102597335992_n

関連・参考