【Swift】仕様変更が怖くなくなるif文の書き方 〜 enumを使ってSwiftらしく書く 〜


今回は、enum型を使ってSwiftらしいif文の書き方を記事にしてみました。

この記事で学べること

  • いつものif文をenumを利用してSwiftらしくスマートに書く方法
  • 仕様変更に強いif文の書き方

サンプルコード

仕様

今回はサンプルとして、APIなどの外部リソースから都道府県の文字列を取得したと仮定します。
その上で、都道府県が"Tokyo"or"Osaka"の場合とそれ以外の都道府県で処理を分岐したいという仕様にします。

enumを一切使わないif文の場合

if city == "Tokyo" || city == "Osaka" {
    print("特定の都市が入力されました")
} else {
    print("特定の都市以外が入力されました")
}

この書き方でも処理的な問題はないが、この書き方で書かれているコードがプロジェクトに複数箇所あると、
「都道府県名を大文字に変更してください」
という仕様変更が発生した場合、該当箇所を全部修正する必要があります。
その過程でプログラマーが文字列のタイプミスをした場合、ヒューマンエラーによるバグが発生します。

enumを使ってリファクタリング①

そこでenumを用いることで、上記のような手間を解消でき、ヒューマンエラーを防ぐことができます。
このようにif文をenumを利用して制御する方法はよく見られるやり方です。
僕も色々なところでこのように制御する方法を見てきましたし、自分も使います。

都道府県名を大文字にする仕様変更が発生しても、enumだけ修正すれば、if文自体の修正は不要です。

enum SelectedCity: String {
    case tokyo = "TOKYO"
    case osaka = "OSAKA"
}

if city == SelectedCity.tokyo.rawValue || city == SelectedCity.osaka.rawValue {
    print("特定の都市が入力されました")
} else {
    print("特定の都市以外が入力されました")
}

しかし、またまた仕様変更が発生し
「北海道の場合も東京と大阪のように特別な処理を行ってください」
となった場合、以下のように修正しなくてはいけません。

enum SelectedCity: String {
    case tokyo = "TOKYO"
    case osaka = "OSAKA"
    case hokkaido = "HOKKAIDO"
}

if city == SelectedCity.tokyo.rawValue || city == SelectedCity.osaka.rawValue || city == SelectedCity.hokkaido.rawValue {
    print("特定の都市が入力されました")
} else {
    print("特定以外の都市が入力されました")
}

となると、1回目のサンプルコードの問題同様、if文を直接修正する必要があります。
さらに、if文の条件が冗長になりがちなので、ちょっと可読性が下がってしまうかなぁと思います。

enumを使ってリファクタリング②

そこで、if letenumを組み合わせて使うことで、可読性と拡張性の両方を兼ね備えたコードを実現できます。

enum SelectedCity: String {
    case tokyo = "TOKYO"
    case osaka = "OSAKA"
    case hokkaido = "HOKKAIDO"
}

if let _ = SelectedCity(rawValue: city) {
    print("特定の都市が入力されました")
} else {
    print("特定以外の都市が入力されました")
}

enuminitする時の

  • SelectedCityrawValueに定義されている文字列であればインスタンスが返される
  • SelectedCityrawValueに該当しない文字列であればnilが返される

という性質を利用して、該当文字列以外だったらelseの処理が実行されるというコードを書くことができました。

if文を最初からこのようにコーディングしておけば、あとから愛知京都も追加してくださいと言われても、enumに定義を追加するだけで済みます。
そうすればヒューマンエラーも仕様変更にかかるコストも最小限に抑えられると思います。

おわりに

記事を読んでいただきありがとうございました。

実際にプロジェクトやっているときに、こうやったらいい感じじゃないかなということで思いついたものですので、
「こういう方法もありますよ!」というやり方があればコメントいただけると、嬉しいです。

いままで書いたif文でこれ使える所があれば、全部リファクタリングしたい気分です。。。