Swiftの命名規則を理解する（Swift API Design Guidelines - Naming 日本語まとめ）


私は普段Swiftをメインで書いていますが、Namingがとても苦手です。
どうやったらNamingがうまくなるか、考えました、
公式ドキュメントを見つけて、考えるのをやめました。

Namingがうまくなるためには、公式ドキュメントに従うのが一番です。
そこで `Swift API Design Guidelines` のNamingを読みました。
https://swift.org/documentation/api-design-guidelines/#naming

他の方の翻訳もありますが、当時から公式ドキュメントが更新されていたようですので、
2019/02時点での翻訳をまとめてみました。

- 翻訳というより、日本語意訳に近いと思います。
- 構成や日本語表現を独断と偏見で一部編集しています。
- 忙しい人は、「fuwamakiまとめ」だけ見れば十分かもしれません。
- 忙しくない人や英語ができる人は、公式ドキュメントを見てください。

# 命名

## クリアな使い方にしましょう

### 1. 曖昧さを避けるために全ての単語を含めよう

呼び出し側を読む人にとって曖昧な意味に捉えられないように、全ての単語を含めよう。

#### 良い例：

```swift
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` は呼び出し部分で、意味のある情報を与えないのでアカン。

#### 良い例：

```swift
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)
}

-> エンティティの役割を表す名前を選択すべき、アカン。

#### 良い例：

```swift
var greeting = "Hello"
protocol ViewController {
  associatedtype ContentView : View
}
class ProductionLine {
  func restock(from supplier: WidgetFactory)
}
```

関連付いた型がProtocol制約に密接に結びついて、Protocol名が役割になっている場合、
衝突を回避するためにProtocol名に `Protocol` を付けるのは問題ない。

```swift
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

-> 宣言は明確だが、使用法が曖昧でアカン。

#### 良い例

弱く型付けられたパラメータの前に、役割を示す名詞を付ける

```swift
func addObserver(_ observer: NSObject, forKeyPath path: String)
grid.addObserver(self, forKeyPath: graphics) // clear
```

### fuwamakiまとめ

- <font color="red">必要な単語を全て含んだ命名にしよう</font>
- <font color="red">意味を示さない単語は省略してOK</font>
- <font color="red">型制約じゃなくて役割に応じた命名をしよう</font>
- <font color="red">意味を示しきれない型情報には理解補助で単語を補ってOK</font>

## スムーズな利用を心掛けよう

### 1. メソッド名と関数名で、文法的な英語のフレーズにしよう

#### 良くない例：

> x.insert(y, position: z)
x.subViews(color: y)
x.nounCapitalize()

#### 良い例：

```swift
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”
```

メインの意味を示す引数の後に、フレーズとしての流暢さが低下する引数が続くのは許容

```swift
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作成者が最初の引数を使って文法的な連続性を示そうとしていてアカン。

#### 良い例：

```swift
let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)
let ref = Link(target: destination)
```

呼び出しが値保存型変換をしていない限り、最初の引数にラベルがあることを示す。

```swift
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まとめ

- <font color="red">メソッド名&関数名で英語のフレーズしよう</font>
- <font color="red">生成メソッドは、makeから始めよう</font>
- <font color="red">initと生成メソッドは、関数名と引数でフレーズ作っちゃダメ</font>

※副作用のとこはまとめられませんでしたごめんなさい

## 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まとめ

- <font color="red">曖昧な用語は避けよう、意味に合った単語を使おう</font>
- <font color="red">専門用語でしか表せない時に専門用語を使おう</font>
- <font color="red">略語は避けよう</font>
- <font color="red">先例には従おう</font>

## 参考

https://qiita.com/moaible/items/fbe87b343b9eaa48816e
https://qiita.com/yamoridon/items/b89a18a037631b6770b9
https://qiita.com/mono0926/items/11203c8cce0d7f4548db