Skip to content

Nesting Depth Analyzer

Analyzer IDCategorySeverityTime To Fix
nesting-depth✅ Code QualityMedium20 minutes

What This Checks

  • Detects code blocks with excessive nesting levels (default threshold: 4)
  • Identifies deeply nested if/else statements
  • Flags nested loops (for, foreach, while)
  • Detects nested try/catch blocks
  • Tracks maximum nesting depth per method
  • Reports exact file location and line number of each issue

Why It Matters

  • Reduced readability: Deeply nested code is difficult to understand and follow
  • Maintenance burden: Complex nesting makes code harder to modify and debug
  • Cognitive load: Developers spend more mental energy understanding nested logic
  • Testing difficulty: Deep nesting makes it harder to test all code paths
  • Bug risk: Complex nested conditions increase the likelihood of logic errors
  • Code review challenges: Reviewers struggle to understand deeply nested code
  • Refactoring resistance: Developers avoid touching complex nested code
  • Performance impact: Deep nesting can indicate inefficient algorithms

How to Fix

Quick Fix (5 minutes)

Use early returns to reduce nesting:

php
// ❌ Before: Deep nesting
if ($user) {
    if ($user->isActive()) {
        if ($user->hasPermission()) {
            if ($user->canAccess($resource)) {
                // Actual logic here
                return $resource->process();
            }
        }
    }
}

// ✅ After: Early returns
if (!$user || !$user->isActive()) {
    return;
}

if (!$user->hasPermission()) {
    return;
}

if (!$user->canAccess($resource)) {
    return;
}

// Actual logic here
return $resource->process();

Proper Fix (20 minutes)

1: Extract Methods

php
// ❌ Before: Deep nesting in single method
public function processOrder(Order $order, User $user)
{
    if ($order) {
        if ($order->isValid()) {
            if ($user->canProcess($order)) {
                if ($order->hasItems()) {
                    foreach ($order->items as $item) {
                        if ($item->isAvailable()) {
                            // Process item
                        }
                    }
                }
            }
        }
    }
}

// ✅ After: Extract methods to reduce nesting
public function processOrder(Order $order, User $user)
{
    if (!$this->canProcessOrder($order, $user)) {
        return;
    }

    $this->processOrderItems($order);
}

private function canProcessOrder(Order $order, User $user): bool
{
    return $order
        && $order->isValid()
        && $user->canProcess($order);
}

private function processOrderItems(Order $order): void
{
    if (!$order->hasItems()) {
        return;
    }

    foreach ($order->items as $item) {
        if ($item->isAvailable()) {
            $this->processItem($item);
        }
    }
}

2: Use Guard Clauses

php
// ❌ Before: Nested conditions
public function calculatePrice(Product $product, User $user, int $quantity)
{
    if ($product) {
        if ($product->isActive()) {
            if ($quantity > 0) {
                if ($user->isPremium()) {
                    return $product->price * $quantity * 0.9;
                } else {
                    return $product->price * $quantity;
                }
            }
        }
    }
    return 0;
}

// ✅ After: Guard clauses
public function calculatePrice(Product $product, User $user, int $quantity): float
{
    if (!$product || !$product->isActive() || $quantity <= 0) {
        return 0.0;
    }

    $basePrice = $product->price * $quantity;

    return $user->isPremium()
        ? $basePrice * 0.9
        : $basePrice;
}

3: Use Strategy Pattern for Complex Conditions

php
// ❌ Before: Deep nesting with multiple conditions
public function processPayment(Order $order, PaymentMethod $method)
{
    if ($method->isCreditCard()) {
        if ($order->amount > 1000) {
            if ($order->user->isVerified()) {
                // Process credit card
            } else {
                // Require verification
            }
        } else {
            // Process normally
        }
    } elseif ($method->isPayPal()) {
        if ($order->amount > 500) {
            // Process PayPal
        }
    }
}

// ✅ After: Strategy pattern
public function processPayment(Order $order, PaymentMethod $method)
{
    $processor = $this->getPaymentProcessor($method);
    return $processor->process($order);
}

private function getPaymentProcessor(PaymentMethod $method): PaymentProcessor
{
    return match (true) {
        $method->isCreditCard() => new CreditCardProcessor(),
        $method->isPayPal() => new PayPalProcessor(),
        default => new DefaultProcessor(),
    };
}

4: Combine Conditions

php
// ❌ Before: Multiple nested ifs
if ($user) {
    if ($user->isActive()) {
        if ($user->hasRole('admin')) {
            // Admin logic
        }
    }
}

// ✅ After: Combined conditions
if ($user?->isActive() && $user->hasRole('admin')) {
    // Admin logic
}

5: Customize ShieldCI Settings (Optional)

To customize the nesting depth threshold, publish the config:

bash
php artisan vendor:publish --tag=shieldci-config

Then in config/shieldci.php:

php
'analyzers' => [
    'code-quality' => [
        'enabled' => true,
        
        'nesting-depth' => [
            'threshold' => 4,  // Default: 4 levels
        ],
    ],
],

TIP

The default threshold of 4 is based on industry best practices. Code with deeper nesting becomes significantly harder to understand and maintain.

References