Cleaner, more elegant, and wrong(msdn blog)
Cleaner, more elegant, and wrong
Just because you can't see the error path doesn't mean it doesn't exist.
Here's a snippet from a book on C# programming, taken from the chapter on how great exceptions are.
try {
AccessDatabase accessDb = new AccessDatabase();
accessDb.GenerateDatabase();
} catch (Exception e) {
// Inspect caught exception
} public void GenerateDatabase()
{
CreatePhysicalDatabase();
CreateTables();
CreateIndexes();
}Notice how much cleaner and more elegant [this] solution is.
Cleaner, more elegant, and wrong.
Suppose an exception is thrown during CreateIndexes(). The GenerateDatabase() function doesn't catch it, so the error is thrown back out to the caller, where it is caught.
But when the exception left GenerateDatabase(), important information was lost: The state of the database creation. The code that catches the exception doesn't know which step in database creation failed. Does it need to delete the indexes? Does it need to delete the tables? Does it need to delete the physical database? It doesn't know.
So if there is a problem creating CreateIndexes(), you leak a physical database file and a table forever. (Since these are presumably files on disk, they hang around indefinitely.)
Writing correct code in the exception-throwing model is in a sense harder than in an error-code model, since anything can fail, and you have to be ready for it. In an error-code model, it's obvious when you have to check for errors: When you get an error code. In an exception model, you just have to know that errors can occur anywhere.
In other words, in an error-code model, it is obvious when somebody failed to handle an error: They didn't check the error code. But in an exception-throwing model, it is not obvious from looking at the code whether somebody handled the error, since the error is not explicit.
Consider the following:
Guy AddNewGuy(string name)
{
Guy guy = new Guy(name);
AddToLeague(guy);
guy.Team = ChooseRandomTeam();
return guy;
}
This function creates a new Guy, adds him to the league, and assigns him to a team randomly. How can this be simpler?
Remember: Every line is a possible error.
- What if an exception is thrown by "new Guy(name)"?
-
Well, fortunately, we haven't yet started doing anything, so no harm done.
- What if an exception is thrown by "AddToLeague(guy)"?
-
The "guy" we created will be abandoned, but the GC will clean that up.
- What if an exception is thrown by "guy.Team = ChooseRandomTeam()"?
-
Uh-oh, now we're in trouble. We already added the guy to the league. If somebody catches this exception, they're going to find a guy in the league who doesn't belong to any team. If there's some code that walks through all the members of the league and uses the guy.Team member, they're going to take a NullReferenceException since guy.Team isn't initialized yet.
When you're writing code, do you think about what the consequences of an exception would be if it were raised by each line of code? You have to do this if you intend to write correct code.
Okay, so how to fix this? Reorder the operations.
Guy AddNewGuy(string name)
{
Guy guy = new Guy(name);
guy.Team = ChooseRandomTeam();
AddToLeague(guy);
return guy;
}
This seemingly insignificant change has a big effect on error recovery. By delaying the commitment of the data (adding the guy to the league), any exceptions taken during the construction of the guy do not have any lasting effect. All that happens is that a partly-constructed guy gets abandoned and eventually gets cleaned up by GC.
General design principle: Don't commit data until they are ready.
Of course, this example was rather simple since the steps in setting up the guy had no side-effects. If something went wrong during set-up, we could just abandon the guy and let the GC handle the cleanup.
In the real world, things are a lot messier. Consider the following:
Guy AddNewGuy(string name)
{
Guy guy = new Guy(name);
guy.Team = ChooseRandomTeam();
guy.Team.Add(guy);
AddToLeague(guy);
return guy;
}
This does the same thing as our corrected function, except that somebody decided that it would be more efficient if each team kept a list of members, so you have to add yourself to the team you intend to join. What consequences does this have on the function's correctness?
Cleaner, more elegant, and wrong(msdn blog)的更多相关文章
- Cleaner, more elegant, and wrong(翻译)
Cleaner,more elegant,and wrong 整洁,更优雅,但是错的 并不是因为你看不到错误的产生路径就意味着它不存在. 下面是C#编程书中的一个片段,摘自关于异常处理的章节. try ...
- 树状数组的笔记√(hzwer blog)
int lowbit(int x) { return x&(-x); } lowbit()的返回值就是 2^k 次方的值. 求数组的和的算法: (1)首先,令sum=0,转向第二步: (2)接 ...
- Alpha 任务状态总览(持续更新)
Alpha 任务状态总览(持续更新) Part 0 · 简 要 目 录 Part 1 · 流 程 Part 2 · 总 任 务 量 安 排 Part 3 · 爬 虫 任 务 Part 4 · 接 口 ...
- Cleaner, more elegant, and harder to recognize (msdn blog)
It appears that some people interpreted the title of one of my rants from many months ago, "Cle ...
- Cleaner, more elegant, and harder to recognize(翻译)
Cleaner, more elegant, and harder to recognize 更整洁,更优雅,但更难识别 看来,有些人把我几个月前一篇文章的标题"Cleaner,more e ...
- js 正则表达式 转至(七郎's Blog)
//匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线 var re =new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,19}$"); if( ...
- Visual Studio 2010 简体中文旗舰、专业版(MSDN原版下载)
Visual Studio 2010 简体中文旗舰.专业版(MSDN原版下载)(Visual Studio 2010 ultimate professional x86 dvd)2010[光盘镜像]- ...
- Hibernate 配置 转(http://blog.csdn.net/b671900/article/details/39156065)
做项目必然要先进行数据库表设计,然后根据数据库设计建立实体类(VO),这是理所当然的,但是到公司里做项目后,让我认识到,没有说既进行完数据库设计后还要再“自己”建立一变VO.意思是,在项目设计时,要么 ...
- HDU 5813 Elegant Construction(优雅建造)
HDU 5813 Elegant Construction(优雅建造) Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65 ...
随机推荐
- 初学者易上手的SSH-整合
许久没更新博客了! spring还有一章aop(面向切面),我就没讲述了,你们可以去看下代理模式. 那么我们开始整合:struts2 2.3.4 ,hibernate 5.2.10 ,spring ...
- Python3.6_安装numpy
刚刚编辑了一次,但是犯了新手都会犯的没保存的错误,第二次编辑可能略有粗糙,如有问题欢迎指正 想用Python 画图,但是我的是vs自动安装的因此缺少许多必要的库,在安装的过程中也是遇到了诸多问题,下面 ...
- codeforces 895B XK Segments 二分 思维
codeforces 895B XK Segments 题目大意: 寻找符合要求的\((i,j)\)对,有:\[a_i \le a_j \] 同时存在\(k\),且\(k\)能够被\(x\)整除,\( ...
- php银联网页支付实现方法
本文实例讲述了php银联网页支付实现方法.分享给大家供大家参考.具体分析如下: 这里介绍的银联WAP支付功能,仅限消费功能. 1. PHP代码如下: 复制代码代码如下: <?phpna ...
- NOIP2017提高组初赛解析
首发于订阅号 嗨编程,这是一个以嗨为目标的编程订阅号(仅仅是目标而已),扫码可关注,不定期更. 解析中引用了一张关于排序的总结课件图片,来源网络,如果侵权,请联系本人删除(没钱付版权费)
- Struts2学习笔记整理(一)
最近在学习框架,很多人建议我直接学SSM,SSM看了一段时间后发现很多东西虽然可以用了,但是并不是很了解,所以我打算重新来过.从SSH开始学习,前面已经大致的学习了Hibernate,对于Hibern ...
- 不用asp.net MVC,用WebForm照样能够实现MVC
在<避开WebForm天坑,拥抱ASP.Net MVC吧>这篇博客中我讲到了ASP.net WebForm由于一些先天的"诱导犯罪"的缺陷,如今用ASP.net MVC ...
- HTML中在a标签中添加onclick事件
1.链接的onclick 事件被先执行,其次是href属性下的动作; 2.假设链接中同时存在href 与onclick,如果想让href 属性下的动作不执行,onclick 必须得到一个false的返 ...
- Lua的数学函数
ua5.1中数学库的所有函数如下表: math.pi 为圆周率常量 = 3.14159265358979323846 函数名 函数功能 示例 示例结果 abs 取绝对值 math.abs(-15) ...
- 自学Python2.2-基本数据类型-列表list(object)
Python List方法总结 一. 列表简介: 列表是序列对象,可包含任意的Python数据信息,如字符串.数字.列表.元组等 列表的数据是可变的,我们可通过对象方法对列表中的数据进行增加.修改 ...