读程序员的制胜技笔记12_与Bug共存(下)

这篇具有很好参考价值的文章主要介绍了读程序员的制胜技笔记12_与Bug共存(下)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

读程序员的制胜技笔记12_与Bug共存(下)文章来源地址https://www.toymoban.com/news/detail-746181.html

1. 亚伯拉罕·马斯洛(Abraham Maslow)在1966年所说:“如果你唯一的工具是一把锤子,你往往会把每个问题都看成钉子。”

2. 错误恐惧

2.1. 不是每一个bug都是由你的代码中的错误引起的,也不是每一个错误都意味着你的代码中存在一个bug

2.1.1. 开发人员本能地把所有的错误当作bug,并不约而同地、坚持不懈地把它们消灭

2.1.2. 对这些错误用平常心看待,这些所谓的错误是很正常的事情

2.2. 有关异常的真相

2.2.1. 异常可能是编程史上被误解最多的结构

2.2.1.1. 故障代码(failing code)放在一个try语句块里,然后加上一个空的catch语句块,就大功告成了

2.2.1.2. 开发者为整个应用程序添加了一个通用的异常处理程序,但实际上这个程序的工作原理就是忽略所有的异常,也就防止所有的崩溃

2.2.1.3. 如果像那样添加一个空的处理程序就是“万金油”的话,我们早就解决了所有bug

2.2.2. 异常是解决未定义状态问题的一种新方法

2.2.2.1. 在错误处理只用返回值的时代,有可能漏掉了对错误的处理,只假设它没问题,然后继续运行

2.2.2.2. 未知状态意味着你无法预测接下来会发生什么

2.2.3. 错误代码与异常情况不同

2.2.3.1. 在程序运行期间,如果异常情况没有得到处理,是可以检测出来的,而错误代码则不然

2.2.3.2. 对于那些未处理的异常,采取的解决办法也比较简单、粗暴:终止程序

2.2.3.3. 操作系统也是这样做的:如果应用程序出现无法处理的异常,操作系统就会终止该应用程序

2.2.3.3.1. UNIX操作系统的“内核恐慌”
2.2.3.3.2. Windows操作系统臭名昭著的“死亡蓝屏”

2.2.3.4. 在基于微内核的操作系统中问题不大,因为内核级组件的数量很少,甚至设备驱动也在用户空间中运行,对性能的影响也微乎其微,我们一般很难感受到

2.2.4. 对于异常,其实我们忽略的一件事就是它们是意外情况

2.2.4.1. 它们不是用于通用流控制,你可以通过结果值结合流控制来实现它

2.2.4.2. 异常是指在函数作用之外发生的事情,它不能再完成交给它实现的功能的情况

2.2.4.3. 像(a,b) => a/b这样的函数可以保证正常除法运算的执行,但当b的值等于0的时候,这个函数就没法执行,因为b等于0这个情况既是意外也没有被定义

2.2.5. 在每一步,你都可能遇到异常,如果没有被处理,或者处理不当,那就会有程序崩溃的可能性

2.3. 不要捕捉异常

2.3.1. 异常应该导致崩溃,因为这是在不引起进一步问题的情况下找出问题所在的最简单方法

2.3.2. 要害怕那些被空的catch语句块所掩盖的问题,它们潜伏在代码中,伪装成看起来好像正确的状态,在长时间的运行过程中积攒了不少问题,到最后导致明显的速度下降或一个突如其来的崩溃,比如OutOfMemoryException

2.3.3. 不必要的catch语句块可以防止一些崩溃,但它们可能会让你花费数小时来阅读日志

2.3.4. 应该避免使用未定义的catch语句块,因为它们太宽泛了,导致很多不相关的异常被捕获

2.3.5. 异常处理的第一条规则是,不要捕捉异常

2.3.6. 异常处理的第二条规则是IndexOutOf RangeExceptionat

2.3.7. 不要因为异常会导致崩溃就去捕捉异常

2.3.7.1. 如果它是由一个不正确行为引起的,那就修复引起它的错误

2.3.7.2. 如果它是由一种已知的可能性引起的,那么就在代码中为这种特定的情况加上明确的处理语句

2.3.7.3. 盲目地处理异常可能会掩盖你的代码中更深、更严重的问题

2.4. 容异性

2.4.1. 你的代码应该在不处理异常的情况下也能工作,即使是面临崩溃的时候也一样

2.4.2. 你应该设计一个流程,即使在不断得到异常时也能正常工作,而且不应该进入不受控制的状态

2.4.3. 设计软件实现容异性从幂等性(idempotency)下手

2.4.3.1. 如果一个函数或一个URL无论被调用多少次都返回相同的结果,那么它就是具有幂等性的

2.4.3.2. 对于网络请求来说,幂等性通常被认为是一种简化的方式

2.4.4. 当我们设计函数时,无论它被调用多少次,返回结果都一致,当它被意外中断时,一致性让我们因此获得好处

2.4.5. 数据库的事务机制可以帮你避免程序进入异常状态

2.4.5.1. 事务可以在程序因某个异常而中断端的时候进行回滚操作

2.4.5.2. 在很多场景当中这个操作并不是必需的

2.5. 没有事务的容异性

2.5.1. 具有幂等性可能并不足以保证其具有容异性,但至少为其打下了一个很好的基础

2.5.2. 事务可以防止这种情况,因为它们会回滚所有的变化,而不会留下任何脏数据

2.5.3. 并不是每个存储都支持事务机制

2.5.3.1. 比如说文件系统

2.6. 异常与错误

2.6.1. 异常标志着错误(勉强可以这么说),但不是所有的错误都有资格成为异常

2.6.2. 常规的错误值在大多数情况下都能很好地返回响应

2.6.2.1. 没有返回值也没任何问题,只要你觉得返回值没任何用处

2.6.3. 你可以根据你预想的调用者对信息的需求程度来设置不同类型的错误结果

2.6.4. 使用enum的好处是,当你使用swtich语句的时候,编译器会告诉你有未处理的情况

2.6.5. 对于未处理的情况,你会得到一个编译器警告,因为它们没写完

3. 不要调试

3.1. 调试(debugging)是一个古老的术语,它的出现甚至要早于编程

3.1.1. 在20世纪40年代,格雷丝·霍珀(Grace Hopper)在一台出问题的Mark Ⅱ计算机的继电器中发现了一只真正的虫子(bug)

3.1.2. 最初在航空业中用于描述识别飞机故障的过程

3.1.3. 现在它被硅谷更先进的做法所取代

3.2. 用调试器运行程序,设置断点,一步一步地追踪代码,并检查程序的状态

3.3. 连续检查应用程序的状态可能是最古老的调试程序的方法

3.4. 不是所有的程序都有可见的控制台输出、网络应用程序或服务

3.5. printf()调试法

3.5.1. 在程序中插入控制台输出行来查找问题是一种古老的做法

3.5.2. printf()调试的名字来自C语言中的printf()函数

3.5.3. printf()调试是可以显示运行中的程序的状态,所以程序员可以了解问题发生的地方

3.5.4. printf()或Console.WriteLine()会将状态信息输出到控制台,你可以通过历史记录来查看

3.6. .NET为其提供了替代方案

3.6.1. Debug.WriteLine()方法

3.6.1.1. 用于将输出写入调试器输出控制台,在Visual Studio的调试器输出窗口中显示,而不是在应用程序自己的控制台输出

3.6.1.2. 最大的好处是对它的调用会从成品(release版本)的二进制文件中完全剥离,所以它不会影响发布代码的性能

3.6.2. Trace.WriteLine()方法

3.6.2.1. Trace.WriteLine()在跟踪意义上是一个更好的工具,因为.NET跟踪的除了通常的输出外,还有运行时配置的监听器

3.6.2.2. 可以把跟踪的输出写进文本文件、事件日志、XML文件,以及任何你能想到的安装了正确组件的东

3.7. 初识转储

3.7.1. 逐步调试的一个替代方案是检查崩溃转储

3.7.2. 崩溃转储文件不一定是在崩溃后创建的

3.7.3. 崩溃转储文件是包含程序的内存空间快照内容的文件

3.7.4. 微软在MS-DOS的2.0版本而不是1.0版本中加入了目录这个文件系统

3.7.5. UNIX系统中也被称为核心转储(core dump)

3.7.5.1. 一个非侵入性(non-invasive)的操作,只会暂停进程直到操作完成,但之后会保持进程运行

3.7.6. 从.NET上扩展名为.pdb的调试文件中获取这些信息,并将内存地址与符号和行号相匹配

3.8. 小黄鸭调试法是一种通过把问题告诉坐在你桌子上的小黄鸭来解决问题的方法

3.8.1. 可以帮助你意识到你还没有尝试过所有可能的解决方案

4. 总结

4.1. 对bug进行优先级排序,以避免将资源浪费在修复不重要的bug上

4.2. 只有当你的行动是有意识、有计划的时候,才能捕捉到异常情况

4.2.1. 不然,就不要去进行bug捕捉

4.3. 写有容异性的代码,它首先得有抵御崩溃的能力,而不是作为“马后炮”

4.4. 对于那些常见错误或者因为对代码期待过高而导致的错误,使用结果代码(result code)或者enum,而不是使用异常

4.5. 使用框架提供的跟踪功能,比笨重的逐步调试能更快发现问题

4.6. 如果其他方法不可用,则使用崩溃转储分析来识别生产环境中运行代码的问题

到了这里,关于读程序员的制胜技笔记12_与Bug共存(下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 读程序员的制胜技笔记06_测试(下)

    1.3.1.1. 假设18岁是你游戏用户的法定年龄 1.3.2.1. C# 1.3.2.1.1. 不需要测试公元1年1月1日到9999年12月31日之间所有可能的DateTime值(有360多万个) 1.3.2.1.2. 只需要测试7个不同的输入 1.3.2.1.3. 通过条件语句将输入范围进行分割的操作称为“边界条件”(boundary conditional) 1.3.2.1.3.1. 定

    2024年02月05日
    浏览(36)
  • 读程序员的制胜技笔记10_可口的扩展

    2.8.3.1. 纯函数有一个好处,它们是100%线程安全的 2.9.1.1. 这套数据结构并不都是无锁的 2.9.1.2. 虽然它们依然使用锁,但它们是被优化过的,锁的持续时间会很短,保证了其速度,而且它们可能比真正的无锁替代方案更简单 2.9.2.1. 其中原始数据从未改变,但每个修改操作都

    2024年02月05日
    浏览(49)
  • 读程序员的制胜技笔记13_安全审查(上)

    5.6.1.1. 任何你不想丢失或泄露的东西都是资产,包括你的源代码、设计文档、数据库、私钥、API令牌、服务器配置,还有Netflix观看清单 5.6.2.1. 每台服务器都会被一些人访问,而每台服务器都会访问其他一些服务器 6.1.1.1. 设计时首先要考虑到安全问题,因为在既有基础上去

    2024年02月05日
    浏览(47)
  • 读程序员的制胜技笔记14_安全审查(下)

    1.2.2.1. 看不出来是什么?那我拒绝为你服务 1.4.1.1. 工作量证明相当消耗客户端的运算资源,对那些性能较低的设备不友好,并且它还会影响设备电池的使用寿命 1.4.1.2. 有可能会严重降低用户体验,其后果甚至比验证码的还要恶劣 3.5.2.1. 存储需求更少,性能更强,数据管理

    2024年02月05日
    浏览(32)
  • 读程序员的制胜技笔记08_死磕优化(上)

    4.3.1.1. 只能给你一堆用于比较的数字 4.3.1.2. 不能告诉你代码的运行速度是快还是慢 4.3.1.3. 可以告诉你它们比其他一些代码运行得慢还是快 4.3.5.1. 可以消除因测量误差或者调用开销产生的波动 4.3.5.2. 适用于微观基准测试 4.3.5.2.1. 适用于微观基准测试 4.3.5.3. 基准测试并没

    2024年02月05日
    浏览(61)
  • 读程序员的制胜技笔记09_死磕优化(下)

    7.5.3.1. 在256KB之后,提升突然变得杯水车薪

    2024年02月05日
    浏览(59)
  • 读程序员的制胜技笔记02_算法与数据结构

    3.1.1.1. 根据你的需要,可以有更智能的算法 3.1.3.1. 算法本身并不意味着它很聪明 3.2.1.1. public static bool Contains(int[] array, int lookFor) { for (int n = 0; n < array.Length; n++) {        if (array[n] == lookFor) {            return true;        }    }    return false; } 3.3.1.1. public sta

    2024年02月06日
    浏览(47)
  • 读程序员的制胜技笔记03_有用的反模式(上)

    4.5.4.1. 你在物理数据库结构上增加了一个依赖项 4.5.4.2. 如果你需要改变信息表的布局或所使用的数据库技术,你就必须检查所有的代码,确保所有的东西都能与新的表布局或新的数据库技术一起工作 4.5.6.1. 这是保持组件或整个层尽可能简单的关键 4.8.3.1. 每个成员只对自己

    2024年02月06日
    浏览(34)
  • 读程序员的制胜技笔记04_有用的反模式(下)

    1.3.1.1. 自己做自己的甲方 3.2.2.1. 紧耦合(tight coupling) 3.2.2.2. 依赖性是万恶之源 3.3.7.1. 因为你可能需要用接口而不是具体的引用来定义依赖关系,但这也会使代码摆脱依赖关系 5.2.3.1. 没有其他错误发生时执行的代码部分 5.3.3.1. 退出点(exit point)是指函数中导致其返回给调用

    2024年02月06日
    浏览(69)
  • 【学习笔记】黑马程序员Java课程学习笔记(更新至第12章---集合)

    Java语言是美国Sun公司(Stanford University Network)在1995年推出的计算机语言, 2009年Oracle甲骨文公司收购Sun公司。Java之父:詹姆斯·高斯林(James Gosling)。 Java可以在任意操作系统上运行,Windows、Mac、Linux。我们只需要在运行Java应用程序的操作系统上,安装一个与操作系统对应

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包