# 一、整洁代码的定义

  • 整洁的代码只做一件事情
  • 逻辑不清楚,性能不好的代码,会让别人非常想改它,然后改的更乱了。

# 二、命名

  1. 不能提供更多额外信息的词汇不要用。 比如一个 Product 类,还有一个 ProductInfo 和 ProductData,其中 Info 和 data 并不能提供更多的信息。Info和 data 就像是 a\an\the 这种词都是冗余。

  2. 避免误导,就是程序名和变量名要名符其实。比如 OrderList 就应该是一个 list,而不应该是一个对象。函数的名称要和函数所做的动作一致。假如发现无法有很好的函数名称形容这个函数,那说明这个函数做的事情太多了,需要进行拆分。

  3. 名称宁愿长点,也不要缩写成别人无法理解的单词。

  4. 不要前缀! 因为代码读的越多,眼中就慢慢会自动忽略前缀。

  5. 类名和对象名应该是名词或者名词短语。例如:Customer、WikiPage、AddressParser。类名不应该是动词。避免:Manager,Processor 这种类名,因为他是比较笼统的概念。

  6. 方法名应该是动词或者动词短语。如 PostPayment, Delete 。初始化一个类时

    Complex fulcrumPoint = new Complex(20, 30)
        
    //这种方式会更好
        
    Complex fulcrumPoint = Complex.FromRealNumber(20,30)
    
    1
    2
    3
    4
    5

    可以考虑将对应的构造器设为 priate,强制使用各种方式

  7. 每个概念对应一个单词。给每个抽象出来的对象或者操作规定一个名称。比如fetch、retrieve、get他们都是获取的意思时,要给出对应的场景单词。注意区分insert、append并替代add使用。尽可能使用email代替emailAddress,因为后者几乎没有提供比前者更多的信息。

  8. 对于词义比较广泛的,需要进行限制,比如 get、add、manage 等。

    • get 是获取对象属性
    • fetch 从远程获取数据
    • load 从文件或者存储中获取数据
    • query 从数据库里获取数据
    • calculate 计算出来的数值
    • find 从数组中查找数据
    • createparsebuild 从数据生成数据

    常用单词:

    add/remove        increment/decrement       open/close
    begin/end            insert/delete                      show/hide
    create/destory    lock/unlock                        source/target
    first/last              min/max                             start/stop
    get/put                next/previous                     up/down     
    get/set                old/new
        
    新增: add, new, create, make, build, generate
    更新: update, set, transform, 
    获得:get, load, fetch, calculate, find, search, filter, query
    删除:remove, delete, clear, 
    接口:Ajax
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  9. 很少有名称是可以自我说明的,比如 name, 所以需要有上下文环境,上下文环境可以是名称前缀,当然抽象成类更好。

# 三、函数

  1. 函数的第一规则是短小,第二规则还是短小!
  2. 函数只做一件事情。做好这件事情,只做这一件事情
  3. 函数的抽象层级要统一,就是函数内操作的颗粒度要统一。比如一个函数要渲染页面, render(View) 是高层次抽象,然后 printString(String) 这里就是底层的实现,他们应该要进行分层。就像我们设置里面,先进入控制面板,然后找到所属的模块,然后细节的操作。
  4. 函数参数,最理想的参数数量是0,应该避免三个参数以上的函数,有足够特殊的里有才能用三个以上的参数。参数太多可以用责任链设计模式。
  5. 禁止标识参数,就是 Flag 或者 Switch,不准像函数传入布尔值。这标明了函数没有做一件事情,假如为 true 会这么做,假如为 false 会这么做。
  6. 如果函数参数看来需要两个或者三个以上,那说明其中一些参数应该被封装成类了。
  7. 函数要么做什么事,要么回答一些事。但二者不可兼得。把动作查询分开。当然有时候动作的结果就是我们查询的对象,这时候直接返回。但是不要既做动作,又对结果进行额外的查询。
  8. try...catch...中的代码块,应该抽离成函数
  9. 不要重复!重复是复杂度的根源之一。很多原则和实践规则都是为了避免重复

# 四、注释

  1. 注释不能美化糟糕的代码!
  2. 注释只应该出现在理解困难或者容易出错的地方,能不用就不要用。
  3. 不准保留注释掉的代码,统统删干净

# 五、格式

  1. 统一的缩进格式
  2. 代码行应该尽可能短小,最好不要超过120字
  3. 代码格式要团队进行统一,使用编辑器工具进行限制
  4. 类的组织,首先应该是常量, 然后是属性,然后是公共函数,对应的私有函数要放在调用者附近。公共函数应该在变量之后

# 六、对象和数据结构

  1. 类并不是用取值和赋值将私有变量对外使用。二是要暴露抽象接口,让用户无需了解数据结构就可以使用。
  2. 对象把数据隐藏于抽象之后,暴露操作数据的函数。 数据结构暴露起数据结构,没有提供有意义的函数。
  3. 过程式代码(使用数据结构的代码),难以修改数据结构,因为会影响函数,但是容易修改函数。
  4. 对象式代码,难以添加新函数,因为会影响很多类。
  5. 模块不应该了解对象内部的数据结构,对象不应该通过存取器暴露内部结构。
  6. 数据对象,只有公共变量,没有函数的类。被称为数据传送对象。作用就是将原始数据转化为类的操作,比如 ActiveRecord

# 七、错误处理

  1. 使用异常而不是返回码。 意思是主函数调用子函数时,子函数不应该返回 true 或者 false 等返回码,这样主函数还需要进行判断,而应该直接抛异常。由统一的错误处理进行处理。
  2. 不要返回 null 值!不要传递 null 值

# 八、范围

  1. 一个类要有其对应的范围。不能啥都干。比如 StoreHandler 只应该做返回值是Store 的操作,获取 Store 的 Price 应该放到 PriceHandler
  2. 使用接口类限制边界

# 九、类

  1. 类的单一权责。系统应该由很多短小的类而不是少量巨大的类构成。
  2. Controller 过于臃肿,而且 controller 里面的方法不便于其他 controller 进行调用。所以将 controller 逻辑提取出来,根据函数所获得的结果进行汇总,然后控制逻辑层,防止逻辑层大爆炸。为了防止逻辑层大爆炸,就要求逻辑层有比较想尽的文档,在编写之前可以先查阅文档是否已经存在有类似的函数。对与逻辑层的起名不要包含业务层信息。仅描述对资源的获取,包含三个部分,请求的资源,请求的条件,请求返回的格式。