Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Refactoring/SimplifyingConditionalExpressions

From ZeroWiki

Chapter 9 Simplifying Conditional Expressions

Decompose Conditional

  • You have a complicated conditional (if-then-else) statement.
    Extract methods from the condition, then part, and else parts.
    if (data.before( SUMMER_START ) || data.after(SUMMER_END) )
        charge = quantity * _winterRate + _winterServeceCharge;
    else charge = quantity * _summerRate;
    if (notSummer(date))
        charge = winterCharge(quantity);
    else charge = summerCharge(quatity);

Consolidate Conditional Expression

  • You have a sequence of conditional tests with the same result.
    Combine them into a single conditional expression and extract it.
    double disabilityAmount() {
        if (_seniority < 2) return 0;
        if ( _monthsDisabled > 12) return 0;
        if ( _isPartTime) return 0;
        // compute the disability amount
    double disabilityAmount() {
        if( isNotEligableForDisability()) return 0;
        // compute the disability amount;

Consolidate Duplicate Conditional Fragments

  • The same fragment of code is in all branches of a conditional expression.
    Move it outside of the expression.
if (isSpecialDeal()){
    total = price * 0.95;
    send();
}
else {
    total = price * 0.98;
    send();
}
if (isSpecialDeal())
    total = price * 0.95
else     
    total = price * 0.98;
send();

Replace Nested Conditional with Guard Clauses

  • A method has conditional behavior that does not make clear the normal path of execution
    Use guard clauses for all the special cases.
double getPayAmount(){
    double result;
    if( _isDead) result = deadAmount();
    else {
        if (_isSeparated) result = separatedAmount();
        else {
            if (_isRetried) result = retiredAmount();
            else result = normalPayAmount();
        };
    }
    return result;
double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetried) return retiredAmount();
    return normalPayAmount();

Replace Conditional with Polymorphism

  • You have a conditional that chooses different behavior depending on the type of and object
    Move each leg of the conditional to an overriding method in a subclass. Make the orginal method abstract.
    double getSpeed() {
        switch (_type) {
            case EUROPEAN:
                return getBaseSpeed();
            case AFRICAN:
                return getBaseSpeed() - getLoadFactor() * _numberofCoconuts;
            case NORWEGIAN_BLUE:
                return (_isNailed) ? 0 : getBaseSpeed(_voltage);
        }
        throw new RuntimeException ("Should be unreachable");
    }
                ┌─────┐
                │  Bird    │
                ├─────┤
                │getSpeed  │
                └─────┘
                      △
                      │
      ┌───────┼─────────┐
      │              │                  │
┌──┴──┐  ┌──┴──┐  ┌────┴──┐
│European| │  │African   │  │Norwegian Blue│
├─────┤  ├─────┤  ├───────┤
│getSpeed  │  │getSpeed  │  │getSpeed      │
└─────┘  └─────┘  └───────┘

Introduce Null Object

  • You have repeated checks for a null value
    Replace the null value with a null object.
    if (customer == null) plan = BillingPlan.basic();
    else plan = customer.getPlan();
          ┌───────┐
          │  Cutomer     │
          ├───────┤
          │getPlan       │
          └───────┘
                  △
                  │
          ┌───┴───┐
          │Null Customer │
          ├───────┤
          │getPlan       │
          └───────┘                

Introduce Assertion

  • A section of code assumes something about the state of the program.
    Make the assumption explicit with an assertion.
    double getExpenseLimit() {
        //should have eigher expense limit or a primary project
        return (_expenseLimit != NULL_EXPENSE)?
                _expenseLimit:
                _primaryProject.getMemberExpenseLimit();
    }
    double getExpenseLimit() {
        Assert.isTrue( _expenseLimit != NULL_EXPENSE || _primaryProject != null );
        return (_expenseLimit != NULL_EXPENSE)?
                _expenseLimit:
                _primaryProject.getMemberExpenseLimit();

Refactoring