陈同学
微服务
Accelerator
About
# 异常处理的反模式 > 参考资料 > [Exception-Handling Antipatterns Blog](https://community.oracle.com/docs/DOC-983543) from Oracle Community > [Exception management antipatterns](http://javapeanuts.blogspot.com/2012/02/exception-management-antipatterns.html) from Java Peanuts > 《反模式-危机中软件、架构和项目的重构》by 宋锐 等译 [异常设计实践](https://chenyongjun.vip/articles/24) 中有位读者评论:**又记录日志又抛异常反模式设计**。其实我并不知道反模式,本文是对于反模式的学习整理,数据都来自参考资料。 先岔开主题,BB两个小点: * 读者的一个评论,有时却能让笔者受益良多,这也是交流带来的好处,打破认知的局限。 * 对于知识的学习经常是写小学作文的 **总-分-总** 模式。先知晓概念,然后碎片学习,最后整体总结,通过一个个小知识点的积累,最终不断丰富与深化自己知识框架。 ## 关于反模式 设计模式的风靡,反映了软件从业人员对改善行业质量与标准的强烈愿望,因使用和创建可复用的设计模式而获得成功的项目不断增长,设计模式体验了巨大的价值。 设计模式通俗来说就是 **套路**,来源于实践,反哺给实践。但实践中,也常因将设计模式应用于不适当的上下文环境而导致许多问题。 **反模式** 利用实践经验来定义经常发生的错误,让你留意开发过程中潜在的各种陷阱与风险。**反模式**描述了这些易错场景的基本形式、可能带来的负面影响,提供了补救措施,并给这些场景定义了名称。 更多关于反模式的知识,可以阅读《反模式-危机中软件、架构和项目的重构》。 ## 异常处理反模式 > 此处仅挑选几个,更多请参考 [Exception-Handling Antipatterns Blog](https://community.oracle.com/docs/DOC-983543) ### Log and Throw 下面是三个讨厌的反模式,既打印日志又抛出异常,这对于运维工程师来说简直就是噩梦,因为一个问题产生了多种log信息。 例1: ```java catch (NoSuchMethodException e) { LOG.error("Blah", e); throw e; } ``` 例2: ```java catch (NoSuchMethodException e) { LOG.error("Blah", e); throw new MyServiceException("Blah", e); } ``` 例3: ```java catch (NoSuchMethodException e) { e.printStackTrace(); throw new MyServiceException("Blah", e); } ``` ### Throwing Exception ```java public void foo() throws Exception {} ``` 直接抛出 **异常基类** 完全打破了 **checked exeption** 的目的,这样做就是在向你的调用者宣布:**我可能会干点坏事,你悠着点**。 ### Catching Exception ```java try { foo(); } catch (Exception e) { LOG.error("Foo failed", e); } ``` 这是"私吞"异常的例子,也是异常处理中不可饶恕的 **恶行**,异常从此凭空消失,只有这条淹没在日志汪洋中的傻乎乎的日志是唯一线索。 ### Destructive Wrapping ```java catch (NoSuchMethodException e) { throw new MyServiceException("Blah: " + e.getMessage()); } ``` 这种破坏性包装导致原始异常的stack trace丢失,出现异常时大家一起来抓瞎,再抓个实习生顶锅。 ### Return null 下面三个例子都返回null值,除非特殊的业务场景需要返回null值,否则最好抛出异常,让调用者进行处理。 ```java catch (NoSuchMethodException e) { LOG.error("Blah", e); return null; } catch (NoSuchMethodException e) { e.printStackTrace(); return null; } catch (NoSuchMethodException e) { return null; } ``` ### Throw from Within Finally ```java try { blah(); } finally { cleanUp(); } ``` 如果 *cleanUp()* 永远不会抛异常倒还好,因为如果 *blah()* 出错,将进入 *finnaly*,可一旦 *cleanUp()* 出错,将丢失 *blah()* 中抛出的异常,同时需要处理 *finally* 中的异常。 ### Relying on getCause() ```java catch (MyException e) { if (e.getCause() instanceof FooException) {} ``` 依赖 *getCause()* 的代码非常脆弱,这种方式不一定能捕获到真正的异常。推荐使用 Apache的 **commons-lang** 中的 **ExceptionUtils.getRootCause()** 来代替。
本文由
cyj
创作,可自由转载、引用,但需署名作者且注明文章出处。
文章标题:
异常处理的反模式
文章链接:
https://chenyongjun.vip/articles/55
扫码或搜索 cyjrun 关注微信公众号, 结伴学习, 一起努力