0. 기존코드
export const bmiTypeCalculation = (height: number, weight: number): string => {
const currentBMI = weight / ((height / 100) * (height / 100));
let bmiType: string;
if (currentBMI < 14.99) {
bmiType = 'muscular';
} else if (currentBMI >= 15 && currentBMI < 19.99) {
bmiType = 'slim';
} else if (currentBMI >= 20 && currentBMI < 24.99) {
bmiType = 'normal';
} else {
bmiType = 'fat';
}
return bmiType;
};
프로젝트를 보니 위처럼 화살표함수 써서 리턴시키고 분기를 If/else로 나눠서 처리했었다.
이는 구간별로 분기처리가 되어있었다. BMI 지수가 범위로 되어있기 때문에 그랬던것 같다.
이 분기문을 리팩토링 해보자
1. SWITCH - CASE 로 변경
export const bmiTypeCalculation = (height: number, weight: number): string => {
const currentBMI = Math.floor(weight / ((height / 100) * (height / 100)));
switch (currentBMI){
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
case 8:
case 7:
case 6:
case 5:
case 4:
case 3:
case 2:
case 1:
case 0:
bmiType = 'muscular';
break;
case 19:
case 18:
case 17:
case 16:
case 15:
bmiType = 'slim';
break;
case 24:
case 23:
case 22:
case 21:
case 20:
bmiType = 'normal';
break;
default:
bmiType = 'fat';
}
return bmiType;
};
변경점
1. 정수로 변경하면 문자열로 변경하고 소수점까지 비교할 필요가 없음
2. 15 미만은 근육몬 / 15~19는 마름 / 20~24는 보통 / 그 이상은 뚱뚱함으로 수정
2. SWITCH - CASE 수정 1
export const bmiTypeCalculation = (height: number, weight: number): string => {
const currentBMI = weight / ((height / 100) * (height / 100));
const MUSCULAR_MAX = 15;
const SLIM_MAX = 20;
const NORMAL_MAX = 25;
switch (true) {
case currentBMI < MUSCULAR_MAX:
bmiType = 'muscular';
break;
case currentBMI < SLIM_MAX:
bmiType = 'slim';
break;
case currentBMI < NORMAL_MAX:
bmiType = 'normal';
break;
default:
bmiType = 'fat';
}
return bmiType;
};
변경점
1. 상수 정의 : 매직넘버로 작성된 숫자들을 의미있는 이름의 상수로 정의하여 각 BMI 분류의 최대값을 저장한다.
2. switch-case : 각 case 에서 상수를 이용하여 BMI가 해당 범위 이하인지 확인한다.
3. switch (true) 로 수정 : currentBMI 값을 비교하는 것이 아니라 코드 분류를 위한 논리적 흐름 제어 목적으로 변경
4. Math.floor()를 제거 : 값이 변경되어 실제 BMI 값으로 비교되도록해서 의도치않은 결과를 일으키지 않도록 수정
3. SWITCH - CASE 수정 2
1번에 이어서 추가적으로 수정해보자.
export const bmiTypeCalculation = (height: number, weight: number): string => {
const currentBMI = weight / ((height / 100) * (height / 100));
const MUSCULAR_MAX = 15;
const SLIM_MAX = 20;
const NORMAL_MAX = 25;
switch (true) {
case currentBMI <= MUSCULAR_MAX:
return 'muscular';
case currentBMI <= SLIM_MAX:
return 'slim';
case currentBMI <= NORMAL_MAX:
return 'normal';
case currentBMI > NORMAL_MAX:
return 'fat';
};
};
변경점
1. default 제거 : 범위를 지정한 상수로 모든 case 처리가 가능해짐
2. break -> return으로 수정
break를 감싸고 있는 루프를 빠져 나가고 함수 밖으로는 나가지 않는다.
return은 함수 실행을 종료하고 함수를 호출한 곳으로 실행 흐름을 옮긴다.
그래서 return으로 수정하였다.
4. 범위를 객체로 추출해서 관리
export const bmiTypeCalculation = (height: number, weight: number): string => {
const currentBMI = Math.floor(weight / ((height / 100) * (height / 100)) / 5 );
const TypeMap = {
0: 'muscular',
1: 'muscular',
2: 'muscular',
3: 'slim',
4: 'normal'
}
return TypeMap[currentBMI] ?? 'fat';
};
변경점
1. 객체로 분류 : 15,20,25는 5로 나뉘어 떨어진다. 그럼 키값으로 3,4,5를 기준으로 관리하면 switch/case 문을 관리할 수 있다.
2. nullish coalescing operator : 키값이 없을경우(null이나 undefined인 경우) fat을 리턴한다.
5. enum을 사용해서 관리
TypeMap 객체안에 0,1,2 키값에 muscular가 반복되서 나와서 보기가 좀 그렇다.
이를 개선해보자.
enum BMIType {
Muscular,
Slim,
Normal,
Fat
}
const bmiTypeCalculation = (height: number, weight: number): string => {
const currentBMI = Math.floor(weight / ((height / 100) * (height / 100)) / 5);
const bmiType = currentBMI <= 2 ? BMIType.Muscular : currentBMI <= 3 ? BMIType.Slim : currentBMI <= 4 ? BMIType.Normal : BMIType.Fat;
return BMIType[bmiType];
};
변경점
1. BMIType 수정 : typeMap 객체를 enum으로 바꾸어서 파싱하도록 함
2. 삼항연산자를 사용해 조건부 연산
후기
이후로 함수를 모듈화해서 더 작게 쪼갤 수 있겠지만, 또다시 활용할 수 있어보이지는 않아서 그만뒀다.
switch - case 까지 사용한 1~3번까지가 깔끔했던 것 같고 4~5번부터는 뭔가 억지로 진행한것 같기도 하다.
코드를 너무 억지로 리팩토링하려 하지말고 적당히 보기좋게까지만 하면 될것 같다.
참고
FE 재남 if-else 리펙토링 유투브 : https://www.youtube.com/watch?v=p0YEviesgRM
'JaveScript > ExpressJS' 카테고리의 다른 글
async/await 를 Promise.allSetted로 리팩토링하기 (0) | 2024.03.31 |
---|---|
유효성검사 중복코드 리팩토링하기 (0) | 2024.03.26 |
Redis로 Refresh Token 관리 (1) | 2024.01.15 |
ExpressJS와 ChatGPT 연동 (2) (1) | 2023.12.26 |
ExpressJS와 ChatGPT 연동 (1) (2) | 2023.12.18 |