명확한 조건 선택하기
긍정조건 사용하기
//bad
const isNotBoy = false;
//good
const isBoy = true;
// ! 표기가 잘보이지 않고 부정의 부정이라 조건문을 잘못 해석할 여지가 다분함
if(!isNotBoy){}
if(isBoy){}
꼭 부정문을 사용해야할때는??
조건문에 이름 붙이기
const isBoy = !isNotBoy // if 문 바로 상단에서 긍정 조건으로 변경해주기!
if(isBoy){}
함수를 통해서 조건을 사용하자
//bad
if(name === 'js'
&& obj.someProperty.title === "sparta"
&& height < 180) {...}
//good
const isJsTutor = name === 'js' && obj.someProperty.title === "sparta"
|| height < 180;
if(isJsTutor) {...}
만약 아주 복잡한 조건문에 맞닥드렸다면? 그리고 이 조건이 언제든 변경의 여지가 남아있다면?
//bad
if(name === 'js'
&& obj.someProperty.title === "sparta"
&& height < 180
|| lastName === 'lee') {...} // 근데 다음에 몸무게도 추가될지도 몰라요~
//good
const checkThisDataValid = ({name, title, hegiht, lastName})=>{
let result = true;
... // 비지니스 로직
return result;
}
if(checkThisDataValid()) {...}
조건문의 성능은 생각하지 말자
- 10개의 조건을 2개로 줄인다면 성능상으로 얼마나 이득일까요? 티도 나지 않는 적은 양입니다.
- 조건문을 압축하지 마세요. 시간이 지나면 너무나 압축된 조건문을 다시 해석하느라 시간을 많은 시간을 써야할 가능성이 높아요.
- 조건문을 최적화하려고 하기보다는 이름을 명확하게 지어줌으로써 보기 좋고 읽기 편하게 변경합시다.
조건, 반복 depth 지옥
- if문을 작성할 때, 가장 주의할 점은 깊이(Deep)입니다.
- 이중(if 안에 if), 삼중, N 중 중첩문을 가장 기피해야 합니다. 가능하다면 최대한 깊이가 1인 분기문을 작성하는 것이 좋습니다.
- 이럴때 사용하는 패턴이 Guard Clause 인데, 우리에게는 early return 이라는 이름으로 더 익숙한 패턴입니다.
- 사전 조건이 판별하여 거짓이라면 예외 혹은 반환 처리하여 더 이상 다음 단계가 실행되지 않도록 사전에 차단하는 방식입니다.
- 이 방식을 제대로만 사용한다면 정말 좋은 조건문을 작성할 수 있게됩니다.
// bad
async function guardClause(userId) {
const user = await getUser(userId);
if (user) {
const orders = await getOrders(user);
if (orders && orders.length > 0) {
const order = orders.find(order => order.value > 100);
if (order) {
// 실제 처리할 로직
console.log(`Found an order from user ${user.id} with value greater than 100: ${order.id}`);
}
}
}
}
// good
async function guardClause(userId) {
const user = await getUser(userId);
if (!user) return;
const orders = await getOrders(user);
if (!orders || orders.length === 0) return;
const order = orders.find(order => order.value > 100);
if (!order) return;
// 실제 처리할 로직
console.log(`Found an order from user ${user.id} with value greater than 100: ${order.id}`);
}
object mapping
- if 문을 효과적으로 줄여주기 위해서 우리는 Object Mapping 방식도 사용해 볼 수 있습니다.
function loginWithKakao() {}
function loginWithGoogle() {}
function loginWithApple() {}
// switch
const socialLogin = (social) => {
switch (social) {
case "kakao":
loginWithKakao();
case "google":
loginWithGoogle();
case "apple":
loginWithApple();
}
};
//obj mapping
const socialMapper = {
kakao: loginWithKakao,
google: loginWithGoogle,
apple: loginWithApple,
};
const socialLogin = (social) => {
socialMapper[social]();
};
import img1 from '...'
import img2 from '...'
import img3 from '...'
import img4 from '...'
import img5 from '...'
import img6 from '...'
let imgSrc;
if(imgId === 1){imgSrc = img1}
if(imgId === 2){imgSrc = img2}
if(imgId === 3){imgSrc = img3}
if(imgId === 4){imgSrc = img4}
if(imgId === 5){imgSrc = img5}
if(imgId === 6){imgSrc = img6}
//imgMapper.js
export const imageMapper = {
1:img1,
2:img2,
3:img3,
4:img4,
5:img5,
6:img6,
}
// 사용처
let imgSrc = imgMapper[imgId];
early return 을 쓸때는 몇가지 주의할 점이 있는데요.
함수의 일관성이 떨어질 수 있습니다.
- Early return은 먼저 리턴을 시켜버림으로써 함수의 흐름을 분산시킬 수 있기 때문에, 함수의 일관성을 해칠 수 있습니다.
- 즉, 함수를 읽는 사람이 어떤 조건에서 반환이 일어나는지를 정확히 이해하고 추적할 수 있어야 합니다.
- 말 그대로 early return 이기때문에 뒤에 무언가 새로운 비지니스 로직이 있다는 암시가 될 수 있습니다.
- 단순히 return; 만 작성할 경우 함수는 원하는 값이 아닌 undefined 을 반환하게 됩니다.
- 반환값이 없는 void 함수일때는 문제가 없겠지만 필요한 반환값이 존재할 경우 원치 않는 undefined 을 반환하게 되고 만약 undefined check 를 외부에서 하지 않으면 오류가 발생하겠죠?
- 그럴때 사용하는 방법이 initial value 초기값을 할당해 주는 방법입니다.
function calculateTotalPrice(items) {
// 초기값 설정
let totalPrice = 0;
if (!items || items.length === 0) {
return totalPrice;
}
items.forEach(item => {
totalPrice += item.price * item.quantity;
});
return totalPrice;
}
이렇게 명확한 초기값을 할당해주게 되면 반환값이 꼭 필요한 함수의 경우 만약 내부 조건문이 잘못되어서 이상한 값을 받는다 하더라도 undefined 로 부터 초래되는 문제는 방지할 수 있겠죠?
무분별하게 early return 을 사용하지 않도록 return 을 작성할때에는 신중하게 하는 것이 좋습니다!
'Clean Code' 카테고리의 다른 글
클린코드 - PR 리뷰 할 때 활용하기 (1) | 2023.11.22 |
---|---|
클린코드 - 코드 퀄리티 & 가독성 올리기 (1) | 2023.11.22 |
클린코드 - 추상화와 구체화 (1) | 2023.11.22 |
클린코드 - 의미 있는 변수명 짓기 (0) | 2023.11.21 |
클린코드 - 클린 코드는 무엇이고 왜 써야 하는가? (0) | 2023.11.21 |