More actions
imported>Unknown No edit summary |
(Repair MoniWiki formatting after migration) |
||
| Line 2: | Line 2: | ||
= Chapter 9 Simplifying Conditional Expressions = | = Chapter 9 Simplifying Conditional Expressions = | ||
== Decompose Conditional == | == Decompose Conditional == | ||
* You have a complicated conditional (if-then-else) statement. | * You have a complicated conditional (if-then-else) statement. <br /> ''Extract methods from the condition, then part, and else parts.'' | ||
if (data.before( SUMMER_START ) || data.after(SUMMER_END) ) | if (data.before( SUMMER_START ) || data.after(SUMMER_END) ) | ||
charge = quantity * _winterRate + _winterServeceCharge; | charge = quantity * _winterRate + _winterServeceCharge; | ||
| Line 11: | Line 11: | ||
else charge = summerCharge(quatity); | else charge = summerCharge(quatity); | ||
== Consolidate Conditional Expression == | == Consolidate Conditional Expression == | ||
* You have a sequence of conditional tests with the same result. ''Combine them into a single conditional expression and extract it.'' | * You have a sequence of conditional tests with the same result. <br />''Combine them into a single conditional expression and extract it.'' | ||
double disabilityAmount() { | double disabilityAmount() { | ||
if (_seniority < 2) return 0; | if (_seniority < 2) return 0; | ||
| Line 21: | Line 21: | ||
// compute the disability amount; | // compute the disability amount; | ||
== Consolidate Duplicate Conditional Fragments == | == Consolidate Duplicate Conditional Fragments == | ||
* The same fragment of code is in all branches of a conditional expression. ''Move it outside of the expression.'' | * The same fragment of code is in all branches of a conditional expression. <br />''Move it outside of the expression.'' | ||
if (isSpecialDeal()){ | if (isSpecialDeal()){ | ||
total = price * 0.95; | total = price * 0.95; | ||
| Line 36: | Line 36: | ||
send(); | send(); | ||
== Replace Nested Conditional with Guard Clauses == | == Replace Nested Conditional with Guard Clauses == | ||
* A method has conditional behavior that does not make clear the normal path of execution | * A method has conditional behavior that does not make clear the normal path of execution <br /> ''Use guard clauses for all the special cases.'' | ||
double getPayAmount(){ | double getPayAmount(){ | ||
double result; | double result; | ||
| Line 55: | Line 55: | ||
return normalPayAmount(); | return normalPayAmount(); | ||
== Replace Conditional with Polymorphism == | == Replace Conditional with Polymorphism == | ||
* You have a conditional that chooses different behavior depending on the type of and object | * You have a conditional that chooses different behavior depending on the type of and object <br /> ''Move each leg of the conditional to an overriding method in a subclass. Make the orginal method abstract.'' | ||
double getSpeed() { | double getSpeed() { | ||
switch (_type) { | switch (_type) { | ||
| Line 84: | Line 84: | ||
== Introduce Null Object == | == Introduce Null Object == | ||
* You have repeated checks for a null value ''Replace the null value with a null object.'' | * You have repeated checks for a null value<br /> ''Replace the null value with a null object.'' | ||
if (customer == null) plan = BillingPlan.basic(); | if (customer == null) plan = BillingPlan.basic(); | ||
else plan = customer.getPlan(); | else plan = customer.getPlan(); | ||
| Line 101: | Line 101: | ||
== Introduce Assertion == | == Introduce Assertion == | ||
* A section of code assumes something about the state of the program. ''Make the assumption explicit with an assertion.'' | * A section of code assumes something about the state of the program. <br />''Make the assumption explicit with an assertion.'' | ||
double getExpenseLimit() { | double getExpenseLimit() { | ||
//should have eigher expense limit or a primary project | //should have eigher expense limit or a primary project | ||
| Line 115: | Line 115: | ||
---- | ---- | ||
[[Refactoring]] | [[Refactoring]] | ||
Revision as of 14:01, 26 March 2026
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();