Aikido

アーリーリターンとガード節を使うべき理由

読みやすさ

ルール

使用 早い リターン そして ガード 条項を使用する。
深い 入れ子  遅い パラメータ 検証
作る 関数 が難しくなる にする 読みにくくなる そして メンテナンスが難しくなります。

対応言語 45+

はじめに

ガード節は、関数の開始時に前提条件を検証し、条件が満たされない場合は即座にリターンします。これは、エラー・ケースを前もって処理することで入れ子を平らにし、メイン・ロジックを入れ子にせず、読みやすくします。中途半端にパラメータを検証したり、複数の条件文の中に成功パスを入れ子にしている関数は、読者に何段階ものインデントにわたってコンテキストを追跡することを強いる。

なぜそれが重要なのか

コードの可読性:ガード句は、ネストすることなく、関数の最後でハッピーパスを可視化します。読者は、すべてのエラー条件を前もって見ることができ、入れ子になった複数の条件を意識的に追跡することなく、1つのインデント・レベルでメイン・ロジックを読むことができます。

メンテナンスと修正:深く入れ子になったコードに新しい検証条件やエラー条件を追加するには、既存のロジックを壊さないように慎重に配置する必要があります。上部にあるガード節は、メインのロジックに触れることなく新しいチェックを追加することを可能にし、バグを引き起こすリスクを低減します。

コード例

非準拠:

function processPayment(user, amount) {
    if (user) {
        if (user.isActive) {
            if (amount > 0) {
                if (user.balance >= amount) {
                    user.balance -= amount;
                    return { success: true, newBalance: user.balance };
                } else {
                    return { success: false, error: 'Insufficient funds' };
                }
            } else {
                return { success: false, error: 'Invalid amount' };
            }
        } else {
            return { success: false, error: 'Inactive user' };
        }
    } else {
        return { success: false, error: 'User required' };
    }
}

なぜ間違っているのか:4段階の入れ子により、メインロジック(バランス推論)が関数の奥深くに隠されている。エラー条件ごとにインデントレベルが追加されるため、ハッピーパスが見つけにくく、一目で理解しにくい。

✅ 準拠:

function processPayment(user, amount) {
    if (!user) {
        return { success: false, error: 'User required' };
    }
    if (!user.isActive) {
        return { success: false, error: 'Inactive user' };
    }
    if (amount <= 0) {
        return { success: false, error: 'Invalid amount' };
    }
    if (user.balance < amount) {
        return { success: false, error: 'Insufficient funds' };
    }

    user.balance -= amount;
    return { success: true, newBalance: user.balance };
}

なぜこれが重要なのか:ガード節はすべての前提条件をアーリーリターンで検証し、関数を1つのインデントレベルに保ちます。ハッピーパス(残高控除)は、入れ子にすることなく最後にはっきりと見えるので、関数を読みやすく、修正しやすくします。

結論

関数の開始時に、ガード節を使って入力の妥当性を確認し、エラー・ケースを処理する。条件が失敗した場合は、成功経路をネストするのではなく、早めにリターンする。これにより、コードが平坦で読みやすくなり、既存のロジックを壊すことなく簡単に変更できる。

よくある質問

ご質問は?

複数のリターンがあると、関数がわかりにくくなるのでは?

古い「シングルリターン」ルールは、リソースのクリーンアップを手作業で行っていた時代のものだ。現代の言語では、クリーンアップは自動的に処理される。エラー条件に対する複数のアーリーリターンは、ネストされた条件式を追跡して実行がどこで終了するかを見つけるよりも、意図を明確にする。

ガード節は例外を投げるべきか、エラー値を返すべきか?

コンテキストに依存する。予期しないエラー (プログラミングのバグ、システム障害) には例外を使用する。予期せぬ検証失敗(無効な入力、ビジネスルール違反)にはエラー値を返す。ガード節はどちらのアプローチでも機能するが、重要なのは関数の開始時に素早く失敗することである。

複数のreturn文のパフォーマンスについては?

影響ゼロ。コンパイラーとインタープリターは、return文がいくつあっても同じように最適化する。早期リターンは、前提条件が失敗したときの不要な作業を回避することで、実際にパフォーマンスを向上させることができる。

ガード節で複雑な検証ロジックを扱うには?

バリデーションを別の関数に分離します。これにより、複雑なバリデーションロジックをカプセル化しつつ、ガード節を読みやすく保つことができます。それぞれのバリデーション関数は、独自のテストとドキュメントを持つことができます。

帰国前にクリーンアップコードが必要な場合は?

try-finallyブロックや言語固有のクリーンアップ・メカニズム(Goではdefer、C#ではusing、Pythonではコンテキスト・マネージャー)を使う。ガード節はtryブロックの中に、クリーンアップはfinallyの中に入れる。クリーンアップを確実に行いながら、アーリーリターンでフラットな構造を維持する。

まずは無料で体験

コード、クラウド、ランタイムを1つの中央システムでセキュアに。
脆弱性を迅速に発見し、自動的に修正。

クレジットカードは不要。