컴파일 에러 처리 방식은 모든 에러를 개발자가 해소해주기 때문에 번거롭다.
RuntimeException을 잘 사용하자
if (name == null) {
throw new IllegalArgumentException("이름이 Null일 수 없습니다.");
}
if (name.isEmpty()) {
throw new IllegalArgumentException("이름이 빈 값 일 수 없습니다.");
}
if (name.isBlank()) {
throw new IllegalArgumentException("이름에 공백만 존재할 수 없습니다.");
}
if (name.length() > 5) {
throw new IllegalArgumentException("이름의 길이는 5자를 넘을 수 없습니다.");
}
위 코드가 나을까
if (name == null || name.isBlank() || name.length() > 5) {
throw new IllegalArgumentException("유저 생성에 실패했습니다.");
}
return new User(name);
위 코드가 나을까?
static class MalformedUserNameException extends IllegalArgumentException {
class OldVendingMachine extends VendingMachine {
@Override
Item selectItemByName(final String name) {
if (ThreadLocalRandom.current().nextBoolean()) {
throw new IllegalStateException("아이템을 뽑는 데 실패했습니다.");
}
return super.selectItemByName(name);
}
}
final class CustomVendingMachine extends OldVendingMachine {
@Override
Item selectItemByName(final String name) {
try {
return super.selectItemByName(name);
} catch (final IllegalStateException e) {
return selectItemByName(name);
}
}
}
위와 같이 문제가 생기는 로직에서 throw 한다면, 상위 객체에서 이를 catch해서 문제가 생기지 않는 코드가 나올때까지 호출해주면 된다.
핵심은 문제가 생겼을때 책임을 해당 객체에서 진다는 것.
복구가 아닌 회피
final class CustomVendingMachine extends OldVendingMachine { @Override Item selectItemByName(final String name) { return super.selectItemByName(name); } }만약 위와같이 예외를 처리하지않고 그냥 사용한다면 회피하는 것이 된다.
책임을 외부에 준다는 것은 책임이 새어나가는 것이기 때문에 지양하는 것이 좋겠다.
try {
final var item = vendingMachine.selectItemByName(name);
soldItems.add(item);
} catch (final IllegalStateException e) {
throw new IllegalStateException("자판기 회사에 문의하세요.", e);
}
void orderFromVendingMachine(final String name) {
try {
final var item = vendingMachine.selectItemByName(name);
soldItems.add(item);
} catch (final IllegalStateException ignored) {
// Note: 의도된 무시기 때문에 문제가 있는 코드가 아니다.
}
}
우테코에서 제공되는 코드를 많이 참고하자..
몰랐던 좋은 문법들이 많다..
ex) final class, var
테스트 코드 작성 방법 등