关闭

Clean Code 读书笔记九

标签: code-monsterjava方法
514人阅读 评论(0) 收藏 举报
分类:

要点汇总:

一般性问题

方法名称应该准确表达其具体行为
比如:

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

测试

  • 使用测试覆盖工具

  • 测试边境条件
    很多问题都出在边界上,如数组越界等等。注意边境!

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:84891次
    • 积分:2231
    • 等级:
    • 排名:第17822名
    • 原创:114篇
    • 转载:11篇
    • 译文:1篇
    • 评论:49条
    最新评论