[英]Refactoring a method which is calling others methods that throws Exception
我有幾個(超過20個)方法( getXXX()
),在調用它們時可能會引發異常( NotCalculatedException
)。
在另一種方法中,我需要訪問這些方法給出的結果。 目前,我有一個可怕的代碼,看起來像:
public void myMethod() {
StringBuffer sb = new StringBuffer();
// Get 'foo' result...
sb.append("foo = ");
try {
sb.append(getFoo());
} catch (NotCalculatedException nce) {
sb.append("not calculated.");
}
// Get 'bar' result...
sb.append("\nbar = ");
try {
sb.append(getBar());
} catch (NotCalculatedException nce) {
sb.append("not calculated.");
}
...
}
在不修改getXXX
方法的情況下 (因此,它們必須保持throws NotCalculatedException
),如何重構/簡化myMethod()
使其看起來更好?
請注意,該項目仍在使用Java 1.4 :(
編輯
我無法將所有getXXX()
方法都放在try { ... }
塊中,因為如果一個方法拋出NotCalculatedException
,則StringBuffer將不完整。
public void myMethod() {
StringBuffer sb = new StringBuffer();
try {
sb.append("foo = ");
sb.append(getFoo());
sb.append("\nbar = ");
sb.append(getBar());
} catch (NotCalculatedException nce) {
sb.append("not calculated.");
}
...
}
換句話說,如果getFoo()
拋出NotCalculatedException
,我想要這種輸出:
foo = not calculated
bar = xxx
...
如果將所有內容放在一個單獨的try { ... }
,我將獲得該輸出,但我不想得到:
foo = not calculated
我認為您不應該使用NotCalculatedException來控制邏輯。
但是我對此有一些想法。
您需要另一種吸氣方法
sb.append(this.getFoo(“未計算”)));
創建hasValue方法
sb.append(hasFoo()?this.getFoo():“未計算”);
創建一個通用的getter方法
sb.append(this.getValueByName( “富”));
對於每個getXXX
您都可以添加一個getXXXOrDefault()
來包裝異常,並返回getXXX
或“未計算”的值。
public void myMethod() {
StringBuffer sb = new StringBuffer();
// Get 'foo' result...
sb.append("foo = ");
sb.append(getFooOrDefault());
// Get 'bar' result...
sb.append("\nbar = ");
sb.append(getBarOrDefault());
// ...
}
public Object getFooOrDefault() {
try {
return getFoo();
} catch() {
return "not calculated.";
}
}
或者...使用反射
public Object getValueOrDefault(String methodName) {
try {
// 1 . Find methodName
// 2 . Invoke methodName
} catch() {
return "not calculated.";
}
}
但我認為我仍然更喜歡第一選擇。
我的建議是增加代碼,但提高myMethod的可讀性:
public void myMethod() {
StringBuilder resultBilder = new StringBuilder();
resultBuilder.append("foo=");
appendFooResult(resultBuilder);
resultBuilder.append("\nbar=");
appendBarResult(resultBuilder);
...
}
private void appendFooResult(StringBuilder builder) {
String fooResult = null;
try {
fooResult = getFoo();
} catch (NotCalculatedException nce) {
fooResult = "not calculated.";
}
builder.append(fooResult);
}
private void appendBarResult(StringBuilder builder) {
String barResult = null;
try {
barResult = getBar();
} catch (NotCalculatedException nce) {
barResult = "not calculated.";
}
builder.append(barResult);
}
我認為您應該將代碼保持原樣。 它很冗長,但是很容易分辨它的作用,並且行為正確。
您可以使用Execute Around成語。 不幸的是,Java語法很冗長,因此在簡單情況下並不是什么大好事。 假設NotCalculatedException
是一個未經處理的異常。
appendThing(sb, "foo = ", new GetValue() { public Object get() {
return getFoo();
}});
appendThing(sb, "bar = ", new GetValue() { public Object get() {
return getBar();
}});
另一種丑陋的方法將循環和切換結合在一起:
int property = 0;
lp: for (;;) {
String name = null; // Ugh.
try {
final Object value;
switch (property) {
case 0: name= "foo"; value = getFoo(); break;
case 1: name= "bar"; value = getBar(); break;
default: break lp;
}
++property;
sb.append(name).append(" = ").append(value).append('\n');
} catch (NotCalculatedException exc) {
sb.append(name).append(" = ").append("not calculated.\n");
}
}
另外,每個參數都有一個枚舉和一個開關。 只是不要使用反射!
似乎Java沒有像C#-這樣的開箱即用的代理,但是Google向我展示了可以使用自己的代理的方法 。 因此,以下可能是可以嘗試的方法。
public static PrintProperty(JavaDelegateWithAName del, StringBuilder collector)
{
try
{
collector.append( del.Name+ " = " );
collector.append( del.Target.Invoke() );
}
catch(NotCalculatedException nce)
{ collector.append("NotCalculated"); }
}
...主要
foreach(JavaDelegateWithAName entry in collectionOfNamedJavaDelegates)
SomeUtilityClass.PrintProperty(entry, sb);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.