用结构化思维解一切BUG(2):实践原则
背景
本文是系列文章《用结构化思维解一切BUG》的第二篇。本系列文章主要介绍一种「无需掌握技术细节,只需结构化思维和常识即可解一切BUG的方法」。
在前序文章《用结构化思维解一切BUG(1):核心思路》中,我介绍了用结构化思维解BUG的核心思路。即,基于结构化的「假设树」,通过重复多次执行「做实验→造现象→缩范围」动作序列,逐级下钻,缩小问题范围,直到找到问题根因。
但本方法是一个理论和实践相结合的方法,仅靠核心思路,无法完整表达。您真正使用时,还需一系列实践原则来指导方向,才能高效执行。
我把这些实践原则总结成「程序断案三字经」,5 条 30 个字:
- 先诊断,后开药。
- 信机器,慎信人。
- 做试验,缩范围。
- 找不同,看变化。
- 先脆弱,后稳定。
下文详述。
1. 先诊断,后开药
切勿在没有充分的证据时,投入大量人力去修改 BUG。如果现有的现象不足以充分支撑结论,则应该做「小成本」的试验去制造更多现象,以支撑结论。
我看过很多程序员,只了解了基本的现象,就开始靠直觉和经验来推断:「这里最有可能是这里的问题,咱们引入另一个新的工具库可以解决这个问题,我们改改试试」。当大家大动干戈地修改完后,发现问题并没有解决。然后马上改变主意:「刚刚的推断不对,我认为可以再改下这里试试」。几轮下来,极大的影响团队士气不说,更加影响业务的正常运转。
所以,这种在进行严谨的诊断之前就盲目开药的行为,是应该尽力避免的。
2. 信机器,慎信人
这里有两层意思:
一、机器不说谎。
机器没有「真」随机,就算随机数也是伪随机,更不用说你观测到的 BUG 现象了。你观测到的随机BUG,一定不是随机的,一定有确定稳定的根因,只是你暂时没有发现。
另外,机器不会错报任何一个现象。如果您找到的根因,解释了 10 个现象中的 9 个现象,只差 1 个解释不了,那么请相信,您还没有找到根因。
二、人会说谎。
你要相信自己「观察」到的现象,而不是别人「描述」的现象。这不是说您的同事或客户会故意骗人,而是人类大脑有自身缺陷。面对不重要的事情时,人脑经常容易遗忘;当面对信息缺失时,人脑又会自己进行无中生有的脑补。比如,有一次,我问一个运维工程师,这次发布跟上次的发布有什么区别时,他说完全没有。但最终证明,在本次发布时,他新建了一个新的文件夹来存放应用的运行包,而这个文件夹是以 root 的角色创建的。他完全忘记了这件事,而这件事就是应用无法启动的根因。
所以,我们对别人描述的现象,要自己判断其真实性,必要时做试验验证。举个例子,如果有人说,他昨天早上 9 点多登录应用失败,并且报错“Invalid Password”。你应该相信的是,他真的登录失败了;你应该保持怀疑的是,登录的时间和报错的信息,这些信息最好去后台日志去验证一下。
3. 做试验,缩范围
在「假设树」中下钻的过程中,如果当前已知现象没有提供充分的证据,来帮我们进一步缩小范围,则我们需要主动做试验,来创造更多现象,以支撑我们缩小范围。
并且,试验要有针对性,针对目标的就是「假设树」中当前阶段的「可能原因列表」。你设计的「试验」,是需要能排除一个或多个可能的原因。
4. 找不同,看变化
这条原则是对上一条原则「做实验,缩范围」的补充说明。
即,在做实验时,一次验证一个原因,控制单一变量,尽量排除其他干扰。然后,寻找单一变化因子下的现象变化。
举个真实的例子,曾经有一个登录问题,我的直觉判断是浏览器版本问题。我设计的试验是:
- 让现在没有 BUG 的用户升级 Chrome 浏览器到有 BUG 的用户一样的版本,看是否出现 BUG。
- 并且,我让两个用户都打开隐私窗口,以排除 Cookie 可能造成的干扰。
- 同时,我让两个用户都更换浏览器到 Edge、Firefox 和 Safari,做了同样的试验。
我得到的现象是:Edge 和 Chrome 升级后都会报错,其它两个浏览器都不报错。
得到的结论是:此 BUG 必然跟 Chrome 最新内核的更新有关,因为 Chrome 和 Edge 都是同一个内核。
5. 先脆弱,后稳定
现代应用有非常多模块,不同的模块有不同的“置信度”或“可靠度”。要从更脆弱的、更有可能出错的地方入手。就像警察断案,先找有犯罪前科的,工作不稳定的,是一个道理。有些人对自己的代码过于自信,经常从 MySQL、Nginx 这样的模块入手去查找问题。不是说这两个组件绝对不会出问题,而是说 100 次有 99 次都会失败,严重影响效率。
一般置信度从高到低的排列如下:
- 操作系统。
- 行业通用组件。这类系统经过大量验证,比如 MySQL、Nginx、Memcached、RabitMQ 等。
- 组织内通用组件。比如被企业内多个项目使用过的 SSO 模块。
- 自己写的最上层的业务代码。
除了代码提供者这个维度以外,还有一个更新时间维度。越是有新的更新的代码,越没有经过时间验证的代码,越有可能有问题。
总结
至此,《用结构化思维解一切BUG》的方法的理论部分已经讲完。
为了更好的帮助大家掌握此方法,我准备了多个实际案例,将在后续系列文章中细致讲解,请关注我的公众号接收更新。
关于作者
您好,朋友。我现就职于西门子工业软件,担任高级咨询顾问。成功领导 10 多个世界 500 强企业的数字化转型项目,跨越政府、零售、金融、汽车制造、生物医药等多个行业,创造巨大商业价值。
如有任何与「数字化转型」有关的问题,欢迎用以下方式与我交流:
添加我的个人微信「zjh1943」。添加时请注明姓名、行业、交流的问题。
关注我的微信公众号「知明所以」。
关注我的知乎专栏:https://www.zhihu.com/people/zhu-jin-heng 。
用结构化思维解一切BUG(2):实践原则的更多相关文章
- 工作中的Buff加成-结构化思考力:第一章:认识结构化思维及其作用
一:引言 为了更好的说明结构思考力,我们先来做几个小测试. PS:如果你能做到,请留言,因为我要和你交好友,因为你是人才啊,可以挖一挖,挖到我的公司中. 第一个测试:请在三秒内记住下列数字.数字顺序不 ...
- 有效的结构化思维训练,MECE分析法
MECE原则,表达精准分类与全面性的有效利器 结构化思维的本质就是逻辑,其目的在于对问题的思考更完整.更有条理,它帮助我们一个一个找到线头,理清思路,探求事物之间的相互联系.MECE分析法是一种结构化 ...
- 你真的了解字典(Dictionary)吗? C# Memory Cache 踩坑记录 .net 泛型 结构化CSS设计思维 WinForm POST上传与后台接收 高效实用的.NET开源项目 .net 笔试面试总结(3) .net 笔试面试总结(2) 依赖注入 C# RSA 加密 C#与Java AES 加密解密
你真的了解字典(Dictionary)吗? 从一道亲身经历的面试题说起 半年前,我参加我现在所在公司的面试,面试官给了一道题,说有一个Y形的链表,知道起始节点,找出交叉节点.为了便于描述,我把上面 ...
- 结构化CSS设计思维
LESS.SASS等预处理器给CSS开发带来了语法的灵活和便利,其本身却没有给我们带来结构化设计思维.很少有人讨论CSS的架构设计,而很多框架本身,如Bootstrap确实有架构设计思维作为根基. 要 ...
- 详解Google-ProtoBuf中结构化数据的编码
本文的主要内容是google protobuf中序列化数据时用到的编码规则,但是,介绍具体的编码规则之前,我觉得有必要先简单介绍一下google protobuf.因此,本文首先会介绍一些google ...
- NumPy之:结构化数组详解
目录 简介 结构化数组中的字段field 结构化数据类型 创建结构化数据类型 从元组创建 从逗号分割的dtype创建 从字典创建 操作结构化数据类型 Offsets 和Alignment Field ...
- Bigtable:一个分布式的结构化数据存储系统
Bigtable:一个分布式的结构化数据存储系统 摘要 Bigtable是一个管理结构化数据的分布式存储系统,它被设计用来处理海量数据:分布在数千台通用服务器上的PB级的数据.Google的很多项目将 ...
- 视频结构化 AI 推理流程
「视频结构化」是一种 AI 落地的工程化实现,目的是把 AI 模型推理流程能够一般化.它输入视频,输出结构化数据,将结果给到业务系统去形成某些行业的解决方案. 换个角度,如果你想用摄像头来实现某些智能 ...
- Shell 语法之结构化命令(流程控制)
许多程序在脚本命令之间需要某种逻辑流控制,允许脚本根据变量值的条件或者其他命令的结果路过一些命令或者循环执行这些命令.这些命令通常被称为结构化命令.和其他高级程序设计语言一样,shell提供了用来控制 ...
- 第25章 SEH结构化异常处理_未处理异常及向量化异常
25.1 UnhandledExceptionFilter函数详解 25.1.1 BaseProcessStart伪代码(Kernel32内部) void BaseProcessStart(PVOID ...
随机推荐
- Hexo博客yilia主题首页添加helper-live2d模型插件
插件效果 插件的github地址 插件作者提供了较为详细的安装步骤,我结合自己操作和图示,提供大家. 效果展示:红框内为2d模型,可以随鼠标移动而变化 安装模块: hexo博客根目录选择cmd命令窗口 ...
- C语言变量常量
目录 前言 一.数据类型 1.整形 2.浮点型 3.字符型 二.变量的操作 1.变量的创建 2.变量的使用 2.1 变量的赋值 2.2 变量的加减 2.3 变量的隐式类型转换 2.4 强制类型转换 3 ...
- Mysql基础7-约束
一.约束的基本概念 1.概念:约束是作用于表中字段上的规则,用于限制储存在表中的数据 2.目的:保证数据库中的数据的正确性,有效性和完整性 3.分类 非空约束(not null):限制该字段的数据不能 ...
- 侯捷C++STL源码分析
STL六大部件 容器(Containers):放东西,需要占用内存. 分配器(Allocators):支持容器. 算法(Algorithms):操作容器里面的数据. 迭代器(Iterators):容器 ...
- 手摸手带你初探Vue 3.0
1 前言 距离Vue 3.0正式发布已经过去一段时间了,2月7日Vue团队正式宣布Vue 3正式成为新的默认版本.最近接触的新项目也使用Vue 3.0来开发,因此有必要对它进行一波总结和学习. 2 简 ...
- .NET下数据库的负载均衡“经典方案”(大项目必备,建议收藏)
[前言] 本文讲述的"数据库负载均衡"方案,为市面上最经典(没有之一),由.NET界骨灰级大佬推出.采用该技术方案的大公司,一年省下了几个亿的支出. [正文] 支持.Net Cor ...
- 线性关系和非线性关系在.net中的应用
在数学中,线性关系和非线性关系是描述两个变量之间函数关系的两种不同类型. 线性关系是指两个变量之间可以用一条直线来表示的关系.具体来说,如果存在一个一次函数 y = kx + b,其中k和b是常数,使 ...
- vue3 + ElementPlus 封装函数式弹窗组件
需求场景:弹窗组件需要支持自定义的插槽内容,删除的弹窗也要使用这个组件,只是样式不一样而已,希望在父组件使用删除弹窗的时候直接调用某个方法就可以显示弹窗 组件模拟 cuDialog 假设我的弹窗组件有 ...
- MindSponge分子动力学模拟——安装与使用(2023.08)
技术背景 昇思MindSpore是由华为主导的一个,面向全场景构建最佳昇腾匹配.支持多处理器架构的开放AI框架.MindSpore不仅仅是软件层面的工具,更重要的是可以协同华为自研的昇腾Ascend平 ...
- 9、Spring之代理模式
9.1.环境搭建 9.1.1.创建module 9.1.2.选择maven 9.1.3.设置module名称和路径 9.1.4.module初始状态 9.1.5.配置打包方式和依赖 <?xml ...