《代码整洁之道》归纳 (1)

1. 书籍信息

书名:《Clean Code : A Handbook of Agile Software Craftsmanship》

翻译:韩磊

引用:[USA]Martin R C . 代码整洁之道[M]. 人民邮电出版社, 2010.

2. 第二章:有意义的命名总结

2.1. 名副其实

[1]变量、函数、或类的名称应该已经答复了所有的大问题,它应该告诉你为什么存在,做什么事,应该怎么做;

// 反例
int d; //消逝的时间

//正例

int elapsedTimeInDays;
int daysSinceCreation;
int fileAgeInDays;

[2]多用常量表示数字的意义,不要在判断式中使用数字或字符串;

// 反例
if (list[0] == 4)
dosomething();

// 正例
if (cell[STATUS_VALUE] == FLAGGED)
dosomething();

2.2. 避免误导

[1]不用accounList来指代账号列表,除非它真的是List类型,可用accounts代替;

[2]同一文件中不使用相似度高的词汇命名,不使用英文字母o/l、数字0/1命名;

2.3. 有意义的区分

[1]用source/target命名函数参数好过用a1/a2

[2]Table一词不出现在表的命名中,Variable一词不出现在变量名中,不必用m_作为成员变量的前缀,不必用I/Abstact作为接口或者抽象类的前缀;

2.4. 一以贯之

[1]在fetch/retrieve/get中选一个表示获取,在controller/manager/driver中选一个表示驱动;

[2]用insert表示添加数据好过用add

2.5. 使用解决方案领域名称

[1]代码是给程序员看的,尽量用计算机科学领域名称命名,如Visitor表示观察者,不要让程序员为了读懂代码去问客户名称的含义;

[2]如果不能用程序员熟悉的术语命名,就用问题所涉及的领域来命名;

2.6. 添加有意义的语境

[1]name/state等变量前面添加addrName/addrState让人更能明白这组变量是在描述一个联系地址,当然创建一个Adress的实体类更好;

[2]不要添加没有意义的语境,一个管理系统(Manage System)的账号实体类,用Account就行,没必要加上MSAccountMSAddress

3. 第三章:函数

3.1. 短小

[1]函数的第一规则是要短小,第二规则是还要更短小;

// 反例(改良版,更糟糕的上百行了)
public static String renderPageWithSetupAndTeardowns(
 PageData pageData, boolean isSuite
) throws Exception {
    boolean isTestPage = pageData.hasAttribute("Test");
    if (isTestPage) {
        WikiPage testPage = pageData.getWikiPage();
        StringBuffer newPageContent = new StringBuffer();
        // balabala...
        includeTeardownPages(testPage, newPageContent, isSuite);
        pageData.setContent(newPageContent.toString());
    }
    return pageData.getHtml();
}

//正例(究极改良版,不属于该函数同一抽象层的代码全部另立新篇)
public static String renderPageWithSetupAndTeardowns(
 PageData pageData, boolean isSuite
) throws Exception {
    if (isTestPage(pageData) 
      includeSetupAndTeardownPages(pageData, isSuite);
    return pageData.getHtml();
}

[2]if/else/while语句等,其中的代码块应该只有一行,所以函数缩进层级不应该多余一层或者两层;

3.2. 只做一件事

[1]函数应该做一件事,做好这件事,只做这一件事;

上一正例的函数renderPageWithSetupAndTeardowns看起来做了三件事,其实这三个步骤均在该函数的同一抽象层上,可以用简洁的TO起头段落来描述:To Render Page With Setup and Teardowns.

// 反例
public Boolean checkPassWord(String username, String password) {
    String phrase = getCodePhraseEncodedByUsername(username);
    if (VALID_OK.equals(password)){
        /* 验证密码成功后初始化会话在逻辑上没问题,但如果调用者只是想验证密码                * 你却让它做了更多余的甚至没必要的动作
        */
        Session.initialize();
        return true;
    }
    return false;
}

[2]如果函数中不断出现重复代码,说明这些重复代码可以做一件事;

3.3. 每个函数一个抽象层级

自顶向下读代码:向下规则,程序就像是一系列的TO起头的段落,每一段都描述当前抽象层级,并引用位于下一抽象层级的后续TO起头段落;

如:

  1. To do thing No.1, we do thing No.2, then do thing No.3;
  2. To do thing No.2, we do thing No.4;
  3. To do thing No.3, we do thing No.5;
doThingNo1() {
    doThingNo2();
    doThingNo3();
}

doThingNo2() {
    doThingNo4();
}

doThingNo3() {
    doThingNo5();
}

3.4. 函数参数

[1]最理想的参数数量是零,其次是一,再次是二,应尽量避免三个参数,如果需要更多参数,说明其中一些参数应该封装为类了;

[2]尽量避免使用输出参数,我们期望通过返回值输出;

[3]使用参数列表Object... args好过使用二元函数、三元函数;

3.5. 分隔指令与询问

下列函数中设置某个指定属性,如果成功就返回true,如果不存在那个属性则返回false

public boolean set(String attr, String value);

这样就导致了以下语句:

if (set("username", "unclebob"))...

作者本意,set是个动词,但在if语句上下文中,它像个形容词。要解决这个问题,就要把指令与询问分隔开来:

if (attrExists("username")) {
    setAttr("username", "unclebob");
}

3.6. 使用异常捕获代替返回错误码

[1]创建返回错误码的枚举是不推荐的做法,这样一来如果需求改变,枚举就得修改,其它类可能要重新部署,使用异常捕获代替错误码,新异常就可以从异常类派生出来,无需重新部署;

[2]抽离try/catch代码块,把错误处理与正常流程区别开来:

// 反例
try {
  deletePage(page);
  registry.deleteReference(page.name);
  configKeys.deleteKey(page.name.makeKey());
}
catch(Exception e) {
  logger.error(e.getMessage());
}

// 正例
public void delete(Page page) {
    try {
      deletePageAndAllReferences(page);
    }
    catch(Exception e) {
      logError(e);
    }
}

private void deletePageAndAllReferences(Page page) throws Exception {
    deletePage(page);
    registry.deleteReference(page.name);
    configKeys.deleteKey(page.name.makeKey());
}

private void logError(Excepton e) {
    logger.error(e.getMessage());
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值