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










