1.Decompose Conditional(分解条件表达式)

2.Consolidate Conditional Expressions(合并条件表达式)

3.Consolidate Duplicate Conditional Fragments(合并重复的条件片段)

4.Remove Control Flag(移除控制标记)

5.Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件表达式)

6.Replace Conditional with Polymorphism(以多态取代条件表达式)

7.Introduce Null Object(引入null对象)

8.Indroduce Assertion(引入断言)

1.Decompose Conditional(分解条件表达式)

当有复杂的if else判断时,应该将条件判断抽成方法,使代码思路更清晰,即使是简短的判断,抽成方法也会对代码的可读性起到很大的提升作用.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (date.before (SUMMER_START) || date.after(SUMMER_END))
charge = quantity * _winterRate + _winterServiceCharge;
else charge = quantity * _summerRate;
---------
if (notSummer(date))
charge = winterCharge(quantity);
else charge = summerCharge (quantity);
private boolean (Date date) {
return date.before (SUMMER_START) || date.after(SUMMER_END);
}
private double summerCharge(int quantity) {
return quantity * _summerRate;
}
private double winterCharge(int quantity) {
return quantity * _winterRate + _winterServiceCharge;
}

像这个例子不知道会不会有点过头了?

2.Consolidate Conditional Expressions(合并条件表达式)

当众多条件的结果是一样时,应将其合并为一个方法.

1
2
3
4
5
6
7
8
9
10
11
12
double disabilityAmount() {
if (_seniority < 2) return 0;
if (_monthsDisabled > 12) return 0;
if (_isPartTime) return 0;
}
---------
double disabilityAmount() {
if (isNotEligableForDisability()) return 0;
}
boolean isNotEligibleForDisability() {
return ((_seniority < 2) || (_monthsDisabled > 12) || (_isPartTime));
}

3.Consolidate Duplicate Conditional Fragments(合并重复的条件片段)

条件判断中相同部分的代码应该移出条件表达式,这样你能看出来哪些是一样的哪些是不一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
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();

这个哥一直是这样做的:)

4.Remove Control Flag(移除控制标记)

可以使用break,continue或return来替换控制标签,增强代码可读性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
void checkSecurity(String[] people) {
boolean found = false;
for (int i = 0; i < people.length; i++) {
if (! found) {
if (people[i].equals ("Don")){
sendAlert();
found = true;
}
if (people[i].equals ("John")){
sendAlert();
found = true;
}
}
}
}
------
void checkSecurity(String[] people) {
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){
sendAlert();
break;
}
if (people[i].equals ("John")){
sendAlert();
break;
}
}
}
//example2
void checkSecurity(String[] people) {
String found = "";
for (int i = 0; i < people.length; i++) {
if (found.equals("")) {
if (people[i].equals ("Don")){
sendAlert();
found = "Don";
}
if (people[i].equals ("John")){
sendAlert();
found = "John";
}
}
}
someLaterCode(found);
}
----------
void checkSecurity(String[] people) {
String found = foundMiscreant(people);
someLaterCode(found);
}
String foundMiscreant(String[] people){
for (int i = 0; i < people.length; i++) {
if (people[i].equals ("Don")){
sendAlert();
return "Don";
}
if (people[i].equals ("John")){
sendAlert();
return "John";
}
大专栏  Simplifying Conditional Expressions(简化条件表达式)v class="line"> }
return "";
}

5.Replace Nested Conditional with Guard Clauses(以卫语句取代嵌套条件表达式)

用卫语句代替所有特殊的case。卫语句:check the condition and return if the condition is true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
double getPayAmount() {
double result;
if (_isDead) result = deadAmount();
else {
if (_isSeparated) result = separatedAmount();
else {
if (_isRetired) result = retiredAmount();
else result = normalPayAmount();
};
}
return result;
};
----------
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
};

6.Replace Conditional with Polymorphism(以多态取代条件表达式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Employee...
int payAmount() {
return _type.payAmount(this);
switch (getType()) {
case EmployeeType.ENGINEER:
return _monthlySalary;
case EmployeeType.SALESMAN:
return _monthlySalary + _commission;
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException("Incorrect Employee");
}
}
int getType() {
return _type.getTypeCode();
}
private EmployeeType _type;
-------------------------------
abstract class EmployeeType...
abstract int getTypeCode();
abstract int payAmount(Employee emp);
class Engineer extends EmployeeType...
int getTypeCode() {
return Employee.ENGINEER;
}
int payAmount(Employee emp) {
return emp.getMonthlySalary();
}
class Salesman...
int payAmount(Employee emp) {
return emp.getMonthlySalary() + emp.getCommission();
}
class Manager...
int payAmount(Employee emp) {
return emp.getMonthlySalary() + emp.getBonus();
}

7.Introduce Null Object(引入null对象)

当每次取数据时如果都要去判空的话会非常耗体力,并且代码非常难看,还有可能有漏掉的情况。这时可以引入一个null对象来解决,null是在对象没有值时的默认值,省去判空的动作,easying+happy呀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Site...
Customer getCustomer() {
return _customer;
}
Customer _customer;
class Customer...
public String getName() {...}
public BillingPlan getPlan() {...}
public PaymentHistory getHistory() {...}
public class PaymentHistory...
int getWeeksDelinquentInLastYear()
//example
Customer customer = site.getCustomer();
BillingPlan plan;
if (customer == null) plan = BillingPlan.basic();
else plan = customer.getPlan();
String customerName;
if (customer == null) customerName = "occupant";
else customerName = customer.getName();
int weeksDelinquent;
if (customer == null) weeksDelinquent = 0;
else weeksDelinquent = customer.getHistory().getWeeksDelinquentInLastYear();
---------
class Customer...
static Customer newNull() {
return new NullCustomer();
}
class NullCustomer extends Customer {
public boolean isNull() {
return true;
}
public String getName(){
return "occupant";
}
}
class Site...
Customer getCustomer() {
return (_customer == null) ? Customer.newNull(): _customer;
}
//当NullCustomer有自己的getName方法时
String customerName = customer.getName();

8.Indroduce Assertion(引入断言)

通过断言来调试

1
2
3
4
5
6
7
8
9
10
11
12
13
double getExpenseLimit() {
// should have either 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();
}