Boolean expression chains five or more operands

ID

apex.maintainability.expression_too_complex

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Complexity

Language

Apex

Description

Reports a boolean expression joining five or more operands with &&, or five or more operands with ||, at one level (fixed threshold: four operators). An expression that reaches four operators only by mixing && and || is reported only when the mixing is parenthesised, so that one level still carries five operands.

Rationale

Apex evaluates && and || left to right and short-circuits, so in a chain this long the later operands run for some records and not for others - and when one of them is a method call, a contains on a collection or a null-safe navigation, whether it runs at all depends on the order somebody happened to write. That is also what makes such a condition expensive to test: five operands need thirty-two combinations to cover, so in practice the test class covers two of them and the rest ship unverified. When the condition later needs one more clause, the person adding it has to re-derive the whole precedence by reading, and && binding tighter than || is the standard place that goes wrong.

The following code illustrates the pattern detected by this rule:

public class OpportunityGuard {

    public Boolean isReadyToClose(Opportunity opp, User owner) {
        // FLAGGED: Boolean expression chains five or more operands
        return opp.Amount != null && opp.CloseDate != null && opp.StageName != 'Closed Lost' && opp.AccountId != null && owner.IsActive;
    }

    public void route(Case c, Boolean afterHours) {
        // FLAGGED: Boolean expression chains five or more operands
        if (c.Priority == 'High' || c.Origin == 'Phone' || c.IsEscalated || afterHours || c.Type == 'Outage') {
            c.OwnerId = UserInfo.getUserId();
        }
    }

    public Boolean needsReview(Account a, Boolean flagged) {
        // FLAGGED: Boolean expression chains five or more operands
        Boolean review = a.AnnualRevenue > 1000000 && a.Industry != null && (a.Type == 'Customer' || a.Type == 'Partner') && a.OwnerId != null && flagged;
        return review;
    }

    public Boolean isComplete(Contact c) {
        return c.FirstName != null && c.LastName != null && c.Email != null && c.Phone != null;
    }

    public Boolean isContactable(Contact c) {
        return c.Email != null && c.Phone != null && (c.MailingCity != null || c.MailingStreet != null);
    }

    public Boolean hasOwner(Lead l) {
        return l.OwnerId != null && l.Status != 'Converted';
    }

    public Boolean namedGroups(Opportunity opp, User owner) {
        Boolean hasFigures = opp.Amount != null && opp.CloseDate != null;
        Boolean isOpen = opp.StageName != 'Closed Lost' && opp.AccountId != null;
        return hasFigures && isOpen && owner.IsActive;
    }

    public Boolean isStale(Account a, Boolean flagged, Boolean archived) {
        // FLAGGED: Boolean expression chains five or more operands
        return a.Industry != null && a.Type != null && a.OwnerId != null && a.ParentId != null && flagged && archived;
    }

    public Boolean anyChannel(Case c, Boolean escalated, Boolean afterHours, Boolean weekend) {
        // FLAGGED: Boolean expression chains five or more operands
        return c.Origin == 'Phone' || c.Origin == 'Email' || c.Origin == 'Web' || c.Origin == 'Chat' || escalated || afterHours || weekend;
    }
}

Remediation

Give the parts names: assign each group to a well-named Boolean local, or move the whole condition into a small private method whose name says what it decides, so the call site reads as one question. Where the operands are checks over the same record, a method on a wrapper or domain class keeps them together and makes each one testable on its own.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved