Don't swallow exceptions
Make sure the exceptions are handled and not swallowed. public void notifyOthers() {
try {
List<party> interestedParties = fetchInterestedPartiesFromDb();
} catch (Exception e) {
// do nothing
}
}
private List<party> fetchInterestedPartiesFromDb() throws Exception {
return fetchFromDb(Party.class);
}
private <t> List<t> fetchFromDb(Class<t> partyClass) {
//interact with db
return null;
}
An exception caught must be logged
Make sure the complete exception is logged rather than just logging the message usingException.getMessage().
public void notifyOthers() {
try {
List<party> interestedParties = fetchInterestedPartiesFromDb();
} catch (Exception e) {
LOGGER.severe(e.getMessage());
}
}
Instead of the above, we should simply log the exception object itself so that one can see the entire execution stack.
public void notifyOthers() {
try {
List<party> interestedParties = fetchInterestedPartiesFromDb();
} catch (Exception e) {
LOGGER.severe("Exception " + e);
}
}
Do not catch Throwable
If you catchThrowable even errors will be caught, for example, java.lang.OutOfMemoryError. Below code throws OutOfMemoryError but is caught instead of letting JVM deal with it. Since Throwable is superclass of Error and Exception, it will catch even those errors which indicate serious problem.
![]() |
| Exception hierarchy |
ThrowsOom:
package refactor.clean;
import java.util.logging.Logger;
public class ThrowsOom {
public static void main(String[] args) {
try {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append(i).append(sb);
}
} catch (Throwable t) {
LOGGER.severe("Throwable: " + t);
}
LOGGER.warning("Throwable is caught, replace it with Exception");
}
private static final Logger LOGGER = Logger.getLogger(ThrowsOom.class.getName());
}
Output:
Jan 16, 2017 5:29:56 PM refactor.clean.ThrowsOom main SEVERE: Throwable: java.lang.OutOfMemoryError: Java heap space Jan 16, 2017 5:29:56 PM refactor.clean.ThrowsOom main WARNING: Throwable is caught, replace it with ExceptionCatch
Exception instead of Throwable.
ThrowsOom:
package refactor.clean;
import java.util.logging.Logger;
public class ThrowsOom {
public static void main(String[] args) {
try {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append(i).append(sb);
}
} catch (Throwable t) {
LOGGER.severe("Throwable: " + t);
}
LOGGER.warning("Throwable is caught, replace it with Exception");
try {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append(i).append(sb);
}
} catch (Exception e) {
LOGGER.severe("Exception: " + e);
}
}
private static final Logger LOGGER = Logger.getLogger(ThrowsOom.class.getName());
}
Output:
Jan 16, 2017 5:55:11 PM refactor.clean.ThrowsOom main SEVERE: Throwable: java.lang.OutOfMemoryError: Java heap space Jan 16, 2017 5:55:11 PM refactor.clean.ThrowsOom main WARNING: Throwable is caught, replace it with Exception Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3332) at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:445) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:459) at java.lang.StringBuilder.append(StringBuilder.java:166) at refactor.clean.ThrowsOom.main(ThrowsOom.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Don't throw generic exception
Below method tries to find an existing issue for the passed in IDissueId.
If issue not found throws a RuntimeException.
public static Issue findById(String issueId) throws RuntimeException {
Issue issue = fetchFromDb(issueId);
if (issue == null) {
throw new RuntimeException("Issue not found");
}
return issue;
}
Instead of a generic exception, one can define and throw a dedicated exception.
IssueNotFoundException:
package refactor;
public class IssueNotFoundException extends RuntimeException {
public IssueNotFoundException(String message) {
super(message);
}
}
Fix findById() to throw specific exception.
public static Issue findById(String issueId) throws IssueNotFoundException {
Issue issue = fetchFromDb(issueId);
if (issue == null) {
throw new IssueNotFoundException("Issue not found");
}
return issue;
}
Since the method now throws specific exception, the calling methods can handle the exception
based on its type.
IssueAlreadyResolvedException:
IssueAlreadyResolvedException:
package refactor;
public class IssueAlreadyResolvedException extends Exception {
public IssueAlreadyResolvedException() {
super("Issue already resolved");
}
}
public void resolve(String issueId) throws IssueAlreadyResolvedException {
Issue issue;
try {
issue = Issue.findById(issueId);
} catch (IssueNotFoundException e) {
return;
}
if (issue.isResolved()) {
throw new IssueAlreadyResolvedException();
}
issue.resolve();
}

No comments:
Post a Comment