U E D R , A S I H C RSS

Refactoring/Simplifying Conditional Expressions

1. Chapter 9 Simplifying Conditional Expressions

1.1. Decompose Conditional

  • You have a complicated conditional (if-then-else) statement.
    Extract methods from the condition, then part, and else parts.

~cpp 
    if (data.before( SUMMER_START ) || data.after(SUMMER_END) )
        charge = quantity * _winterRate + _winterServeceCharge;
    else charge = quantity * _summerRate;

~cpp 
    if (notSummer(date))
        charge = winterCharge(quantity);
    else charge = summerCharge(quatity);

1.2. Consolidate Conditional Expression

  • You have a sequence of conditional tests with the same result.
    Combine them into a single conditional expression and extract it.

~cpp 
    double disabilityAmount() {
        if (_seniority < 2) return 0;
        if ( _monthsDisabled > 12) return 0;
        if ( _isPartTime) return 0;
        // compute the disability amount
~cpp 
    double disabilityAmount() {
        if( isNotEligableForDisability()) return 0;
        // compute the disability amount;

1.3. Consolidate Duplicate Conditional Fragments

  • The same fragment of code is in all branches of a conditional expression.
    Move it outside of the expression.

~cpp 
if (isSpecialDeal()){
    total = price * 0.95;
    send();
}
else {
    total = price * 0.98;
    send();
}
~cpp 
if (isSpecialDeal())
    total = price * 0.95
else     
    total = price * 0.98;
send();

1.4. 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.

~cpp 
double getPayAmount(){
    double result;
    if( _isDead) result = deadAmount();
    else {
        if (_isSeparated) result = separatedAmount();
        else {
            if (_isRetried) result = retiredAmount();
            else result = normalPayAmount();
        };
    }
    return result;

~cpp 
double getPayAmount() {
    if (_isDead) return deadAmount();
    if (_isSeparated) return separatedAmount();
    if (_isRetried) return retiredAmount();
    return normalPayAmount();

1.5. 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.

~cpp 
    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");
    }

~cpp 
                ┌─────┐
                │  Bird    │
                ├─────┤
                │getSpeed  │
                └─────┘
                      △
                      │
      ┌───────┼─────────┐
      │              │                  │
┌──┴──┐  ┌──┴──┐  ┌────┴──┐
│European| │  │African   │  │Norwegian Blue│
├─────┤  ├─────┤  ├───────┤
│getSpeed  │  │getSpeed  │  │getSpeed      │
└─────┘  └─────┘  └───────┘

1.6. Introduce Null Object

  • You have repeated checks for a null value
    Replace the null value with a null object.

~cpp 
    if (customer == null) plan = BillingPlan.basic();
    else plan = customer.getPlan();
~cpp 
          ┌───────┐
          │  Cutomer     │
          ├───────┤
          │getPlan       │
          └───────┘
                  △
                  │
          ┌───┴───┐
          │Null Customer │
          ├───────┤
          │getPlan       │
          └───────┘                

1.7. Introduce Assertion

  • A section of code assumes something about the state of the program.
    Make the assumption explicit with an assertion.

~cpp 
    double getExpenseLimit() {
        //should have eigher expense limit or a primary project
        return (_expenseLimit != NULL_EXPENSE)?
                _expenseLimit:
                _primaryProject.getMemberExpenseLimit();
    }
~cpp 
    double getExpenseLimit() {
        Assert.isTrue( _expenseLimit != NULL_EXPENSE || _primaryProject != null );
        return (_expenseLimit != NULL_EXPENSE)?
                _expenseLimit:
                _primaryProject.getMemberExpenseLimit();

Refactoring
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-05-27 07:09:19
Processing time 0.2954 sec