软件系统设计-10-防御式编程

1. 防御式编程 Defensive Programming

1.1. 可用、正确和优秀的代码

  1. 编写大多数情况下都能用(可用)的代码很容易:但是提供意外输入会崩溃。
  2. 正确的代码绝不会崩溃
    1. 但所有可能输入集合很大,难以测试
    2. 并非所有正确的代码都是优秀的代码:可能逻辑难以理解,并且几乎无法维护。
  3. 优秀的代码是健壮的、高效的、当然也是正确的:即便面对不常见输入,产品级代码也不会崩溃和产生错误的结果。

1.2. 编程中的常见设想

  1. 这个函数”绝不会”被那样调用:传递给我的参数总是有效的
  2. 这段代码肯定会”一直”正常运行:它绝对不会产生错误
  3. 如果我把这个变量标记为”仅限内部使用”,就没有人会尝试访问这个变量
  4. 进行防御式编程时,不应该做任何设想

1.3. 你的软件开发过程是怎样的/h2>

  1. 1 :工作流:可读性差
  2. 2 :扁平化,缺点是需要明显的控制变量
  3. 3 :短路,需要做之后的处理
  4. 4 :合适的
  5. 5 :异常,异常的处理不明显

3.4. 错误信息编写

  1. 当需要由用户清理错误时
    1. 以用户期望的方式呈现信息:“磁盘空间:0KB”/li>
    2. 确保用户能够理解错误信息
    3. 不要呈现毫无意义的错误代码:“Error code 707E”/li>
    4. 将后果严重的错误与仅仅是警告区分开来:可使用”Error:”或图标
    5. 提示用户每种选择可能的后果后再提出问题:“是否继续”/li>

3.5. 异常

  1. 是把代码中的错误或异常事件传递给调用方代码的一种特殊手段
    1. 当遇到意料之外的情况,但不知道该如何处理时,可以抛出一个异常
    2. 同继承一样,谨慎使用可降低复杂度
  2. 基本结构
    1. 子程序使用throw抛出一个异常对象
    2. 被调用链上层其他子程序的try-catch语句捕获

软件系统设计-10-防御式编程
  1. 为什么C++没有finally呢为C++提供了资源获得和初始化RAI,确保无论是否发生异常都可以完成清理工作。因为C++可以自己进行析构。

3.5.1. Trace a Program Execution

3.5.2. 使用建议

  1. 用异常通知程序的其他部分,发生了不可忽略的错误
    1. 能提供一种无法被忽略的错误通知机制
    2. 消除了错误向外扩散的可能性
  2. 只有真正例外的情况下才抛出异常
    1. 仅在其他编码实践方法无法解决的情况下才使用异常(同断言类似,处理罕见且不该发生的情况)
    2. 会增加复杂度:调用子程序的代码需要了解被调用代码中可能会抛出的异常,弱化了封装性
  3. 不能用异常来推卸责任:可以在局部处理就在局部处理掉
  4. 避免在构造函数和析构函数中抛出异常,除非你在同一地方把它们捕获:C++中,构造函数中的异常会造成资源泄露
  5. 在恰当的抽象层次抛出异常:确保异常的抽象层次与子程序接口的抽象层次是一致的

3.5.3. 举例

  1. 抛出的异常也是程序接口的一部分,和其他具体的数据类型一样
  1. 子程序的调用方代码不是与Employee类的代码耦合,而是与比Employee类层次更低的抛出EOFException异常的代码耦合起来了

3.5.4. 改进

  1. GetTaxId() 代码应抛回一个与其所在类的接口相一致的异常
  1. 在设计上需要增加EmployeeDataNotAvailable异常类型,
    并将更底层的EOFException异常映射为该异常类型3

3.5.5. 使用建议(补)

  1. 在异常消息中加入关于导致异常发生的全部信息:确保消息中含有为理解异常抛出原因所需的信息,如数组下标错误
  2. 避免使用空的catch语句:意味着try或catch里的代码不对

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年3月6日
下一篇 2022年3月6日

相关推荐