代码重构整理小结(吐槽)

近期接手了一个项目,前期项目为了快速上线,几乎是复制了另一个项目的代码。现在迭代逐渐趋于平稳,在修复bug的过程中慢慢对代码进行重构。这个过程是相当的痛苦!!!(真怀念当前跟通爷干活的时候~~)

举一个例子:

重构一个弹窗

以下代码片段是重构以后的一个方法,作用是刷新界面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void updateView() {

boolean isLogin = QDUserManager.getInstance().isLogin();
int balance = getBalance();

setBalanceView(isLogin, balance);
// 顶部免费、免费+订阅
setTopChaptersItemInfo(mHasVIP);
// 设置第一个vip章节
setStartTextView(mHasVIP);
// 章节的档位
mSelectableLayout.setVisibility(mHasVIP ? View.VISIBLE : View.GONE);
mBatchAdapter.notifyDataSetChanged();
// 设置底部 订阅 + 充值
setBottomView(isLogin, balance, mSelectedPrice);
showLoadingView(false);
}

再来看一看重构之前的代码,不要被吓到!

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public void updateView() {
showBalance = balance;
boolean isLogin = QDUserManager.getInstance().isLogin();
//余额
boolean isShowBalance = QDUserManager.getInstance().isLogin() && balance >= 0; // fixme isLogin多余
String balanceString = String.format(mContext.getString(R.string.batch_yue),isShowBalance ? String.valueOf(showBalance) : " -- ");
userBalanceTxv.setText(balanceString);
userBalanceTxv.setVisibility(isLogin ? View.VISIBLE : View.GONE);

//是否显示下载免费及已订阅章节
setTopChaptersItemInfo();

//是否显示选择章节下载(20章/100章节)
if (mHasVIP) {
selectable_layout.setVisibility(View.VISIBLE);
setStartTextView();
if (mBatchAdapter != null) {
mBatchAdapter.notifyDataSetChanged();
}
} else {
selectable_layout.setVisibility(View.GONE);
}

// fixme 多余
if (balance != -1) {
quickChargeView.setBuyPrice(showBalance,selectedFee);
} else {
quickChargeView.setVisibility(View.GONE);
}
//控制显示登录/订阅/充值
if (isLogin) {
if (balance >= 0) {
if (showBalance < selectedFee) {
quickChargeView.setBuyPrice(balance,selectedFee);
quickChargeView.setVisibility(View.VISIBLE);
batchOrderLayout.setVisibility(View.GONE);
} else {
switch (userSelectItem) {
case Type_Selected_Ordered_And_Free:
case Type_Selected_Free:
batchOrderTxv.setText(getString(R.string.batch_download));
break;
case Type_Selected_10:
case Type_Selected_30:
case Type_Selected_50:
case Type_Selected_100:
case Type_Selected_all:
default:
batchOrderTxv.setText(String
.format(getString(R.string.batch_order_download2), String.valueOf(selectedFee)));
break;
}
batchOrderLayout.setVisibility(View.VISIBLE);
load_layout.setVisibility(View.VISIBLE); // fixme 多余
quickChargeView.setVisibility(View.GONE);
}

if (isDownLoading || isBuying || quickCharging) {//如果在下载中 设置为不可点击
batchOrderLayout.setEnabled(false);
} else {
batchOrderLayout.setEnabled(true);
}
} else {//没拉到数据
load_layout.setVisibility(View.VISIBLE); // fixme 多余
quickChargeView.setVisibility(View.GONE);
batchOrderTxv.setText(mContext.getString(R.string.xiazai));
batchOrderLayout.setEnabled(false);
}
} else {
batchOrderTxv.setText(mContext.getString(R.string.dengluxiazai));
load_layout.setVisibility(View.VISIBLE); // fixme 多余
quickChargeView.setVisibility(View.GONE);
batchOrderLayout.setEnabled(true);
}
handler.sendEmptyMessage(Message_Update_Finshed);

// fixme ???
batchOrderLayout.setEnabled(true);
showLoadingView(false);
}

一个方法快100行,各种ifelse逻辑嵌套!写这种妖魔鬼怪代码的人不怕被人骂吗!!!上面的问题至少10十几处问题:

1、showBalance和balance同为成员变量,同样表示余额,赋值相等,方法体内一会showBalance一会用balance。而且在整个类中两个变量的意义都是相同的!
2、创建isLogin局部变量后,仍然用QDUserManager.getInstance().isLogin()获取登陆态,多余的方法调用
3、字符串硬编码
4、mBatchAdapter在创建类时已经创建,类中其他地方没有置空操作,不存在空的可能性
5、设置quickChargeView的Visiblility重复了两次,判断balance是否为-1那次完全无意义。
6、batchOrderLayout设置enable重复。在ifelse里面根据条件设置了enable,在最后又统一设置了true!!!
7、load_layout命名不规范,设置Visiblility无意义,在整个类中一直是Visible状态。
8、if else嵌套过深
9、方法体太长,完全可以拆分为几个功能单一,命名更有意义的方法。
10、刷新view的方法访问权限完全可以为private

这还只是一个方法,整个类1500行代码,无效代码、重复逻辑随处可见!重构下来只剩800行,加上同一功能相关的类一起花了4天!另外这个弹窗在项目中只是简单的一块,想想整个工程都是这副鬼样子,真的头大!道阻且长长长长长长长长~~~~

最后,希望诸君写代码的时候多思考一下代码的原则:

  • 单一职责原则 Single Responsibility Principle
  • 里氏替换原则 Liskov Substitution Principle
  • 依赖倒置原则 Dependence Inversion Principle
  • 接口隔离原则 Interface Segregation Principle
  • 迪米特法则 Law of Demeter
  • 合成复用原则
  • 开闭原则