[Clean Code] Chapter 3: 函数!

函数


1、Small! 小巧!

The first rule of functions is that they should be small.

The second rule of functions is that they should be smaller than that.


2、Do One Thing! 只做一件事!

FUNCTIONS SHOULD DO ONE THING.

THEY SHOULD DO IT WELL.

THEY SHOULD DO IT ONLY.

函数要只做一件事,并做好它!


怎么知道什么是 DO ONE THING

如果你能从函数A中提取另一个函数B ,而且这个函数B不是A的另一个实现


3、One Level of Abstraction per Functions 函数逻辑应处于同一层抽象


4、The Stepdown Rule 步步深入原则

提取不同的抽象层次,确保function do one thing.


5、switch

对于switch, 如果使用在生成具体对象,并且隐藏在继承关系下,是可以接受的,因为系统其他部分将看不到他们。

对比下面代码

// 代码片段1,如果不使用抽象基类继承做,会导致在其他相关函数也会有switch的判断!!!!
// 譬如: isPayday(Employee e, Date date)
public Money calculatePay(Employee e) throws InvalidEmployeeType {
    switch (e.type) {
        case COMMISSIONED:
            return calculateCommissionedPay(e);
        case HOURLY:
            return calculateHourlyPay(e);
        case SALARIED:
            return calculateSalariedPay(e);
        default:
            throw new InvalidEmployeeType(e.type);
    }
}
public abstract class Employee {
    public abstract boolean isPayday();
    public abstract Money calculatePay();
    public abstract void deliverPay(Money pay);
}

public interface EmployeeFactory {
    public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType;
}

// 将 switch 使用在生成具体的对象上
public class EmployeeFactoryImpl implements EmployeeFactory {
    public Employee makeEmployee(EmployeeRecord r) throw InvalidEmployeeType {
        switch (r.type) {
        case COMMISSIONED:
            return new CommissionedEmployee(r) ;
        case HOURLY:
            return new HourlyEmployee(r);
        case SALARIED:
            return new SalariedEmploye(r);
        default:
            throw new InvalidEmployeeType(r.type);
        }
    }
}

6、起个好名字

描述准确,不怕长,和其他函数统一动名词


7、参数

0参数:好极了

1参数:挺好

2参数:还不错

3参数:如果允许,我应该避免这么做

3+参数: never !


8、Flag 参数

传参true or false 做不同的事情???直接违背do one thing原则。

我们可以将他分割成两个函数来解决此问题。

// 例如
render(boolean isSuite);
|
+-- renderForSuite();
|
+-- renderForSingleTest();

9、 拒绝Side Effects(副作用)!

// 事例代码
public class UserValidator {
    private Cryptographer cryptographer;

    public boolean checkPassword(String userName, String password) {
        User user = UserGateway.findByName(userName);
        if (user != User.NULL) {
            String codedPhrase = user.getPhraseEncodedByPassword();
            String phrase = cryptographer.decrypt(codedPhrase, password);
            if ("Valid Password".equals(phrase)) {
                // 此处做了其他事情,违背了DO ONE THING!
                // 假如session已经存在,将导致不预期的结果
                Session.initialize();
                return true;
            }
        }
        return false;
    }
}

10、查询和命令分离

// 如果存在attribute, 设置其值,返回true, 若不存在,返回false
public boolean set(String attribute, String value);

// 读代码的人一定蒙比
if (set("username", "unclebob")) ...

VS

// 这儿反而清晰的多
if (attributeExists("username")) { 
    setAttribute("username", "unclebob"); 
    ...
}

11、用异常,而不用返回错误码


12、提取try/catch块

try/catch 会导致代码太丑了。理解和修改都不太方便。

// Do one thing.全是关于错误处理的
public void delete(Page page) {
    try {
        deletePageAndAllReferences(page);
    }
    catch (Exception e) {
        logError(e);
    }
}

// 第二抽象层,是delete的下属抽象层,
// 注意已经没有try/catch, 逻辑清晰
private void deletePageAndAllReferences(Page page) throws Exception {     
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}

// error 处理
private void logError(Exception e) {
    logger.log(e.getMessage());
}

函数要只做一件事,而且错误处理是一件事,所以catch finally之后应该没有其他的东西了!!!


13、不要使用相似的函数名!别产生confusion!


总结

  • Do one thing!
  • Do it well!
  • Do it only!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值