見出し画像

この世でいちばんわかりやすいiPhoneアプリ開発のおはなし【Guard構文とは】

関数を可能な限り早い段階で終了すると、コードが読みやすくなると言われています。このページでは、そのために有用なGuard構文を説明します。なお、Ifステートメントについてはこちらのページで解説しています。

早期脱出して、運命のピラミッドを回避する

ここでは、「コーンフレークを美味しく食べる」ための関数を定義しましょう。

コーンフレークを美味しく食べるための条件は、以下の3つです。
①お腹が空いている
②コーンフレークがあること
③ミルクがあること

これらの条件を示すBool型の変数には、既定値としてtrueを設定しておきます。

var isHungry = true
var haveCornfake = true
var haveMilk = true

つまり、3つの変数のいずれかひとつでもfalseだった場合は、コーンフレークを美味しく食べることはできません。

それでは、ifステートメントを使って、このような関数を実行していきましょう。
まずは、「お腹が空いている」ことを確認するためのIfステートメントです。 お腹が空いていなければ、コーンフレークなど食べることはできません。

func eatCornflake() {
   if isHungry {
       // check 2nd condition...
   } else {
       print("I don't want to eat anything.")
   }
}

次に、「コーンフレークがある」ことを確認します。 コーンフレークが無ければ、元も子もありません。

func eatCornflake() {
   if isHungry {
       if haveCornflake {
           // check 3rd conditions...
       } else {
           print("You need the cornflakes.")
       }
   } else {
       print("I don't want to eat anything.")
   }
}

最後に、「ミルクがある」ことを確認します。 ミルクがなかった場合は、やむなくミルクなしでコーンフレークを食べることになってしまいます。

func eatCornflake() {
   if isHungry {
       if haveCornflake {
           if haveMilk {
               print("Enjoy your cornflakes!")
           } else {
               print("You have no choice but to eat without milk...")
           }
       } else {
           print("You need the cornflakes.")
       }
   } else {
       print("I don't want to eat anything.")
   }
}

3つのIfステートメントをネストすることで、「コーンフレークを美味しく食べる」ための関数を実装できました。
ところで、これらのIfステートメントでは、「コーンフレークを食べるコード」が最も深くネストされた位置に押し込まれています。 そのため、関数における「本当に実行したい処理」を直感的に見つけることは困難です。 これは「運命のピラミッド」と呼ばれる悪しき慣習に囚われた構造です。

このような状況ではguardステートメントが有用です。 guardステートメントを使用すると、条件満たす場合に限って、関数の手続きを進めることができます。 guardステートメントの条件を満たさなかった場合、関数は手続きを即座に終了します。

guardステートメントは、以下の通りに記述します。

guard condition else {
   // ここは、conditionの評価がfalseの場合に実行したいコード
   // returnキーワードで関数から脱出
}
// ここから先は、conditionの評価がtrueの場合に実行したいコード

guardステートメントをeatCornflake()メソッドに導入すると、コードの外観が整然とします。

func eatCornflake() {
   guard isHungry else {
       print("I don't want to eat anything.")
       return
   }
   
   guard haveCornflake else {
       print("You need the cornflakes.")
       return
   }
   guard haveMilk else {
       print("You have no choice but to eat without milk...")
       return
   }
   print("Enjoy your cornflakes!")
}

guardステートメントを使って、「コーンフレークを美味しく食べる」ための条件をひとつずつ確認していきます。 guardステートメントの条件を満たさなかった場合は、コーンフレークを美味しく食べることはできずに、処理が関数から脱出します。 その結果、「コーンフレークを食べるコード」はネストがなくなり、一番下の行に移動しました。 関数における「本当に実行したいコードがどこにあるか」は、一目瞭然です。

この記事が気に入ったらサポートをしてみませんか?