读程序员的README笔记04_防御式编程
1. 编写可维护的代码1.1. 生产环境下的软件必须一直保持可用的状态1.1.1. 用户行为不可预测,网络不可靠,事情总会出错1.2. 编写可维护的代码有助于你应对不可预见的情况,可维护的代码有内置的保护、诊断和控制1.2.1. 切记通过安全和有弹性的编码实践进行防御式编程来保护你的系统,安全的代码可以预防许多故障,而有弹性的代码可以在故障发生时进行恢复1.2.1.1. 切记让你的代码安全而有弹性1.2.1.2. 编写拥有良好防御性的代码是一种对那些运行你的代码的人(包括你自己!)富有同情心的表现1.2.1.3. 防御性的代码较少发生故障,就算它发生故障,也更有可能恢复1.2.1.4. 安全的代码利用编译时的校验来避免运行时的故障,使用不可变的变量、限制范围的访问修饰符和静态类型检查工具来防止bug1.2.2. 一个可维护的系统具有可配置参数和系统工具1.2.3. 你需要在不修改代码的情况下控制系统1.2.4. 将日志、指标和跟踪的调用信息暴露出来可以方便诊断2. 避免空值2.1. 没有值的变量默认为null(或nil、None或其他一些变体)2.2. 通过检查变量是否为空,通过使用空对象模式(null object pattern),或通过可选类型(option type)来避免空指针异常2.2.1. 空对象模式会使用一个对象来代替空值2.3. 切记在方法的开头进行空值检查2.3.1. 可以使用NotNull注解和编程语言中类似的特性2.3.2. 在前面校验变量是否为空意味着后面的代码可以安全地假定它是在处理真实的值,这将使你的代码更干净、更易读3. 保持变量不可变3.1. 不可变的变量一旦被赋值就不能被改变3.1.1. 不可变的变量可以防止意外的修改3.2. 使用不可变的变量可以使并发编程变得更简单,而且当编译器或运行环境知道变量不会改变时就可以运转得更有效率4. 使用类型提示和静态类型检查器4.1. 限制变量可以被赋的值4.2. 静态类型检查器在代码执行之前会使用类型提示来发现潜在bug,所以配合静态类型检查器一起使用,你就可以防止运行时出现故障5. 验证输入5.1. 永远不要相信你的代码接收的输入5.2. 校验输入的值可以避免出现意外5.3. 开发人员、有问题的硬件和人为的错误都会破坏输入的数据5.3.1. 计算机硬件并不总值得信赖,网络和磁盘可能会损坏数据5.3.2. 不要忽视安全问题,外部输入是危险的5.3.2.1. 恶意用户可能试图在输入中注入代码或SQL,或撑爆缓冲区以获得对你的应用程序的控制权限5.4. 通过校验输入的正确性去保护你的代码5.4.1. 用先决条件、校验和(checksum)以及校验数据合法性5.4.1.1. 如果你需要强大的耐久性保证,使用校验和的方式来检查数据没有意外的变化5.4.2. 套用安全领域中的最佳实践5.4.2.1. 强制转义输入的字符来防止SQL注入攻击5.4.2.2. 在使用strcpy(特别是strncpy)等命令操作内存时,明确地设置缓冲区的大小,以防止缓冲区溢出5.4.2.3. 使用广泛采用的安全与密码类库或协议,而不是自己去编写这样的类库或协议5.4.2.4. 熟悉开放式Web应用程序安全项目(open Web application security project,OWASP)的十大安全报告以快速建立你的安全知识体系5.4.3. 使用工具来发现常见的错误5.4.3.1. 使用成熟的类库和框架来防止跨站脚本攻击5.4.4. 尽可能地提早拒绝不良输入5.5. 使用前置条件和后置条件的方式来校验方法中输入的变量5.5.1. 当你使用的数据类型不能完全地捕获有效的变量值时,可以使用校验前置条件的类库和框架6. 善用异常6.1. 有弹性的代码使用异常处理中的最佳实践来优雅地处理故障6.2. 不要使用特殊的返回值来标识错误类型(如null、0、−1等)6.3. 异常要有精确含义6.3.1. 精确的异常使代码更容易使用6.3.2. 尽可能地使用内置的异常,避免创建通用的异常6.3.2.1. 如果一个内置的异常可以描述问题,就不要创建自定义的异常6.3.2.2. 当你创建自己的异常时,不要把它们弄得太通用6.3.2.2.1. 通用的异常很难处理,因为开发人员并不知道他们正面临什么样的具体问题6.3.3. 使用异常处理来应对故障,而不是控制应用程序的运行逻辑6.3.3.1. 不要在应用程序的运行逻辑中使用异常6.3.4. 使用异常来跳出方法常常令人困惑,并且使代码难以调试6.3.4.1. 你的代码是不出人意料的,而不是聪明的6.4. 早抛晚捕6.4.1. 遵循“早抛晚捕”的原则来处理异常6.4.2. “早抛”意味着在尽可能接近错误的地方引发异常,这样开发人员就能迅速地定位相关的代码6.4.3. “晚捕”意味着在调用的堆栈上传播这个异常,直到你到达能够处理异常的程序的层级7. 智能重试7.1. 在故障发生之后,系统处于什么状态并不总显而易见7.1.1. 面对一个错误时,适当反应往往是简单地再试一次就好7.1.2. 不要盲目地重试所有失败的调用,尤其是那些写入数据或可能触发一些业务流程的调用7.2. 最单纯的重试方法是捕捉到一个异常马上就进行重试7.3. 谨慎的做法是使用一种叫作“退避”(backoff)的策略7.3.1. 退避会非线性地增加休眠时间(通常使用指数退避,如(retry number)^2)7.4. 构建幂等系统7.4.1. 处理重试的最好方法是构建幂等系统7.4.2. 一个幂等的操作是可以被进行多次并且仍然产生相同结果的操作8. 及时释放资源8.1. 当故障发生后,要确保清理所有的资源,释放你不再需要的内存、数据结构、网络套接字和文件句柄8.2. 所谓网络套接字泄露,是指在使用后没有关闭它们8.2.1. 网络套接字泄露会使无用的连接一直存在,从而填满连接池
大家还看了
也许喜欢
更多游戏