Cleaner, more elegant, and wrong(翻译)
Cleaner,more elegant,and wrong
整洁,更优雅,但是错的
并不是因为你看不到错误的产生路径就意味着它不存在。
下面是C#编程书中的一个片段,摘自关于异常处理的章节。
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.
请看这个解决方案是多么地整洁和优雅。
整洁,更优雅,但是错的。
假设在CreateIndexes()中抛出异常。GenerateDatabase()函数没有捕获它,所以错误被抛给执行catch的调用者,
当异常离开GenerateDatabase()时,重要信息已经丢失:数据库创建的状态捕获异常的代码不知道数据库创建的哪个步骤失败了。是否要删除索引?是否需要删除表吗?是否需要删除物理数据库?它不知道。
因此,如果创建CreateIndexes()时出现问题,则永远会泄露物理数据库文件和表。(由于这些可能是磁盘上的文件,所以它们无限期地挂起)。
在异常抛出模型中编写正确的代码比错误代码模型中更难,因为任何事情都可能是吧,您必须做好准备。在错误代码模型中,什么时候必须要检查错误是很明显的:当收到错误代码时。在异常处理模型中,你只需要错误可能会发生在任何地方。
换句话说,在错误代码模型中,很明显的是如当有人处理错误失败:他们没有检查错误代码。但是在一个异常抛出模型中,从代码中看不出是否有人处理错误,因为错误并不是明确的。
考虑如下:
Guy AddNewGuy(string name)
{
Guy guy = new Guy(name);
AddToLeague(guy);
guy.Team = ChooseRandomTeam();
return guy;
}
这个函数创建一个新的Guy,将他加入了联盟,并随机分配给一个团队。没有比这更简单的了。
记住:每一行都可能发生错误。
如果 “new Guy(name)“抛出异常怎么办?
好吧,幸运的是,我们还没有开始做任何事情,所以没有任何伤害 。
如果“AddToLeague(guy)“抛出异常怎么办?
我们创建的“Guy“将被放弃,GC将会清理它。
如果“guy.Team = ChooseRandomTeam()“抛出异常怎么办?
呃哦,现在我们很麻烦我们已经把这个人加入了联盟。如果有人捕获这个异常,他们将在联盟中找到一个不属于任何球队的人。如果有一些代码遍历联盟的所有成员,并使用gue.Team成员,他们将会获得NullReferenceException,因为guy.Team尚未初始化。
在编写代码时,您是否考虑到每行代码引发异常的后果呢?如果你打算写正确的代码,你必须这样做。
好吧,怎么解决这个问题?对操作重新排序。
Guy AddNewGuy(string name)
{
Guy guy = new Guy(name);
guy.Team = ChooseRandomTeam();
AddToLeague(guy);
return guy;
}
这种看似微不足道的变化对错误恢复有很大的影响。通过延迟提交数据(将guy加入到联盟),任何人员在创建过程中所遇到的异常都没有持久的影响。发生异常时,部分构造的guy被遗弃,最终被GC回收。
当然,这个例子很简单,因为设置guy的步骤没有副作用。如果设置过程中出现错误,我们可以抛弃guy,让GC清理回收。
在现实世界中,事情是比较麻烦的。考虑以下几点:
Guy AddNewGuy(string name)
{
Guy guy = new Guy(name);
guy.Team = ChooseRandomTeam();
guy.Team.Add(guy);
AddToLeague(guy);
return guy;
}
这与我们修正的函数一样,只是有人认为:如果每个球队保留一个成员列表,将会更有效率。所以您必须将自己添加到打算加入的球队中。这样做对函数的正确性有什么样后果?
Cleaner, more elegant, and wrong(翻译)的更多相关文章
- Cleaner, more elegant, and harder to recognize(翻译)
Cleaner, more elegant, and harder to recognize 更整洁,更优雅,但更难识别 看来,有些人把我几个月前一篇文章的标题"Cleaner,more e ...
- 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 e ...
- 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 ...
- Go 开发关键技术指南 | 敢问路在何方?(内含超全知识大图)
作者 | 杨成立(忘篱) 阿里巴巴高级技术专家 Go 开发关键技术指南文章目录: 为什么你要选择 Go? Go 面向失败编程 带着服务器编程金刚经走进 2020 年 敢问路在何方? Go 开发指南大图 ...
- Go 开发关键技术指南 | Go 面向失败编程 (内含超全知识大图)
作者 | 杨成立(忘篱) 阿里巴巴高级技术专家 关注"阿里巴巴云原生"公众号,回复 Go 即可查看清晰知识大图! 导读:从问题本身出发,不局限于 Go 语言,探讨服务器中常常遇到的 ...
- Java 7 Concurrency Cookbook 翻译 第一章 线程管理之四
七.创建和运行一个后台线程 Java中有一种特别的线程叫做 deamon(后台) 线程.这类线程具有非常低的权限,并且只有在同一个程序中没有其他的正常线程在运行时才会运行.注意:当一个程序中只剩下后台 ...
- [翻译]Java垃圾收集精粹(Java Garbage Collection Distilled)
source URL: http://www.infoq.com/articles/Java_Garbage_Collection_Distilled Name: Java Garbage Colle ...
- Effective Java 第三版——8. 避免使用Finalizer和Cleaner机制
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- PEP8中文翻译(转)
原文:https://github.com/zgia/manual PEP 8 -- Style Guide for Python Code PEP Index > PEP 8 -- Style ...
随机推荐
- 爱立信开始大规模mesh网络测试
mesh网络可谓是物联网之关键,相较于传统有线技术,无线连接的mesh网络实施成本较低,而且更具有适应性和可扩展性,让高通信量的应用更加可靠. 虽然Thread和ZigBee等细分技术也能提供标准化的 ...
- 关于MVC Ajax.BeginForm()异步上传文件的问题
问题描述: 如果用juqery原生的异步上传方式,只要如下方法即可 $.ajax({ type: "GET", url: "test.json", data: ...
- Jersy、Jetty和Servlet
1.Jersy框架 Jersey RESTful WebService框架是一个开源的.产品级别的JAVA框架,是JAX-RS的参考实现.Jersey提供自己的API,其API继承自JAX-RS,提供 ...
- 51Nod--1008
1008 N的阶乘 mod P 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 输入N和P(P为质数),求N! Mod P = ? (Mod 就是求模 % ...
- CenterOS 7 基础命令学习
CentOS 7 命令 网络配置 nmcli(NetworkManageCommandLineInterface)查看网卡 nmtui(NetworkManageTextUserInterface)网 ...
- C#设计模式之二十策略模式(Stragety Pattern)【行为型】
一.引言 今天我们开始讲"行为型"设计模式的第七个模式,该模式是[策略模式],英文名称是:Stragety Pattern.在现实生活中,策略模式的例子也非常常见,例如,在一个 ...
- js通用方法检測浏览器是否已安装指定插件(IE与非IE通用)
/* * 检測是否已安装指定插件 * * pluginName 插件名称 */ function checkPlugins(pluginName) { var np = navigator.plugi ...
- 利用java mail发送邮件(转)
JavaMail是SUN提供给开发者在应用程序中实现邮件发送和接收功能而提供的一套标准开发类库,支持经常使用的邮件协议,如SMTP.POP3.IMAP.开发者使用JavaMail编写邮件程序时,无需考 ...
- SVN 的一些操作
SVN是一个非常好的代码管理工具. 之前一直是使用现有的SVN环境,认为非常方便. 可是近期要自己搭建一个SVN环境来托管自己的代码,并且代码放在独立的server上,所以决定自己搭建一个SVN环境. ...
- ASP.NET Core 中间件(Middleware)详解
什么是中间件(Middleware)? 中间件是组装到应用程序管道中以处理请求和响应的软件. 每个组件: 选择是否将请求传递给管道中的下一个组件. 可以在调用管道中的下一个组件之前和之后执行工作. 请 ...