찰쓰 코치님, 병현님, 윤몬님, 한솔님, 나 5명 참여
1시간 5분 토론
책 157페이지
내 이야기가 전하는 교훈은 다음과 같다. 테스트 코드는 실제 코드 못지 않게 중요하다.
프론트에 TDD를 적용하려는 노력
- 한계: 테스트 커버리지를 어디까지 할 것인가?
- 회사에서는 빨리 '구현'이 중요하다.
- 그래도 테스트를 진행하기 위해 나름의 범위를 정함
=> util성 함수까지만 테스트- UI를 위한 E2E 테스트도 도입
- 하지만 이건 관리할 시간이 부족
- page of object pattern(?) 사용
- 페이지 단위로 클래스를 넣어서 테스트를 작성했더니 assert문이 많았는데 줄어들었다.
TDD (테스트 주도 개발) 방식
- 우선 실패하는 테스트 코드를 먼저 짠다.
- 이후 이 테스트가 성공하는 코드를 짠다.
- 테스트 코드를 바탕으로 실제 구현을 진행한다.
TDD가 잘 되려면?
- 탄탄한 기획이 뒷받침 되면 테스트가 수월해짐 (시간적 여유 확보, 테스트 단위 잡기 좋음 등)
- mock 데이터가 많으면 테스트가 수월해짐
=> 결국 TDD가 지속되고 잘 되려면 개발팀 뿐만 아니라 전 조직 단위의 지원(예: 기획팀)이 필요하다. 다른 직무에도 TDD의 필요성을 공감하게 하고 성과를 공유하려는 노력 필요
책 139페이지
null을 반환하지 마라
try/catch의 throw로 에러를 처리하면 좋은 점
- 관심사를 모아서 처리
- null보다는 더 전략적인 에러 처리
책 138페이지
예제를 살펴보자. 다음은 비용 청구 애플리케이션에서 총계를 계산하는 허스한 코드다. (코드)
책 코드 인용
try{
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
} catch(MealExpensesNotFound e) {
m_total += getMealPerDiem();
}
위의 코드를 더 간결하게 표현하면 아래와 같다.
MealExpenses expenses = expenseReportDAO.getMeals(employee.getID());
m_total += expenses.getTotal();
ExpenseReportDAO를 고쳐 언제나 MealExpense 객체를 반환하고, 청구한 식비가 없다면 일일 기본 식비를 반환하는 MealExpense 객체를 반환한다.
public class PerDiemMealExpenses implements MealExpenses{
public int getTotal(){
// 기본값으로 일일 기본 식비를 반환한다.
}
}
그러나 expenseReportDAO는 MealExpenses를 상속 받는 것이지 PerDiemMealExpenses를 상속 받는 것이 아니기 때문에 기본 식비를 반환하지 못하는게 아닌지, 위 코드들에 대한 의논이 필요해보인다.
(여기는 무슨 말인지 몰라서 오가는 얘기를 거의 이해하지 못함)
토론 중 노션에 추가된 코드
class expenseReportDAO {
public getMeals(id) {
res = repository.get(id)
if res === null {
// throw MealExpensesNotFound;
// return 1;
return new PerDiemMealExpenses(); // 요거를 PerDiemMealExpenses 요거로 대체하고 싶었던 거 아닐까요?
}
return res; // MealExpense
}
}
class PerDiemMealExpenses implements MealExpense {
DEFAULT = 1;
public int getTotal() {
return DEFAULT;
}
}
책 141페이지
어떻게 고치면 좋을까? 다음과 같이 새로운 예외 유형을 만들어 던지는 방법이 있다. (코드)
MetricsCalculator
메서드의 예외 처리 코드에서 예외 처리하는 조건 명시와 그에 따른 예외 처리를 먼저 실행하고 마지막에 return
을 하고 있다.노션에 추가된 코드
public class MetricsCalculator
{
public double xProjection(Point p1, Point p2) {
if (p1 != null && p2 != null) {
return (p2.x - p1.x) * 1.5;
} else {
throw InvalidArgumentException(
"Invalid argument for MetricsCalculator.xProjection"
);
}
}
}
마지막 결론
Early Return은 들여쓰기를 줄여 코드를 간결하고 읽기 쉽게 만드는 좋은 방법입니다. 그러나 이 방법이 매번 적용될 수 있다는 의미는 아닙니다.
때때로 Early Return은 함수의 복잡도를 증가시키고 코드를 더 복잡하게 만들 수 있습니다. 그리고 리뷰어의 의견에서처럼, 간결한 코드에서는 오히려 if-else문이 더 명확할 수 있습니다.
따라서, 읽기 쉬운 코드를 작성하기 위해서는 상황에 맞게 적절한 패턴을 선택하는 것이 중요합니다. 무조건적인 Early Return보다는 맥락을 고려해야 합니다.