김시용
1. 📌 핵심 개념 정리
✅ 요약하기
각자 해당 챕터에서 중요하다고 느낀 개념이나 아이디어를 간략하게 정리하고 개선 전, 후에 대한 예시 코드를 비교하며 개념을 설명합니다.
- 오류 코드보다 예외를 사용
오류 코드 사용할 때는 if-else로 오류 처리해서 가독성이 떨어져 호출자 코드가 복잡해진다.
예외를 사용시, 동작과 오류 처리를 분리하여 가독성을 높인다.
- try-catch-finally
예외가 발생할 코드를 짤 때는 try-catch-finally 문으로 시작하자.
try 블록에서 무슨 일이 생기든지 호출자가 기대하는 상태를 정의하기 쉬워진다.
작성 tip. 강제 예외 테스트 케이스 작성 -> 테스트 통과하게 코드를 작성하기
- 미확인 예외 사용
확인된 예외는 OCP (Open Closed Priciple) 위반한다. 상위 함수가 하위 함수를 호출이 반복되는 구조에서 최하위 함수에서 새로운 오류가 발견되면 그 상위 함수들 모두에 catch 혹은 throw를 수정해야 한다.
근데 여기서 확인된 예외를 사용하면 최하위 함수의 새로운 오류를 알아야하는데 여기서 캡슐화가 깨진다.
- 예외 클래스 활용
LocalPort 클래스 처럼 ACMEPort를 감싸는 클래스 유용함.
외부 API를 감싸면 외부 라이브러리와 프로그램 사이 의존성이 크게 줄어든다. 다른 라이브러리로 교체하는데 비용이 적게들고 테스트도 쉬워짐
- 변경전
ACMEPort port = new ACMEPort(12);
try {
port.open();
} catch (DeviceResponseException e) {
reportPortError(e);
} catch (ATM1212UnlockedException e) {
reportPortError(e);
} catch (GMXError e) {
reportPortError(e);
} finally {
...
}
- 변경 후
public class LocalPort {
private ACMEPort innerPort;
public LocalPort (int portNumber) {
innerPort = new ACMEPort(portNumber);
}
public void open() {
try {
port.open();
} catch (DeviceResponseException e) {
reportPortError(e);
} catch (ATM1212UnlockedException e) {
reportPortError(e);
} catch (GMXError e) {
reportPortError(e);
} finally {
...
}
}
- 정상 흐름 이용
특수 사례 패턴 활용하기 -> 특수 상황을 처리할 필요가 없다면 코드가 훨씬 간결해진다.
- 변경 전 : 식비를 비용으로 청구했다면 직원이 청구한 식비를 총계에 더한다. 식비를 비용으로 청구하지 않았다면 일일 기본 식비를 총계에 더한다.
try {
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} cathch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
- 변경 후 : ExpenseReportDA0를 고쳐 언제나 MealExpense 객체를 반환하게 하여 예외 처리 없애기
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
public class PerDiemMealExpenses implements MealExpenses {
public int getTotal() {
// 기본값으로 일일 기본 식비를 반환
}
}
- null 반환, 전달 하지마라
null을 반환하는 코드는 예외처리 일거리만 늘어날 뿐 -> 호출자에게 문제를 떠넘김 -> null 반환 대신 빈 리스트를 반환하는 등 null 반환 안해서 예외처리 줄이기.
null을 전달하게 되면 null을 전달 받는 곳에 예외 처리가 늘어남 -> 애초에 null 전달을 방지하기.
2. 🤔 이해가 어려운 부분
🔍 질문하기
책을 읽으며 이해하기 어려웠던 개념이나 명확하지 않았던 내용을 정리합니다.
- 예외 클래스 활용
- 어려웠던 부분
예시를 보고도 예외 클래스 활용의 장점이 와닿지 않는다. - 궁금한 점
어디서 무엇이 장점인지 살펴보기- 외부 라이브러리와의 의존성 줄이기
원래 코드에서 ACMEPort를 직접 사용함 (ACMEPort 바뀌면, 코드 전반적으로 영향을 줌) -> LocalPort를 만들어 감싸면 ACMEPort가 바뀌어도 LocalPort의 내부 코드만 수정하면 됨 - 다른 라이브러리로 교체 쉬워짐
ACMEPort 대신 NewPort로 바꾸려면 ACME 사용된 모든 부분 바꿔야 함
-> LocalPort 사용하면 내부에서만 바꾸면 됨 - 예외 처리 통합
기존에는 예외 처리를 ACMEPort를 사용하는 모든 곳에서 해줘야 함
-> LocalPort가 예외를 한 곳에서 처리해주면 됨. 예를 들어, LocalPort 안에서 공통 예외 처리 후 RuntimeException으로 감싸서 던질 수도 있음. - 테스트 쉬워짐
기존 코드에서는 ACMEPort를 직접 테스트해야 함
-> LocalPort를 사용하면, ACMEPort를 가짜(Mock)로 바꿔서 테스트할 수 있음
- 외부 라이브러리와의 의존성 줄이기
public class FakePort extends LocalPort { public void open() { // 테스트용 가짜 구현 } }
- 어려웠던 부분
No Comments