【Swift】Null安全について

# はじめに
この記事は社内の勉強会で使用したものです。
Swift案件の経験が少ない社員や言語研修済みの新卒向けにNull安全について紹介したものです。
そのため、細かいOptional型の使い方というよりは「何が良いのか」「どういう風に運用していくのか」といった内容になります。
意見等いただければと思い、投稿致しました。
また、資料を作りにあたりいくつかの記事を参考にさせていただきました。ありがとうございました。

# Null安全とは
**Nullを上手に扱うための仕組み**のことです。
仕組みそのものについては言語により差異はありますが、今回はSwiftを例に紹介していきます。

Swiftでは安全にNullを扱うために、**Optional**というNullを許容する型を使っています。
Xcodeで`Optional`と打って`Command+クリック`をすると`Optional`の使い方がコメントで記載されているので一度見てみることをおすすめします。

Optionalは、`?`または`!`で表します。

```Swift
let hoge: String = “abc” // 非オプショナル(nullを格納出来ない)
let fuga: String? = “abc” // オプショナル(nullを格納出来る)

print(hoge) // abc
print(fuga) // Optional(abc)
```

このようにNullを許容する型としない型を別物のように扱うことによって、「Optionalではない = Nullは絶対に入っていない」変数を実現しています。

## Null安全でない言語との違い
Null安全かそうでないかによって、実際にコードを書く時に考えることの量や質に違いがあります。
既存のプロジェクトの一部を改修する際の例を以下に挙げます。

### Objective-C(Null安全ではない言語)の場合

```Objective-C
- (void)insertData:(NSString *)text {
    // なんか処理
}
```

**・`text`はNullかもしれない**
　・もしNullだったらどうするのか？
　　┗ Assertで落とす/成功失敗をBoolで返す/ダイアログを表示する...?
**・もし`nonnull`が付いていても**
　・Nullそのものは防げてもNullポインタは防げない
　　┗ `nonnull`がついているだけで信じられますか？

### Swift(Null安全言語)の場合

```Swift
func insertData(text: String) {
    // なんか処理
}
```

**・`text`はNullではない**
　┗ 幸せ
**・もし`text: String?`だったら**
　・まずそもそもこのメソッドを作った時点でわざと`Optional`にしているのだから考慮しているはず

Null安全の利点の一つとして、
**OptionalというNullを許容する型があることで、Nullの場合を考慮せざるを得ない**が挙げられます。

# Null安全の良いところ
## Nullを扱おうという意識が付く
例えば、引数で渡された`text`をDBにInsertするメソッドを書く時

`func insertText(_ text: String`
ここまで書いたタイミングでNullを意識せざるを得ないです。

1)`func insertText(_ text: String) {`と書いた場合
　・そもそも`text`にはNullを入れられない
　・このメソッドを呼ぶ側でNullではない状態にしなくてはならない

2)`func insertText(_ text: String?) {`と書いた場合
　・`Optional`になっているためアンラップする必要がある

そこから先どうするかはプログラマ次第ですが、まず一度意識しなくてはならないというのはNull安全言語のメリットだと感じます。

## コードから読み取れる情報が多い
```Swift
func insertData(_ text: String) {
    // なんか処理
}
```
「ここがTextをinsertしてるメソッドかー」
「textは非Optionalだな」
「ということは、メソッドを使う側でNullを弾いているのか」

```Objective-C
- (void)insertData:(NSString *) {
    // なんか処理
}
```
「ここがTextをinsertしてるメソッドかー」
「これNullチェックどこでしてるんだ？」
(メソッドの頭でNullチェックをしていなかった場合)
「とりあえずメソッドを使っているところを探すか・・・」
「💩」

`Optional`によって型を見ただけでNullが来る/来ないを判断出来るのは大きなメリットです。

# Null安全の悪いところ
全部`Optional`にして適当にアンラップしても動いてしまいます。
結局書く人次第です。

# Null安全を使いこなすために
## Null判定位置の統一
例えば、API通信で取得した文字列をDBにinsertする場合

API通信のレスポンスは必ずしも望んだ形で来るとは限りません。
では、どこでその判断をするのか？

・レスポンス取得時
・取得したレスポンスを`Optional`として画面に返してから
・insertメソッドを呼ぶ前
・insertメソッド内で判定して可否をBoolで返させる

統一するとみんな幸せです。

## 簡単にNullの可能性を握り潰さない
`hoge?.fugaAction()`
アンラップは、Swiftにおいて数少ないNullを恐れざるを得ない処理です。
読む人を安心させるアンラップを心がけましょう。

## アンラップ位置の統一
```Swift
func hoge() {
    guard let unwrappedFuga1 = fuga1 else { return }
    guard let unwrappedFuga2 = fuga2 else { return }

    // なんか処理

    guard let unwrappedFuga3 = fuga3 else { return }
    guard let unwrappedFuga4 = fuga4 else { return }

    // なんか処理

    guard let unwrappedFuga5 = fuga5 else { return }
}
```
```Swift
func hoge() {
    guard let unwrappedFuga1 = fuga1 else { return }
    guard let unwrappedFuga2 = fuga2 else { return }
    guard let unwrappedFuga3 = fuga3 else { return }
    guard let unwrappedFuga4 = fuga4 else { return }
    guard let unwrappedFuga5 = fuga5 else { return }

    // なんか処理
}
```
下の方が気持ちいいし分かりやすいです。

# まとめ
Null安全の最大のメリットは、コードに想いを乗せやすいことにあります。
Null安全を活用して気持ちの伝わるコードを書きましょう。