私は普段Swiftをメインで書いていますが、Namingがとても苦手です。
どうやったらNamingがうまくなるか、考えました、
公式ドキュメントを見つけて、考えるのをやめました。
Namingがうまくなるためには、公式ドキュメントに従うのが一番です。
そこで Swift API Design Guidelines
のNamingを読みました。
https://swift.org/documentation/api-design-guidelines/#naming
他の方の翻訳もありますが、当時から公式ドキュメントが更新されていたようですので、
2019/02時点での翻訳をまとめてみました。
- 翻訳というより、日本語意訳に近いと思います。
- 構成や日本語表現を独断と偏見で一部編集しています。
- 忙しい人は、「fuwamakiまとめ」だけ見れば十分かもしれません。
- 忙しくない人や英語ができる人は、公式ドキュメントを見てください。
命名
クリアな使い方にしましょう
1. 曖昧さを避けるために全ての単語を含めよう
呼び出し側を読む人にとって曖昧な意味に捉えられないように、全ての単語を含めよう。
良い例:
extension List {
public mutating func remove(at position: Index) -> Element
}
employees.remove(at: x)
良くない例:
[color=red] employees.remove(x)
-> xが何を示しているか明確でないのはアカン。
2. 不要な単語は省略しよう
全ての単語は、呼び出し側にとって意味のある情報であるべき。
意図を明確にするため、意味の違いを明確にするために多くの単語を使うこともある。
ただ、読み手にとって不要な情報(なくても理解できるもの)は省略しよう。
良くない例:
public mutating func removeElement(_ member: Element) -> Element?
allViews.removeElement(cancelButton)
-> Element
は呼び出し部分で、意味のある情報を与えないのでアカン。
良い例:
public mutating func remove(_ member: Element) -> Element?
allViews.remove(cancelButton) // clearer
曖昧さを避けるために型情報を繰り返すことが時々あるが、
一般的には型よりパラメータの役割を説明する単語を使うことが望ましい。
詳細は次項にて。
3. 役割に応じて変数・パラメータ・関連型を命名しよう
型制約ではなく、役割に応じて変数・パラメータ・関連型を命名しよう。
良くない例:
var string = "Hello"
protocol ViewController {
associatedtype ViewType : View
}
class ProductionLine {
func restock(from widgetFactory: WidgetFactory)
}
-> エンティティの役割を表す名前を選択すべき、アカン。
良い例:
var greeting = "Hello"
protocol ViewController {
associatedtype ContentView : View
}
class ProductionLine {
func restock(from supplier: WidgetFactory)
}
関連付いた型がProtocol制約に密接に結びついて、Protocol名が役割になっている場合、
衝突を回避するためにProtocol名に Protocol
を付けるのは問題ない。
protocol Sequence {
associatedtype Iterator : IteratorProtocol
}
protocol IteratorProtocol { ... }
4. 弱い型情報には理解補助をしましょう
パラメータの役割を明確にするために、弱い型情報には理解補助で単語を補う。
パラメータ型が[NSObject, Any, AnyObject, Int, String]などの基本型の場合、
使用時の型情報とコンテキストが意図をちゃんと伝えられない可能性がある。
良くない例:
func add(_ observer: NSObject, for keyPath: String)
grid.add(self, for: graphics) // vague
-> 宣言は明確だが、使用法が曖昧でアカン。
良い例
弱く型付けられたパラメータの前に、役割を示す名詞を付ける
func addObserver(_ observer: NSObject, forKeyPath path: String)
grid.addObserver(self, forKeyPath: graphics) // clear
fuwamakiまとめ
- 必要な単語を全て含んだ命名にしよう
- 意味を示さない単語は省略してOK
- 型制約じゃなくて役割に応じた命名をしよう
- 意味を示しきれない型情報には理解補助で単語を補ってOK
スムーズな利用を心掛けよう
1. メソッド名と関数名で、文法的な英語のフレーズにしよう
良くない例:
x.insert(y, position: z)
x.subViews(color: y)
x.nounCapitalize()
良い例:
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”
メインの意味を示す引数の後に、フレーズとしての流暢さが低下する引数が続くのは許容
AudioUnit.instantiate(
with: description,
options: [.inProcess], completionHandler: stopProgressBar)
-> withがメインの意味を示す引数。optionとcompletionHandlerは付属する引数。
2. factoryメソッドは、makeから始めよう
ex.) x.makeIterator().
3. initializerやfactoryメソッドの最初の引数は、関数名で始まる英語フレーズにしてはいけない
ex.) x.makeWidget(cogCount: 47)
良くない例:
let foreground = Color(havingRGBValuesRed: 32, green: 64, andBlue: 128)
let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)
let ref = Link(to: destination)
-> API作成者が最初の引数を使って文法的な連続性を示そうとしていてアカン。
良い例:
let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)
let ref = Link(target: destination)
呼び出しが値保存型変換をしていない限り、最初の引数にラベルがあることを示す。
let rgbForeground = RGBColor(cmykForeground)
4. 副作用に応じて関数・メソッドを命名しよう
副作用がない場合は、名詞として読もう
ex.) x.distance(to: y)
, i.successor()
副作用がある場合は、命令動詞句として読もう
ex.) print(x)
, x.sort()
, x.append(y)
mutatingとnonmutatingのメソッド名は一貫したものにしよう
mutating methodは、似た意味を持つnonmutatingな変化をすることがあるけれど、
それはインスタンスが置き換わるのではなく、新しい値が返されている。
動作が動詞で記述される際は、変更方法に応じて ed
または ing
をつけよう
Mutating | Nonmutating |
---|---|
x.sort() | z = x.sorted() |
x.append(y) | z = x.appending(y) |
操作が名詞で記述される場合は、 form
をつけよう
Nonmutating | Mutating |
---|---|
x = y.union(z) | y.formUnion(z) |
j = c.successor(i) | c.formSuccessor(&i) |
Booleanメソッドとプロパティは使用法が変化しない場合、そのまま明示しよう
ex.) x.isEmpty
, line1.intersects(line2)
プロトコルは何が名詞として読まれるべきかを記述しよう
ex.) Collection
capabilityを示すプロトコルには接尾に able
, ible
, ing
をつけよう
ex.) Equatable
, ProgressReporting
その他の型,プロパティ,変数,定数は名詞として読む
fuwamakiまとめ
- メソッド名&関数名で英語のフレーズしよう
- 生成メソッドは、makeから始めよう
- initと生成メソッドは、関数名と引数でフレーズ作っちゃダメ
※副作用のとこはまとめられませんでしたごめんなさい
Term of Art(専門用語)をうまく使う
Term of Artとは…特定の分野または職業の範囲内で、特別な意味を持つ単語・フレーズ
1. 曖昧な用語を避けよう
一般用語を使って良い場面では、わざわざ専門用語を使わず一般用語を使おう。
例) epidermis
(表皮) より skin
(肌)を使って問題なければ、一般用語である skin
を使いましょう。epidermis
のような専門用語は、それでなければダメな場合にのみ利用しましょう。
2. 専門用語は、確立された意味を示す時に使おう
一般用語より専門用語を使うのは、それがなければ曖昧で不明瞭になるモノを正確に示すため。
例) API
のような技術用語も、確立された意味を示す場合に使いましょう。
専門家を驚かせない!
我々が用語に新しい意味を見出して利用していたら、専門家は驚き、怒るでしょう。アカン。
初心者を惑わせない!
初心者はその専門用語の意味を調べるためWeb検索して、伝統的な意味を見つけるでしょう。
伝統的な意味でその専門用語を使いましょう。
3. 略語は避けよう
特に非標準の略語は、人によって専門用語化してしまうのでアカン。
使用している略語の意味は、web検索で簡単に見つけられるようにすべき。
4. 先例に習おう
既にある文化を無視して、初心者に向けて分かりやすくするのは、アカン。
例1) 連続したデータ構造に対して
○ Array
✕ List
List
の方が分かりやすいかもしれないが、
配列は現代コンピューティングにおいて基本であり、
全てのプログラマがArrayを学び、知っています。
例2) 数学のような特定のプログラミング領域において
○ sin(x)
✕ verticalPositionOnUnitCircleAtOriginOfEndOfRadiusWithAngle(x)
略語を避けることは大切だが、sin(x)は数学者の間で数世紀前から使われていた共通用語。
fuwamakiまとめ
- 曖昧な用語は避けよう、意味に合った単語を使おう
- 専門用語でしか表せない時に専門用語を使おう
- 略語は避けよう
- 先例には従おう
参考
https://qiita.com/moaible/items/fbe87b343b9eaa48816e
https://qiita.com/yamoridon/items/b89a18a037631b6770b9
https://qiita.com/mono0926/items/11203c8cce0d7f4548db