我有一个很大的代码库,它有很多很多
的实例try {
// attempt to do something important
} catch (Exception e) {
// do something lame
}
反模式。大约700个实例。我想知道是否有一个工具(例如,IDE或其他东西)可以神奇地,大量地用下一层专门的catch块替换所有这些东西。以下面显示的方式应用类似于IntelliJ或Eclipse "wrap with try/catch"的质量重构的东西。注意:我并不是说所有700都是已知IOException
s;这只是一个例子,假设在特定情况下抛出的唯一异常类型是IOException
)。
我正在寻求的重构是对IntelliJ / Eclipse提供的try{}
块进行相同的语义分析,它提供了“wrap with catch”或“add to throws clause”快速修复:< / p>
try {
// attempt to do something important
// where an IOException is thrown
} catch (IOException e) {
// still do something lame
}
据我所知,这并没有“解决”这个问题,但它保存了考古学的逐步手册。
想法?
答案 0 :(得分:2)
我不认为有任何工具可以做你正在尝试的事情。我可以考虑使用以下算法,但在脚本中自动化它可能需要一些时间......甚至可能需要花费相同的时间来编写脚本来手动进行更改。
class NeverThrown extends RuntimeException {}
全局替换catch (Exception e)
与catch (NeverThrown e)
编译所有文件
对于unreported exception .... must be caught...
的每次出现,都会识别该例外,如果尚未添加,则将其添加到下一个catch
块,例如将catch (NeverThrown e)
替换为catch (NeverThrown, IOException e)
删除所有NeverThrown,
并删除类定义。
当然,更大的智力工作在于决定做什么而不是什么跛脚&#34;。您将无法批量进行,每个案例都必须单独检查。如果我是你,我会停在第3步并经历错误,试图找出如何处理报告的每个未捕获的异常。
或者您可以完全拒绝已检查的异常并删除所有try和catch块,在每个方法后添加throws Exception
:)
答案 1 :(得分:2)
鉴于问题是:
查找表单的所有块:
try { ... }
catch (Exception e) { ... }
带
try { ... }
catch ( T1 e ) { ... }
....
catch ( Tn e ) { ... }
对于所有T1,...这是一个可以进行代码更改的程序转换系统,以及抛出异常的原因,似乎是一个解决方案。
我们的DMS Software Reengineering Toolkit及其Java Front End可能会这样做。
您需要一个可以计算从主块内部抛出的异常集的分析器。您可能还希望根据对象层次结构对这些异常进行分类;如果Tm是Tn的特化,您可能希望为嵌套尝试生成Tm和Tn的处理程序。 DMS具有完整的类型分析,因此它可以确定代码中的类型,并由代码块抛出。人们必须编写自定义DMS代码来计算异常的对象层次结构。
您需要一个调用图,因此可以将调用图中找到的异常传播到try站点。我们有这个,但它需要Java 1.7的一些工作。
您需要转换应用程序,修改代码。我认为你需要担心链接捕获来处理一般情况。使用DMS,它应该看起来像:
rule specialize_catch(b_try: block,
E: qualifed_identifer, e: IDENTIFIER, b_recover: block,
c_pre: catches, c_post: catches):
statement -> statement
" try { \b_try }
\c_pre
catch ( \E \e ) { \b_recover }
\c_post "
->
" try { \b_try }
\c_pre
catch ( \least_specialized\(\E\,\b_try\,\c_pre\) \e ) { \b_recover }
catch ( \E e ) { \b_recover }
\c_post "
if exists_specialized_exception(E,b_try,c_pre);
要转换的语法是* meta * quotes“...”中的代码,以便将其与重写规则的语法分开。重写规则有许多部分。它指定一个名称(我们通常有数百个)。它提供了一组命名占位符(b_try,E,b_recover,...),它们表示目标语言(在本例中为Java)中的特定的,命名的语法形式,并以metaquote和转义(反向)形式之外的裸形式编写在metaquotes里面。 c_pre是一系列catch结构的名称;我们可以这样做,因为“catch”在抽象中形成一个关联列表,类似于c_post。它提供了元函数调用(例如,least_specialized,exists_specialized_exception),它可以调用自定义DMS机器来计算结果(布尔值或新语法[树])。你会注意到对@subspecialized的元函数调用甚至具有元函数调用的语法转义(例如,逗号和括号),因为它们不是Java语言的一部分;在Java代码之外,这样的元函数调用不需要转义。最重要的是,它有一个左侧(“匹配此”,绑定变量)和右侧(如果规则条件为真,则“替换为此”。
元函数least_specialized和exists_specialized将计算,对于主代码块b_try可能抛出的异常,以及由现有捕获c_pre处理的异常,以及当前异常类型E,c_pre之上和E之下的最常见异常,以及插入一个新的catch块。如果不存在,则if失败并且不再进行异常插入。您可能需要添加单个转换来对重复的b_recover块进行解除克隆。
我显然没有实现这一点,可能没有完全考虑过。但我可以将其视为可能解决方案的途径。 YMMV。
我要说700个实例,用DMS做这个可能是非常有限的。如果你个人花了10分钟(编辑,编译,哎呀...)这是7000分钟或~~ 100小时,大约2周。我怀疑你可以配置DMS来快速完成这项工作,特别是以前从未这样做过。 (我公司有专家的DMS用户,这可能是一个可行的时间框架。)
但声称可能存在一种工具。