
조건문
동일한 값을 비교할 경우
if/else로 작성되면 에러코드에 따른 동작을 파악하기 위해
시선이 Z형태(errorCode -> 211 -> navigate)로 이동되어
한번에 읽기 어렵게 한다.
if (errorCode === 211) {
navigate('/signup')
} else if (errorCode === 208) {
navigate('/user/registration')
} else if (errorCode === 202) {
navigate('/home')
} else if (errorCode === 212 || errorCode === 213) {
navigate('/signup')
} else {
navigate('/login')
}
switch/case로 작성되면 에러코드와 동작이 수직으로 위치하여 시선이 수직으로 이동되어 읽기 쉽게 만든다. 그리고 숫자를 작은 것부터 높은 순서로 작성하고 동일한 동작을 하는 코드는 같이 작성하였다.
switch (errorCode) {
case 202: navigate('/home')
break
case 208: navigate('/user/registration')
break
case 211:
case 212:
case 213: navigate('/signup')
break
default: navigate('/login')
break
}
다른 값을 비교할 경우
조건문에 다른 값들을 비교할 때이다. 결과에 따라 각자 다른 동작을 하고 있다. 일관성이 없기 때문에 읽기 어렵고 이해하기 쉽게 작성되어 있다.
if (error.httpStatus === 0) {
openToast('알 수 없는 오류가 발생했습니다.')
} else if (error.response && error.response.name === 'TimeoutError') {
openToast('타임아웃이 발생했습니다.')
} else if (error.code === 211) {
navigate('/signup')
} else if (error.code === 208) {
navigate('/user/registration')
} else {
navigate('/login')
}
먼저 switch/case를 통해 책임연쇄패턴을 작성하여 조건문과 동작을 동일 시선으로 만들 수 있다.
switch (true) {
case error.httpStatus === 0:
openToast('알 수 없는 오류가 발생했습니다.')
break
case error.response && error.response.name === 'TimeoutError':
openToast('타임아웃이 발생했습니다.')
break
case error.code === 211:
navigate('/signup')
break
case error.code === 208:
navigate('/user/registration')
break
default:
navigate('/login')
break
}
그리고 마지막으로 조건문을 함수로 만들면 일관성있는 코드가 작성되어 이해하기 쉽게 한다.
const isUnknownError = error => error.httpStatus === 0
const isTimeoutError = error => error.response && error.response.name === 'TimeoutError'
const isUnregist = error => error.code === 211
const isUnauth = error => error.code === 208
switch (true) {
case isUnknownError(error):
openToast('알 수 없는 오류가 발생했습니다.')
break
case isTimeoutError(error):
openToast('타임아웃이 발생했습니다.')
break
case isUnregist(error):
navigate('/user/registration')
break
case isUnauth(error):
navigate('/signin')
break
default:
navigate('/login')
break
}
특정 값이 존재할 때 할당하는 경우
응답에러와 응답메시지가 있을 때 메시지변수에 할당을 하고, 둘다 없을 경우 공통 메시지를 할당하는 코드이다. 간단한 코드지만 메세지변수를 let으로 선언하여 변경가능성을 표현하였고, 시선이 한방향으로 흐르지 않고 있다.
let message
if (response.error) {
message = response.error
} else if (response.message) {
message = response.message
} else {
message = COMMON_MESSAGE
}
OR를 통해 작성하면 참일 때 메세지변수에 할당하게 된다. 메세지변수의 불변으로 선언하였고, 시선이 한방향으로 흐르게 하였다.
const message = response.error || response.message || COMMON_MESSAGE
각 인자값 분기
Angular의 HttpParams를 사용하여 쿼리스트링을 만드는 함수이다. 인자의 존재 유무에 따라 파라미터의 추가가 결정된다. 다른 값이 사용되어 각 값마다 분기가 사용되어 로직이 중복된다.
const convertToParams = ({name, status, page, pageSize}) => {
let params = new HttpParams()
if (name) {
params = params.append('name', name)
}
if (status) {
params = params.append('status', String(status))
}
if (page) {
params = params.append('page', String(page))
}
if (pageSize) {
params = params.append('size', String(pageSize))
}
return params
}
결국 이 함수는 여러개의 값을 모아 하나의 값을 만드는 작업을 한다. 이때 reduce를 사용하면 params과 중복된 로직을 삭제할 수 있다.
const convertToParams = ({botName, status, page, pageSize}) => {
return [
['botName', botName],
['status', status],
['page', page],
['size', pageSize],
].reduce((params, [key, value]) => {
if (value) {
params = params.append(key, String(value))
}
return params
}, new HttpParams())
}
이 코드에서도 개선 사항이 있다. 파라미터를 배열로 선언해야 하고, reduce 내부의 작업이 많다. 각 역할에 맞게 선언형 함수를 사용하면 좀 더 개선 가능하다.
const convertToParams = ({botName, status, page, pageSize: size}) => {
return Object
.entries({botName, status, page, size})
.filter(([key, value]) => value)
.map(([key, value]) => [key, String(value)])
.reduce((params, [key, value]) => {
return params.append(key, String(value))
}, new HttpParams())
}
'프런트엔드 > 리팩터링' 카테고리의 다른 글
TDD와 BDD 비교 (0) | 2023.07.19 |
---|---|
레거시 코드 리팩터링 시리즈(5/5) 배열과 반복문 (0) | 2023.07.17 |
레거시 코드 리팩터링 시리즈(3/5) 객체 (0) | 2023.07.17 |
레거시 코드 리팩터링 시리즈(2/5) 스타일과 문구 (0) | 2023.07.17 |
레거시 코드 리팩터링 시리즈(1/5) (0) | 2023.07.17 |