异常驱动的开发(Exception-Driven Development)
你的网站或应用程序存在哪些问题?如果你在等着用户来告诉你,那么你只能看到所有的问题中已经暴露的那极小的一部分。要知道,那只是“冰山一角”!
而且,如果你真的是在守株待兔,我不得不很抱歉地告诉你,你有点失职——你应该比用户更了解你的程序的健康状况。每当有用户告诉我一个他们在使用我的软件的过程中碰到的“善意的错误”时,我总会感到局促不安。甚至有些惭愧。我没有在用户把问题告诉我之前发现它们,并且事先解决它们,这就是我的失职。我忽视了对程序崩溃应付的责任。
任何负责任的软件项目,首先要做的事是建立一种异常和错误报告机制。Ned Batchelder把这比作为“先给自己戴好氧气罩,然后再帮小朋友戴”:
当你的程序出现问题时,请你总是先去检查这个错误是否被适当处理了。如果没有被适当处理,那么先去解决错误处理代码里的问题。保持这个工作顺序很重要,原因有如下几方面:
- 在根源错误还在的情况下,你实际上为错误处理代码中的bug准备了一个完美的测试用例。但如果你先把根源问题解决了,你又将怎样来测试你的错误处理代码呢?记住,你的代码里之所以有bug,部分原因就是它在当初的开发阶段很难被测到。
- 一旦根源问题被解决了,解决错误处理代码里的问题的紧迫性便随之消失。你可能会说,“我以后会去解决的,现在急啥?”就好比你家屋顶漏了——下雨的时候,你没办法去修屋顶,因为外面正下着雨呢;但雨停了之后,家里又不漏水了(不急着去修屋顶了)!
你需要集中在一个地方去处理所有的错误。这个地方是你团队里的所有开发人员非常熟悉的,并且每天都会接触到。在Stack Overflow,我们采用了ELMAH(https://code.google.com/p/elmah)的一个自定义分支。
我们每天都在监视着这些异常日志;有时候每个小时都察看。这些异常日志实际上已经成为了我们团队的To-Do列表(待办事项)。我们这么做是有充分理由的。比如,微软收集类似的这种错误日志已经几年了,他们不仅收集自家软件的日志,还收集第三方软件的;他们的这个机制叫Windows Error Reporting(简称WER)。成效喜人啊:
当最终用户遇到程序崩溃时,他们会看到一个对话框,问他们是否想发送错误报告。如果他们选择发送,WER会收集应用程序以及发生崩溃的模块的信息,然后把这些信息通过一个安全服务器发送给微软。
于是,软件厂商可以访问到关于他们产品的数据,再加以分析,定位到问题的根源。他们可以通过错误对话框与用户交互,还可以通过Windows Update升级他们的程序。
在对错误报告数据的广泛分析之后,我们看到:80%的客服问题在修复了用户报得最多的20%的bug之后就能得到解决。即使只修复用户报得最多的1%的bug,也能解决50%的客服问题。这个分析结果通常对于各家公司都是成立的。
尽管我仍然推崇“测试驱动开发”(Test-Driven Development,缩写为TDD),但时间投入的投机性一直是我纠结的一个问题。如果你修复了一个真实用户永远也碰不到的bug,那你的修复有什么价值呢?我知道还有很多其他的理由促使我们去实践TDD,但若单纯作为一种修复bug的机制,在我看来,选用TDD就大可不必了;就像我们过早地进行代码优化一样,是不可取的。我更愿意把时间花在解决真实发生的问题上,而不是那些理论上存在的bug。
当然,你可以两者都做。但考虑到开发时间总是有限的,我更倾向于立足于实实在在的数据,把时间花在解决真实用户在使用我的软件过程中碰到的问题上。这就是我所谓的“异常驱动的开发”(Exception-Driven Development)——将你的软件发布出去,让尽可能多的用户使用它,然后一心一意地研究他们产生的错误日志。使用那些异常日志去找出问题的根源,并且专注在你的代码中有问题的区域。重新架构,重构代码,以消除最严重的3个问题。快速迭代,部署,如此周而复始。这种数据驱动的反馈机制是非常有效的,几个迭代下来,你的程序将非常稳定,坚如磐石。
异常日志可能是用户能够提供给你的最强有力形式的反馈。这种反馈基于已经发布的软件,为了得到它们,你不必去询问用户或者诱导他们,也不必理会他们关于问题的不可思议、似是而非的描述。真正的问题伴随着转储出来的堆栈跟踪信息,已经悄悄地为你自动收集好了。异常日志才是用户反馈中的根本。
(译者注:2009年4月16日,DareObasanjo与Scott Koon @lazycoder在Twitter上有过一次辩论;Dare Obasanjo的观点是:通过将产品发布出去,然后从客户那里得到真实的反馈,这比任何事先的沟通或调研更有价值。)
我是在提倡发布带有bug的代码吗?或者半成品?或者狗屎软件?当然不是!我的意思是说,你越快将你的软件推到真实用户的面前,你就会得到越多的数据以改进你的软件。异常日志在这个过程中扮演着很重要的角色,同样地,用户使用数据也很重要。当然,如果你受得了的话,你还应该跟用户交谈。
不管怎么样,软件在发布的时候总是会带有bug的。所有软件都是这样。只要是软件,它就会崩溃,它就可能丢失数据,它还会难以学习、难以使用。问题不在于你在发布软件的时候带出去了多少bug,而在于你能多快地修复那些bug?如果你的团队一直在践行异常驱动的开发模式,答案就很简单了——别担心,我们马上就会改进我们的软件!看着吧,我们会越做越好!
听起来多美妙啊!就像一首美妙的乐曲,在每个用户的耳边萦绕……
异常驱动的开发(Exception-Driven Development)的更多相关文章
- 【翻译稿】Behavior Driven Development (BDD)行为驱动开发
这是一篇翻译稿,方便给不知道BDD的同学扫盲.原文链接:What is BDD (Behavior Driven Development)? | Agile Alliance Definition定义 ...
- Bug驱动开发(Bug-driven development)
说实话,作为一个Domino开发者,像測试驱动开发(Test-driven development).功能驱动开发(Feature-driven development)之类软件开发的高大上的方法论( ...
- 敏捷软件开发 Agile software Development(转)
原文链接: http://www.cnblogs.com/kkun/archive/2011/07/06/2099253.html 敏捷软件开发 Agile software Development ...
- 编写高质量代码改善C#程序的157个建议[用抛异常替代返回错误、不要在不恰当的场合下引发异常、重新引发异常时使用inner Exception]
前言 自从.NET出现后,关于CLR异常机制的讨论就几乎从未停止过.迄今为止,CLR异常机制让人关注最多的一点就是“效率”问题.其实,这里存在认识上的误区,因为正常控制流程下的代码运行并不会出现问题, ...
- Java异常:选择Checked Exception还是Unchecked Exception?
http://blog.csdn.net/kingzone_2008/article/details/8535287 Java包含两种异常:checked异常和unchecked异常.C#只有unch ...
- S3C2440触摸屏驱动实例开发讲解
出处:http://www.embeddedlinux.org.cn/html/yingjianqudong/ 一.开发环境 主 机:VMWare--Fedora 9 开发板:Mini2440--6 ...
- Vs2010 配置驱动的开发环境
我已被用来VS2010开发环境,之前曾经与vs2010驱动的开发环境.重装系统,一次又一次的配置,找了好几篇文章,配置没有成功,在配置阶段突然成功了,直接把原来的驱动程序的配置文件将能够接管使用. 当 ...
- hibernate异常:org.hibernate.exception.GenericJDBCException
异常:org.hibernate.exception.GenericJDBCException 提示:Cannot open connection 提示:不能打开链接 一般这个异常是由 java.sq ...
- Atititjs javascript异常处理机制与java异常的转换.js exception process
Atititjs javascript异常处理机制与java异常的转换.js exception process 1. javascript异常处理机制 Throw str Not throw err ...
随机推荐
- plsql和tsql常用函数比较
数学函数 .绝对值 S:) value O:) value from dual .取整(大) S:select ceiling(-1.001) value O:select ceil(-1.001) ...
- Oracle中表字段相关操作举例
--创建测试表 create or replace table student ( xh ), --学号 xm ), --姓名 sex ), --性别 birthday date, --日期 sal ...
- 02_版本控制工具SVN
SubVersion: 安装:根据电脑版本选择安装64或32位的subversion,尽量不要选择中文或者有空格的目录安装 版本控制仓库: 创建命令:SVNadmin create 目录 启动SVN服 ...
- 安全框架Shiro
原文地址:https://www.cnblogs.com/learnhow/p/5694876.html 一.架构 要学习如何使用Shiro必须先从它的架构谈起,作为一款安全框架Shiro的设计相当精 ...
- ThreadLocal深入剖析
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序,Threa ...
- Dynamics CRM2016 Web API获取实体元数据Picklist属性的Text&Value
通过组织服务中获取实体picklist字段的text和value可以通过RetrieveAttributeRequest实现,但在使用web api的今天该怎么实现,本文即来一探究竟,本篇基于SDK中 ...
- Objective-C方法的实现
Objective-C的方法被两种数据类型描述:一个是选择子(SEL),它用来描述方法的名称;另一个是实现(IMP),它用来描述方法被调用时实际执行的代码(它们基本上只是C函数的指针). 类似于SEL ...
- Android布局概述
布局 布局定义用户界面的视觉结构,如Activity或应用小部件的 UI.您可以通过两种方式声明布局: 在 XML 中声明 UI 元素.Android 提供了对应于 View 类及其子类的简明 XML ...
- Dynamics CRM2016 升级老版本报“JavaScript Web 资源包含对 Microsoft Dynamics CRM 4.0 (2007) Web 服务终结点的引用”问题的解决办法
今天在新的服务器上部署了CRM2016 on-premises,并将CRM2015的数据库拷贝过来准备附加后升级,但在升级过程中遇到了如下错误,向导检测到了我的JavaScript Web 资源中包含 ...
- 如何使用Matlab产生对称矩阵
有时候做实验需要使用对称矩阵,这里介绍如何使用Matlab产生随机的对称矩阵. 用例子说明一下:我要产生4X4的随机矩阵,要求是对称矩阵. 产生对称矩阵 A = rand(4); B = tril(A ...