《编程匠艺》之代码的表面
第一部分: 处理代码的细节(代码的表面)
处理代码的细节,主要分为如下的几个方向,check:
- 善于防守, 考虑代码的健壮性.
- 好的样式.精心布局.
- 为文件和函数以及各部分起个好名字.
- 良好的注释.
- 错误处理,处理好可能会出现的错误.保证不崩溃.
- 逻辑清晰,可理解.
1. 防御性
防御性的诱因:
- 恶意用户
- 客户端错误的使用
- 运行环境不完整
- 外部运行库问题
如果可以使用函数局部变量,就不要使用全局变量.如果能使用循环体内的变量,就不使用函数级变量.
防御要义:
- 使用合适的风格和规范.
- 逻辑清晰, 而不是简洁.
- 开启合适的警告级别.
- 使用静态lint检查工具.
- 检查返回值,适当的处理之.
- 合理使用日志以及级别.
- 谨慎的进行类型转换.
- 适当的约束,检查数组边界, 指针
Q & A:
- 为每个修复的bug最好都做一个单元测试.
2. 精心布局
- 调整好风格, 调整好tab宽度等.
3. 起个好名字
需要命名的对象有:
- 变量
- 函数
- 类型
- 包名字
- 宏
- 文件名
- 为名字起好名字的关键是理解所命名的对象.
- 进行命名时,重点放在清晰而非简洁上.但是如果是作为循环计数器,那么可以使用短的变量.
- 命名函数时,因为函数是方法, 那么最好是一个动词开头, 表名某种逻辑功能.
- 宏命名时,全大写, 并以项目名为前缀.
- 文件名尽可能描述文件功能;可以拆分文件中的多个逻辑.
- 命名要保持一致.
- 起名字时,要确定其范围, 容易有明确的描述.
4. 编写自说明的代码技巧
-
不要编写需要外部文档支持的代码, 因为对于一个大型的项目, 维护文档本身就是一个很大的挑战, 尤其是代码在不断的迭代中.
-
那么使用注释是一个好主意么?No, 散落在各处的注释, 并不是好的自说明.
-
好的代码如同一本组织良好的书.
- 前言对应文件的代码注释头, 说明文件的内容,作用,属于的项目等.
- 目录对应文件中的函数,类,变量的列表(现代软件可以使用ide)
- 部分对应一个代码部分.不推荐单文件过大, 可以把几个源文件打包成一个"部分",代表一个大的逻辑部分.
- 章对应某一个源文件, 他是功能独立完整的逻辑函数集合.
- 段落对应每个函数的代码组织,如变量在最前面等.
- 语句对应每条语句.
-
使用好的样式编写简单的代码
- 让正常的流程贯穿代码,处理错误或者正确的分支总是放在前面.
- 避免过多的嵌套.
- 谨慎的优化代码,如果不易理解, 要清晰的注释.
-
选择有意义的名称
- 所有的变量, 函数, 文件名, 类型, 都应该有准确的含义.
-
分解为原子函数
- 一个函数,一种操作.观察函数名字就能知道函数功能.
- 保持简短.
-
使用合适的类型
- 如变量不包含负值,那么就直接使用uint
- 如果变量不可修改, 那么就用const修饰
-
突出重要的代码
- 隐藏不重要的信息和代码
- 限制嵌套的条件语句的数量.避免重要的处理条件被嵌套隐藏.
-
分组相关信息
- 通过使用语言的机制,将相关信息分组, 在go中, 就是包.在c中, 就是文件.
-
恰当的处理错误
- 不要返回无意义的错误, 每一层处理自己的错误.如在访问磁盘的代码中出现错误,那么这一层就处理磁盘错误,然后向上抛出错误, 上层可能处理的是打开文件错误等.
-
对于一个自描述的代码,还需要什么什么文档?
- 需要一个描述整个系统和作用的文档
- 系统的结构概要文档和设计文档
- 测试规范
5. 编写合适的注释
- 只需要编写够用的注释,过犹不及.
- 对于复杂的地方, 要解释为什么这么做更重要, 至于做了什么, 如果是自说明的代码, 已经交代的很清楚了.
- 不要文档化差劲的代码, 重写它.可以使用单元测试来保证重写后不会破坏功能.
- 注释应该活在现在, 不要描述已经改变的事情, 也不要讲述某个事物过去是做什么的.
- 当你修改代码时,维护周边的所有注释.
6. 处理出现的错误
-
错误产生的原因总结一下归为三种:
- 用户错误,用户错误的输入或者操作等
- 程序员错误
- 意外情况
-
为了控制代码的错误,我们需要做到:
- 当出现错误时提出错误
- 检测所有可能的错误报告
- 恰当的处理错误
- 传播我们不能处理的错误
-
错误报告机制
- 不报告,比如出现错误, 就中止,但是不是好主意.
- 使用返回值
- 使用错误状态变量,如c语言的errno, 不要用这种方式
- 异常
- 使用信号
-
处理错误
- 何时处理错误
- 尽可能早的处理(尽可能晚的处理) ,没有好坏, 折中
-
错误后的清理的方法