[脱駆け出しエンジニア] 綺麗なコードを書くコツ

はじめまして! 新米iOSエンジニアの[Masa](https://twitter.com/_Masa_asaM_)です。今回は、僕が業務でプログラムを書くようになってから、1~2年で受けたコードレビューやフィードバック、実装経験を元に、 **綺麗なコードを書くTips**  を紹介していきたいと思います。

# `綺麗なコード`とは?
そもそも`綺麗なコード`とは、どんなコードなのでしょうか? 僕が考える綺麗なコードの要素を以下に挙げます。

- 可読性が高い
    - コーディング規約を導入する
    - 分かりやすい命名
    - 深いネストを避ける

- 再利用性がある
    - ソフトコーディング
    - アーキテクチャに則って責務分けを行う
    - 疎結合にする(= 処理の干渉範囲が狭く、変更/拡張がしやすい)


## コーディング規約の導入
どんな遊びにもルールが存在するように、プログラムを組むときのルール = 規約を導入しましょう!
規約を導入すると、例えば分岐処理を記述する際、どんな基準でif/guard/switch/三項演算子を使い分けるか/関数や変数の命名方法が明確になります。

参考として、以下に有名な規約を載せます。

- Swift
    - [Swift Style Guide](https://google.github.io/swift/)
    - [The Official raywenderlich.com Swift Style Guide](https://github.com/raywenderlich/swift-style-guide)

- Ruby
    - [Rubyコーディング規約](https://shugo.net/ruby-codeconv/codeconv.html)
    - [cookpad/styleguide/ruby.ja.md](https://github.com/cookpad/styleguide/blob/master/ruby.ja.md)


- Python
    - [PEP8](https://www.python.org/dev/peps/pep-0008/)
    - [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html)

また、規約に書いてないことは、各言語の仕様に基づいて考えられるとベストなので、公式ドキュメントは目を通しておくと良いです!

swiftの場合

- [The swift programming language](https://docs.swift.org/swift-book/)

## 分かりやすい命名

例えば、新規会員登録をする際に、ユーザー名がダブっていたり不正な値が使われていないかをチェックし、検証結果をbool値で返す関数を次の様に定義するとします。

`not preferred`

```swift:SignUpViewController.swift
func isValid(_ userName: String) -> Bool
```

上記の記述だと、以下の様な問題点が考えられます。

- メールアドレス/パスワードのvalidationと区別がしにくい
- コードを読む際に、isValid()が何をvalidしているのか一目で分からない

そこで、関数や変数の命名をする際は **出来るだけ多くの情報量を盛り込みましょう**

`preferred`

```swift:SignUpViewController.swift
func isUserNameEnable(_ userName: String) -> Bool
```

その他の分かりやすい命名の仕方としては、

- 最大値/最小値を表す際は`max/min`
- bool値を扱うときは、`is/has/should/can`を先頭につける(ex:`isEnabled`)

等があります。

より詳細に知りたい方は、[リーダブルコード](https://hb.afl.rakuten.co.jp/ichiba/1ecbc5fa.93c20969.1ecbc5fc.5f325569/?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F11753651%2F&link_type=hybrid_url&ut=eyJwYWdlIjoiaXRlbSIsInR5cGUiOiJoeWJyaWRfdXJsIiwic2l6ZSI6IjI0MHgyNDAiLCJuYW0iOjEsIm5hbXAiOiJyaWdodCIsImNvbSI6MSwiY29tcCI6ImRvd24iLCJwcmljZSI6MSwiYm9yIjoxLCJjb2wiOjEsImJidG4iOjEsInByb2QiOjAsImFtcCI6ZmFsc2V9)を読むとよく分かると思います。


## 深いネストを避ける

前述のユーザー名チェックで以下の様なロジックが使われていたとします。

`not preferred`

```swift:SignUpViewController.swift
func isUserNameEnable(_ userName: String?) -> Bool {
     // 今回はuserNameのnil判定と重複だけチェックします。(本当は不正文字の検出なども行った方が良い)
     if userName.isNotNil {
        if userName != "" {
           // 初心者向けなのでAPI処理は今回は書きません。 responseに入力したuserNameが含まれていればtrueを返す関数だと思ってもらえると
           if userNameAPIResponse.contains(userName) {
              return false
           } else {
              return true
           }
        } else {
           return false
        }
     } else {
       return false
     }
}
```

わざとネストを深く書きました。こんなに深いネストのコード読みたくないし、間違える可能性高くなります・
ネストは絶対に浅い方が読みやすいので、あの手この手を使ってなんとか浅くしましょう。

- `String?`が`nil`か`""`かを判別する処理を切り出す(他のところでも使いそうなところは共通化する)
- 不要な`else`は削除する
- guard節で早期return

等で、以下の様に書くことができます。

```swift:SignUpViewController.swift
func isUserNameEnable(_ userName: String?) -> Bool {
     if isStringNotNilOrEmpty(userName) {
        return !userNameAPIResponse.contains(userName)
     }
     return false
}

func isStringNotNilOrEmpty(_ string: String?) -> Bool {
      // string?.isEmpty == falseでも良いが今回は分かりやすい様にif letを使用
      if string.isNotNil {
         return string != ""
      }
      return false
}
```

## ソフトコーディング

ソフトコーディングとは、プログラム上で使われる値を定数/変数に格納することです。
ソフトコーディングをしない場合、以下の様なデメリットがあります。

- 値に変更が加わった時に修正範囲が膨大になる
- プログラム中に`1.10`のような値(マジックナンバー)が出てきた際に、何を指しているか分からない

例えば、商品の合計金額を入力したら、消費税込みの値を算出するプログラムがあるとします。

`not preferred`

```swift
totalPrice =  sum([stuff]) * 1.1
```
ここで`1.1`と定義してしまうと、将来消費税が増税した時に、いちいち`1.1`を変更しなければならず、面倒です。
また、消費税額のみを計算したい時、税抜き前の定価からセールで半額になった時等様々なケースでややこしくなりそうです。

そこで、なるべく値は以下のように格納しましょう。

`preferred`

```swift
let consumptionTax = 0.1
let includingTaxPriceRatio = (1 + consumptionTax)
totalPrice =  sum([stuff]) * includingTaxPriceRatio
```

## アーキテクチャに則って責務分けを行う

コードの再利用性を高めるために、アーキテクチャに則ってコードを分割しましょう。

- MVC
- MVVM
- Clean architecture

などの有名どころ抑えておくといいと思います。([俺的アプリケーション・アーキテクチャまとめ in Swift](https://qiita.com/_Masa_asaM_/items/cc50c59785cbd2a47df7))

参考: [iOSアプリ設計パターン入門](https://peaks.cc/books/iOS_architecture)

## 疎結合にする

コードとコードの依存関係/ファイルとファイルの依存関係は

- 依存関係は双方向ではなく、単方向にする

などの制限していきましょう(疎結合にすると言います。)
(基本的には、アーキテクチャにしっかり分けていけば自然と疎結合なコードに近づくと思いあmす。)
詳しくはこちらの記事がとても参考になります!
[プログラムの依存関係とモジュール構成のこと](https://qiita.com/wm3/items/2c90bfd9e973d368ebd8)

依存関係を限定しておくと変更可能性に強いコードになります。

### アクセス修飾子で範囲を限定
`private`/`fileprivate`/`public`
などのアクセス修飾子を変数や定数、関数につけていき、公開範囲を限定させましょう。


# 終わりに
追加でこのTipsを入れた方が良い、もしくは内容が分かりづらい等ありましたらコメントいただけると嬉しいです!