🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Conditional Simplification Strategy

by @quochungto

Select and apply the correct refactoring for complex or tangled conditional logic. Use when: a method has a complicated if-then-else that obscures why branch...

⚑ When to Use
TriggerAction
- A method-level conditional where the condition checks multiple things but the code only tells you *what* happens, not *why* the branching exists
- Several separate conditions that all produce the same result, scattered as sequential checks
- The same code fragment repeated in every branch of a conditional
- A boolean variable toggled to control loop exit β€” the code is structuring state instead of expressing intent
- Nested if-else blocks where finding the "normal" path requires reading through multiple levels of special cases
- A switch (or long if-else-if chain) that dispatches behavior based on an object's type, and new types are expected
- Null checks for the same object in multiple client methods
**The core insight from Fowler:** Conditional logic has two parts β€” the *switching logic* (which path to take) and the *details* of what each path does. When these are mixed inside the same method body, the reader must decode both simultaneously. The refactorings in this chapter separate these concerns so each part is named and readable on its own.
**This skill depends on diagnosis.** If you arrived here from `code-smell-diagnosis` with a Switch Statements finding, use the decision framework in Step 1 to select the right refactoring. If you have a simpler conditional problem (not a Switch Statements smell), the framework also applies β€” start with the pattern that matches your code structure.
---
πŸ’‘ Examples

Example 1: Choosing Between Polymorphism and Explicit Methods

Scenario: A Shape class has this method:

double area(String shapeType) {
    if (shapeType.equals("circle"))    return Math.PI * _radius * _radius;
    if (shapeType.equals("rectangle")) return _width * _height;
    if (shapeType.equals("triangle"))  return 0.5 * _base * _height;
    throw new RuntimeException("Unknown shape");
}

Two questions determine the refactoring:

1. Does shapeType vary at runtime (computed value), or is it always a literal at call sites? 2. Are new shape types expected?

If both answers are yes: Pattern 6 β€” Replace Conditional with Polymorphism. Create Circle, Rectangle, Triangle subclasses; each implements area(). Adding Pentagon = adding a class.

If the type set is stable and callers always pass literals: Pattern 7 β€” Replace Parameter with Explicit Methods. Create circleArea(), rectangleArea(), triangleArea() methods. Simpler, statically checkable, no hierarchy overhead.

Decision rule: When types will grow or the conditional appears in multiple places β†’ polymorphism. When types are fixed, the conditional is in one place, and callers always pass constants β†’ explicit methods.


Example 2: Identifying a Null Object Opportunity

Scenario: Three separate methods in client code contain:

if (customer == null) plan = BillingPlan.basic();
else plan = customer.getPlan();

if (customer == null) name = "occupant"; else name = customer.getName();

if (customer == null) weeksDelinquent = 0; else weeksDelinquent = customer.getHistory().getWeeksDelinquentInLastYear();

Classification: Pattern 8 β€” the same object (customer) is null-checked in multiple clients, each providing a sensible default.

Apply Introduce Null Object:

class NullCustomer extends Customer {
    public boolean isNull()          { return true; }
    public String getName()          { return "occupant"; }
    public BillingPlan getPlan()     { return BillingPlan.basic(); }
    public PaymentHistory getHistory() { return PaymentHistory.newNull(); }
}
// class NullPaymentHistory: getWeeksDelinquentInLastYear() returns 0

// Site returns NullCustomer instead of null: Customer getCustomer() { return (_customer == null) ? Customer.newNull() : _customer; }

// Clients become: plan = customer.getPlan(); name = customer.getName(); weeksDelinquent = customer.getHistory().getWeeksDelinquentInLastYear();

The three conditional blocks disappear. Note that null objects often return other null objects β€” NullCustomer.getHistory() returns NullPaymentHistory, which itself returns sensible defaults.


View on ClawHub
TERMINAL
clawhub install bookforge-conditional-simplification-strategy

πŸ§ͺ Use this skill with your agent

Most visitors already have an agent. Pick your environment, install or copy the workflow, then run the smoke-test prompt above.

πŸ” Can't find the right skill?

Search 60,000+ AI agent skills β€” free, no login needed.

Search Skills β†’