《代码整洁之道》读书笔记四
错误处理
抽离Try/Catch代码块
函数应该只做一件事,错误处理就是一件事。
// bad
public void delete(Page page) {
try{
deletePage(page);
registery.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey();
}catch(Expection e){
logError(e);
}
}
// good
public void delete(Page page) {
try{
// 将上例的操作,封装到一个方法
deletePageAndAllReferences(page);
}catch(Expection e){
logError(e);
}
}
使用非受控异常
受控异常:Checked Exception(FileException、SQLException等)
,这类异常必须写 try/catch
,或者 throw抛出
,否则编译通不过。
非受控异常:Unchecked Exception
,这类异常也叫做运行时异常(与非受控异常 字数相等),这类异常不需要 try/catch
,也不需要 throw抛出
。即使 throw 了,上层调用函数也非必须捕获,编译能通过。
受控异常的代价就是违反开放/闭合原则。如果你在方法中抛出受控异常,这意味着每个调用该函数的函数都要修改,捕获新异常,或在其签名中添加合适的throw语句。对于一般的应用开发,受控异常依赖成本要高于收益成本,尽量 try/catch
处理,不要抛出。
给出异常发生的环境说明
应创建信息充分的错误信息,并和异常一起传递出去。在消息中,包括失败的操作和失败类型。如果你的应用程序有日志系统,传递足够的信息给catch块,并记录下来。
依调用者需要定义异常类
// bad
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,确保它返回通过用异常类型,从而简化代码
// good
LocalPort port = new LocalPort(12);
try {
port.open();
} catch(PortDeviceFailure e) {
reportError(e);
logger.log(e.getMessage(),e);
} finally {
// .....
}
public class LocalPort{
private ACMEPort innerPort;
public LocalPort(int portNumber){
innerPort = new ACMEPort(portNumber);
}
public 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);
}
}
}
将第三方API打包是个良好的实践手段。当你打包一个第三方API,你就降低了对它的依赖。
其他
- try catch语句块的范围不要太大,这样不利于对异常的分析
- 别返回null值,这样可以减少调用者的防御性检测。与其返回null,不如抛出异常,或是返回特例对象(特例对象详见 p101)
- 别传递null值,传递null就要求被调用函数需要一系列防御性检测,也就意味着程序有更大可能出错
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2020-11-08 2020/11/08 刘一辰的JAVA随笔