Not an anti-pattern per se, but a code pattern that tells you need to refactor.
And it's pretty easy, you just have to know a rule of thumb which is writing no more than a try block in the same method. If you know well to write related code together, usually is just copying and pasting each try block with its catch blocks and pasting it inside a new method, and then replace the original block with a call to this method.
This rule of thumb is based on Robert C. Martin's suggestion from his book 'Clean Code':
if the keyword 'try' exists in a function, it should be the very first
word in the function and that there should be nothing after the
catch/finally blocks.
A quick example on "pseudo-java". Suppose we have something like this:
try {
FileInputStream is = new FileInputStream(PATH_ONE);
String configData = InputStreamUtils.readString(is);
return configData;
} catch (FileNotFoundException e) {
try {
FileInputStream is = new FileInputStream(PATH_TWO);
String configData = InputStreamUtils.readString(is);
return configData;
} catch (FileNotFoundException e) {
try {
FileInputStream is = new FileInputStream(PATH_THREE);
String configData = InputStreamUtils.readString(is);
return configData;
} catch (FileNotFoundException e) {
return null;
}
}
}
Then we could refactor each try catch and in this case each try-catch block tries the same thing but in different locations (how convenient :D), we have only to copy paste one of the try-catch blocks and make a method of it.
public String loadConfigFile(String path) {
try {
FileInputStream is = new FileInputStream(path);
String configData = InputStreamUtils.readString(is);
return configData;
} catch (FileNotFoundException e) {
return null;
}
}
Now we use this with the same purpose as before:
String[] paths = new String[] {PATH_ONE, PATH_TWO, PATH_THREE};
String configData;
for(String path : paths) {
configData = loadConfigFile(path);
if (configData != null) {
break;
}
}