要点汇总:
一般性问题
方法名称应该准确表达其具体行为
比如:
Date newDate = date.add(5)//加5天?5个月?
最好使用addDaysTo 或increaseByDays 明确方法的行为。
- 使用多态 代替 switch或if else
比如:
class RequestHandler {
public void handleRequest(int action) {
switch(action) {
case LOGIN:
doLogin();
break;
case LOGOUT:
doLogout();
break;
case QUERY:
doQuery();
break;
}
}
}
interface Command {
public void execute();
}
class LoginCommand implements Command {
public void execute() {
// do what doLogin() used to do
}
}
class RequestHandler {
private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
public void handleRequest(int action) {
Command command = commandMap.get(action);
command.execute();
}
}
- 用命名常量代替魔法数字
不多说,代码中出现某个数字,如21,你知道什么意思么?
这样 CommonConstants.AVERAGE_AGE=21,使用更好。
- 不要再判断中写一堆&& ||的判断
看看下边那个更易于理解
if (shouldBeDeleted(timer))
if (timer.hasExpired() && !timer.isRecurrent())
- 避免否定性调节:
肯定性条件比否定性条件更容易理解
比如下边那一行更易理解呢?
if (buffer.shouldCompact())
if (!buffer.shouldNotCompact())
- 方法只做一件事
public void pay() {
for (Employee e: employees) {
if (e.isPayday()) {
Money pay = e.calculatePay();
e.deliverPay(pay);
}
}
}
重构:
public void pay() {
for (Employee e: employees)
payIfNecessary(e);
}
private void payIfNecessary(Employee e) {
if (e.isPayday()) calculateAndDeliverPay(e);
}
private void calculateAndDeliverPay(Employee e) {
Money pay = e.calculatePay();
e.deliverPay(pay);
}
- 让时序耦合的代码更明显
public class MoogDiver {
Gradient gradient;
List < Spline > splines;
public void dive(String reason) {
saturateGradient();
reticulateSplines();
diveForMoog(reason);
}...
}
saturateGradient();reticulateSplines(); diveForMoog(reason);
三者的关系并没有很好的突出,更好的重构是:
public class MoogDiver {
Gradient gradient;
List < Spline > splines;
public void dive(String reason) {
Gradient gradient = saturateGradient();
List < Spline > splines = reticulateSplines(gradient);
diveForMoog(splines, reason);
}...
}
- 使用枚举代替常量
不要在用
public static fianl int ....
使用enum代替
- Don’t Inherit Constants
public class HourlyEmployee extends Employee {
private int tenthsWorked;
private double hourlyRate;
public Money calculatePay() {
int overTime = tenthsWorked - straightTime;
return new Money(
hourlyRate * (tenthsWorked + OVERTIME_RATE * overTime));
}...
}
TENTHS_PER_WEEK 、OVERTIME_RATE这两个常量来自哪里?
public abstract class Employee implements PayrollConstants {
public abstract boolean isPayday();
public abstract Money calculatePay();
public abstract void deliverPay(Money pay);
}
public interface PayrollConstants {
public static final int TENTHS_PER_WEEK = 400;
public static final double OVERTIME_RATE = 1.5;
}
这种通过继承或实现的方式获取常量,是对常量作用域的忽视,怪异的使用。应该用引入静态类的方式在代码中直接使用常量。
import static PayrollConstants.*;
名称与命名
使用描述性名称
名称很重要,一个准确的名称可以大幅度提高代码的可读性。
public int x() {
int q = 0;
int z = 0;
for (int kk = 0; kk < 10; kk++) {
if (l[z] == 10) {
q += 10 + (l[z + 1] + l[z + 2]);
z += 1;
} else if (l[z] + l[z + 1] == 10) {
q += 10 + l[z + 2];
z += 2;
} else {
q += l[z] + l[z + 1];
z += 2;
}
}
return q;
}
public int score() {
int score = 0;
int frame = 0;
for (int frameNumber = 0; frameNumber < 10; frameNumber++) {
if (isStrike(frame)) {
score += 10 + nextTwoBallsForStrike(frame);
frame += 1;
} else if (isSpare(frame)) {
score += 10 + nextBallForSpare(frame);
frame += 2;
} else {
score += twoBallsInFrame(frame);
frame += 2;
}
}
return score;
}
两段代码对比一下即可知道名称的重要。
- 变量的作用范围越大,越应该重视名称的重要。
- 不要用名称掩盖了内容。
public ObjectOutputStream getOos() throws IOException {
if (m_oos == null) {
m_oos = new ObjectOutputStream(m_socket.getOutputStream());
}
return m_oos;
}
更准确的名称应该是: createOrReturnOos
测试
- 使用测试覆盖工具
- 测试边境条件
很多问题都出在边界上,如数组越界等等。注意边境!
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-08-11 05:34:08