nestif は深くネストされた if 文を検出するツールです。
解決する問題
if 文のネストが深くなると、コードの理解に必要な認知的コストが急激に増加します。ネストが 3〜4 段以上になると条件の組み合わせを頭の中で追跡するのが困難になり、バグの温床になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| func ProcessOrder(ctx context.Context, order Order) error { if order.ID != "" { if order.Status == StatusPending { if order.Total > 0 { if order.CustomerID != "" { return save(ctx, order) } else { return errors.New("customer required") } } } } return errors.New("invalid order") }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| func ProcessOrder(ctx context.Context, order Order) error { if order.ID == "" { return errors.New("order ID required") } if order.Status != StatusPending { return errors.New("order not pending") } if order.Total <= 0 { return errors.New("order total must be positive") } if order.CustomerID == "" { return errors.New("customer required") } return save(ctx, order) }
|
設定
公式ドキュメント
1 2 3 4 5 6 7 8 9
| version: "2"
linters: enable: - nestif settings: nestif: min-complexity: 5
|
オプション
| オプション |
型 |
デフォルト |
説明 |
min-complexity |
int |
5 |
この値以上の複雑度を持つ if 文を報告する |
複雑度の計算ルール
| 構造 |
加算 |
if |
+1 |
else if |
+1 |
else |
+1 |
ネストされた if |
+ネスト深さ(深いほど加算が大きい) |
サンプル
検出例
1 2 3 4 5 6 7 8 9 10 11 12 13
| func CanAccess(user User, resource Resource) bool { if user.IsActive() { if user.HasRole("admin") { return true } else if user.HasRole("editor") { if resource.IsPublished() { return true } } } return false }
|
修正例
1 2 3 4 5 6 7 8 9 10 11 12
| func CanAccess(user User, resource Resource) bool { if !user.IsActive() { return false } if user.HasRole("admin") { return true } if user.HasRole("editor") && resource.IsPublished() { return true } return false }
|
注意点
min-complexity のデフォルトは 5。厳しくするなら 3〜4、緩めるなら 7〜8 が目安
- 早期リターン(guard clause)が最も効果的なリファクタリング手法。条件を反転して異常系を先に返す
else if チェーンは switch に置き換えるとネストが浅くなる
- gocognit は関数全体の複雑度を測るのに対し、nestif は個々の if 文のネスト深さに特化している
参考リンク