代码整洁之道的一些准则摘要

Date:
Categories: code
Author: sysublackbear
Tags: ,

好久没有更博了,之前一直在看python的其他库和一些进阶用法。 最近在看《Clean Code》,才疏学浅,整理一下一些常用的写代码应该注意的点吧。

1.命名

  • 名副其实;
  • 避免误导;
  • 做有意义的区分(a1,a2,i,j 这些变量名区分没有任何意义);
  • 使用读得出来的名称;
  • 使用可搜索的名称(以常量或宏代替魔鬼数字,MAX_CLASSES_PER_STUDENT = 7;)
  • 避免使用编码;
  • 成员前缀(人们会很快学会无视前缀或后缀,只看到名称中有意义的部分。代码读写得越多,眼中就越没有前缀。最终,前缀变作了不入法眼的废料,变作了旧代码的标志物)(不敢苟同
  • 接口与实现;
  • 避免思维映射;
  • 类名(类名不应该是动词);
  • 方法名(方法名应当是动词或动词短语);

重载构造器时,使用描述了参数的静态工厂方法名。例如:

Complex fulcrumPoint = Complex.FromRealNumber(23.0);

通常好于:

Complex fulcrumPoint = new Complex(23.0)

可以考虑将相应的构造器设置为private,强制使用这种方法。

  • 每个概念只对应的一个词(例如controller,driver,manager同义的词不要在一结构体出现多次,容易造成混淆);
  • 别用双关语;
  • 使用解决方案领域名称;
  • 使用源自所涉问题领域的名称;
  • 添加有意义的语境;
  • 不要添加没用的语境。

2.函数

2.1.函数存在的目的

函数追求的目标是要短小,同时函数的设计的原则: 函数应该做一件事。做好这件事。只做这一件事。 注意函数应该分层,要判断函数是否不止做了一件事,还有一个方法,就是看是否能再拆出一个函数,该函数不仅只是单纯地重新诠释其实现。

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

自顶向下读代码:向下规则

按照这个规则分层:

To 做事情1, we should 做事情2 To 做事情2, we should 做事情3 ​ ...

2.3.Switch语句

对待switch语句的正确解决方法是:将switch语句埋到抽象工厂底下,不让任何人看到。该工厂使用switch语句为Employee的派生物创建适当的实体,而不同的函数,如calculatePay,isPayday和deliverPay等,则藉由Employee接口多态地接受派遣。

例如:

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;
}
---------------------
public class EmployeeFactoryImpl implements EmployeeFactory {
  public Employee makeEmployee(EmployeeRecord r) throws InvalidEmployeeType {
    switch (r.type){
      case COMMISSIONED:
        return new CommissionedEmployee(r);
      case HOURLY:
        return new HourlyEmployee(r);
      case SALARIED:
        return new SalariedEmployee(r);
      default:
        throw new InvalidEmployeeType(r.type);
    }
}
}

2.4.函数参数

函数最理想的参数数量是零(零参数函数),其次是一(单参数函数),再次是二(双参数函数),应尽量避免三(三参数函数)。

2.5.避免函数产生副作用

副作用是一种谎言。函数承诺只做一件事,但还是会做其他被藏起来的事情。有时,它会对自己类中的变量做出未能预期的改动。有时,它会把变量搞成向函数传递的参数或是系统的全局变量。无论哪种情况,都具有破坏性的,会导致奇怪的时序性耦合及顺序依赖。

2.6.分隔指令与询问

例如在变量的set方法返回类型为void,不应该是bool,不应该包含IsAttrSet,区分好两个方法

  • SetAttr
  • IsAttrSet

2.7.错误代码抽离

注意两个原则:

  • 运用try-catch结构:把错误处理代码从主路径代码中分离出来。
  • 最好把try和catch代码块的主体部分抽离出来,另外形成函数。
try {
  deletePageAndAllReferences(page);
}
catch (Exception e) {
  logError(e);
}

2.8.错误处理就是一件事

处理错误的函数不该做其他事。

未完待续......