`
feikiss
  • 浏览: 97999 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

clean-code: 错误处理

阅读更多
下面就Clean code 中关于如何优雅的处理一些错误代码总结的一些技巧和思路。

1、使用异常而非返回码

请看下面的代码清单, DeviceController.java
public class DeviceController {
	...
	public void sendShutDown(){
		//Check the state of the device
		if(handle != DeviceHandle.INVALID){
			//Save the device status to the record field
			DeviceRecord record = retrieveDeviceRecord(handle);
			//If not suspended, shut down
			if(record.getStatus() != DEVICE_SUSPENDED){
				pauseDevice(handle);
				clearDeviceWorkQueue(handle);
				closeDevice(handle);
			}else {
				logger.log("Device suspende.");
			}
		} else{
			logger.log("invalid handle for:" + DEV1.toString());
		}
	}
	...
}

我想大家在项目中都碰到过类似的嵌套检查。这类手段的问题在于,他们搞乱了调用者代码。调用者必须在调用之后即可检查错误。不幸的是,这个步骤很容易被遗忘。所以,遇到错误时,最好抛一个异常。调用代码很整洁,其逻辑不会被错误处理搞乱。
下面的代码清单展示了方法中遇到错误时抛出异常的情形。
代码清单: DeviceController.java(采用异常处理)
public class DeviceController {
	...
	public void sendShutDown(){
		try{
			tryToShutDown();
		}catch(DeviceShutDownError e){
			logger.log(e);
		}
	}
	
	private void tryToShutDown() throws DeviceShutDownError{
		DeviceHandle handle = getHandle(DEV1);
		DeviceRecord record = retrieveDeviceRecord(handle);
		
		pauseDevice(handle);
		clearDeviceWorkQueue(handle);
		closeDevice(handle);
		
	}
	
	private DeviceHandle getHanle(DeviceID id){
		...
		throw new DeviceShutDownError("invalid handle for: " + id.toString());
		...
	}
	
	private DeviceRecord retrieveDeviceRecord(DeviceHandle handle){
		...
		throw new DeviceShutDownError("Device suspended.");
		...
	}
	...
}

这段代码就整洁了很多,当然多出了一些异常类,但这是不可缺少的。。。
现在,对两个元素设备的关闭算法和错误处理已经被隔离了,我们可以查看其中任一元素,并分别理解和处理他们,而不必去修改业务逻辑代码。

2、根据调用者需要来定义异常类。
当我们在应用程序中定义异常时,最重要的考虑应该是“他们如何被捕获”。
来看一个很常见的代码。
代码清单:

	ACMEPort port = new ACMEPort(12);
	
	try{
		port.open();
	}catch(DeviceResponseException e){
		reportPortError(e);
		logger.log("Device response exception",e);
	}catch (ATM1212UnlockedException e){
		reportPortError(e);
		logger.log("Unlock exception",e);
	}catch(GMXError e){
		reportPortError(e);
		logger.log("Device response exception",e);
	}finally {
		...
	}

可以看到,语句中包含了大量的重复代码,这并不奇怪。因为我们得记录错误,确保能继续工作。
在本例中,既然我们知道我们所作的事儿不外如此,就可以通过打包调用API,确保它返回通用异常类型,从而简化代码。
代码清单:
LocalPort port = new LocalPort(12);
	try{
		port.open();
	}catch (PortDeviceFailure e){
		reportError(e);
		logger.log(e.getMessage(),e);
	}finally{
		...
	}
	
LocalPort类就是个简单的打包类,捕获并翻译由ACMEPort类抛出的异常:	
public class LocalPort{
		private ACMEPort innerPort;
		
		public LocalPort(int portNumber){
			innerPort = new ACMEPort(portNumber);
		}
	}
	
	public void open(){
		try{
			innerport.open();
		}catch(DeviceResponseException e){
			throw new PortDeviceFailure(e);
		}catch (ATM1212UnlockedException e){
			throw new PortDeviceFailure(e);
		}catch(GMXError e){
			throw new PortDeviceFailure(e);
		}
	}
	...
}

类似我们为ACMEPort定义的这种打包类非常有用,这也可以看作是对第三方API做了一个代理,实际上,将第三方API打包是个良好的实践手段。当打包一个第三方API,就降低了对它的依赖:未来你可以不太痛苦地改用其他代码库。而且在测试自己的代码时,打包也有助于模拟第三方调用。
3、别返回null值
对于NullPointerException,想必大家都熟悉得不能再熟悉了。那么如何尽量避免空指针异常呢?其一就是尽量避免返回null值,可以用一个特例对象来代替。如果是调用第三方API返回null值,可以在新方法中抛出异常或返回特例对象,比如在Java中如果返回的是一个list,如果返回为null,完全可以用Cloolections.emptyList()来代替,这样调用者就不必来检查获取的结果是否为null了。
4、别传递null值,在大多数编程语言中,没有良好的方法能对付由调用者意外传入的null值,事已至此,恰当的做饭就是禁止传入null值。

以上代码是阅读Clean code第七章后做的一些小笔记,大家可以共同学习。
1
0
分享到:
评论

相关推荐

    go-clean-code:罗伯特·C·马丁(Robert C. Martin)用“ Go(GoLang)”写的“清洁代码”一书中的示例[必须阅读!]

    清理代码 罗伯特·C·马丁(Robert C. Martin)用“ Go(GoLang)”写的“清洁代码”一书中的示例[必须...错误处理 界线 单元测试 *班 系统篇 紧急情况 并发 不断完善 * JUnit内部 重构SerialDate 嗅觉和启发式 *待定

    Clean-Code-in-Python:Packt发布的Python中的Clean Code

    在所有这些领域中,经验丰富的专业人员都可以找到由于代码错误而导致的效率低下,问题和其他危险的示例。 阅读本书之后,读者将了解这些问题,更重要的是,如何解决这些问题。 本书涵盖了以下激动人心的功能:设置...

    clean-commit-action:Github防止错误的git commit消息的动作

    [WIP]清洁承诺行动Clean-commit-action是防止不良git commit消息的简单操作。为什么提交消息起着非常重要的作用,并且是在很长一段时间后去查看提交内容的最佳方式,可以与将来的开发人员以及我们自己通信。 我们...

    worldwindjava源码-CleancodeNotes:这个repo包含来自RobertC.Martin的书CleanCode:AHan

    逻辑应该简单明了,使错误难以隐藏,依赖最小化以简化维护,根据明确的策略完成错误处理,以及接近最佳的性能,以免诱使人们通过无原则的优化使代码变得混乱。 干净的代码可以很好地做一件事。 对象的Grady Booch...

    CrashLab-CleanCode:用于阅读关于“崩溃研究”的“清洁代码”一书的研讨会数据

    CrashLab-CleanCode 阅读并讨论 (Robert C. Martin 的)。(发布! :deciduous_tree: ) [] [ ] (划分! :four_leaf_clover: ) [ ] [] [ Sujin(+Jeongryeol/Seonghyeon) ] 第 6 章对象和数据结构[ Sort(+Sunghyeon)...

    idv-one-time-passcode:idv一次密码服务

    IDV一次性密码去做添加简单的应用程序集成测试以验证otp是否获得完整的otp添加空手道测试以验证otp并获取完整的otp安全敏感数据标志从上下文为真添加json错误处理有用的命令// cleans build directories// prints ...

    适用于TypeScript的Clean Code概念-javascript

    目录 介绍 变量 函数 对象和数据结构 类 SOLID 测试 并发错误处理 格式 注释 翻译 介绍 软件工程原理,出自 Robert C. Martin 的著作 Clean Code,适用于 TypeScript。 这不是风格指南。 它是在 TypeScript 中生成...

    cleancode:WingDing学习罗伯特·马丁(Robert Martin)的“清洁代码。敏捷软件Craft.io手册”

    道格五月13 Ch05:格式化(18页) 道格五月27 第06章:数据结构(10页) 斯坦五月27 Ch07:错误处理(10页) 斯坦6月10 第08章:边界(8页) 鲍勃6月10 第09章:单元测试(14页) 莱纳斯6月10 第10章:课程(18页) ...

    MyQQ(DosQQ) 超小的精简QQ DEV-C++ 源码

    your source code to me then everyone will know your work and thank you! You can get the latest version of this software (including its source code) at http://home.xxsyzx.com 注意:本软件以及源代码仅...

    uboott移植实验手册及技术文档

    实验三 移植U-Boot-1.3.1 实验 【实验目的】 了解 U-Boot-1.3.1 的代码结构,掌握其移植方法。 【实验环境】 1、Ubuntu 7.0.4发行版 2、u-boot-1.3.1 3、FS2410平台 4、交叉编译器 arm-softfloat-linux-gnu-...

    :bathtub:为JavaScript定制的清洁代码原则-JavaScript开发

    adapted适用于JavaScript的Clean Code原则clean javascript内容简介变量函数对象和数据结构类SOLID测试异步错误处理格式化注释翻译引言Robert C. Martin Clean Code所著的编程原理,适用于JavaScript。 这不是样式...

    用单片机设计的4位密码锁

    单片机核心接受来自键盘扫面电路的道德键值,判断是数字键还是操作键,并送相应的处理程序。单片机提供动态扫描电路的显示码和位选信号,使动态显示电路正常工作。 键盘扫面电路采用4*4键盘,编号0~9做为数字键“0~9...

    测试培训教材

    For example, you can run a system cleanup test that will restart the machine on which an automated test failed. Alternatively, you can create a system test to retrieve information about a machine's ...

    唯品会Java开发手册.zip

    结合唯品会的内部经验,参考《阿里巴巴Java开发手册》《Clean Code》、《Effective Java》等重磅资料进行了大幅定制,包含核心基础类库VJKit ,问题排查工具VJMap 和 VJTop 三部分。 开发工具在软件开发生命周期中...

    网管教程 从入门到精通软件篇.txt

    Chkdsk 命令还可列出并纠正磁盘上的错误。  含有下列参数的 chkdsk 命令仅在使用故障恢复控制台时才可用。可在命令提示符下使用带有不同参数的 chkdsk 命令。  vol [drive:] [ chkdsk [drive:] [/p] [/r]  ...

    Tinyxml 源代码(VC6 & VS2005)

    TinyXML++是一个全新的TinyXML接口,使用了许多诸如模板,异常处理和更好的错误处理这些C++强项技术。 特性 使用STL TinyXML可以被编译成使用或不使用STL。如果使用STL,TinyXML会使用std::string类,而且完全...

    操作系统(内存管理)

    确定您是否有足够的内存来处理数据。 从可用的内存中获取一部分内存。 向可用内存池(pool)中返回部分内存,以使其可以由程序的其他部分或者其他程序使用。 实现这些需求的程序库称为 分配程序(allocators),...

    内存管理内存管理内存管理

    在大部分操作系统中,内存分配由以下两个简单的函数来处理: void *malloc(long numbytes):该函数负责分配 numbytes 大小的内存,并返回指向第一个字节的指针。 void free(void *firstbyte):如果给定一个由...

    sonarQuest:一种重构代码气味的好玩的方法

    通过解决任务和冒险,以有趣的方式处理代码质量问题,通过重构代码味道和优化获得奖励。 有关SonarQuest的游戏概念和应用场景的更多信息: ://www.viadee.de/sonarquest_zh 声纳探秘信息包: : 目标通过将重构过程...

    Excel公式与函数大辞典.宋翔(带书签高清文字版).pdf

    1.8 处理公式中的错误 36 1.8.1 括号不匹配 37 1.8.2 单元格被#符号填满 37 1.8.3 空白但非空的单元格 37 1.8.4 显示值与实际值 38 1.8.5 返回错误值 39 1.8.6 循环引用 41 1.9 公式使用技巧 42 1.9.1 在多...

Global site tag (gtag.js) - Google Analytics