CleanCode JS - 분기

pds·2022년 11월 26일
0

Cleancode

목록 보기
3/5

클린코드 자바스크립트 강의를 듣고 얻은 정보를 참고하여 기록한 내용입니다.



삼항연산자 사용


다중 분기에는 switch문이 가독성과 유지보수에 좋을 수 있다.

function a() {
	return c1 ? v1 : c2 ? v2 : c3 ? v3 : v4;
}

삼항연산자 사용이 코드는 짧아지지만 과연 알아보기가 좋을까?


읽기 쉽게 구성하자

const a = c1
  ? a === 0
    ? 'zero' : 'positive'
  : 'negative';

const b = c1
  ? ((a === 0) ? 'zero' : 'positive')
  : 'negative';

어떤게 다중조건을 식별하기 좋은지 생각해보자

본인 또는 팀만의 기준을 만들고 읽기 쉽게 구성하자!

숏 코딩만을 위한 삼항연산자는 지양하자


33333333333333333

3 항이라는 것을 잘 생각하여 의도에 맞게 사용할 것

조건에 대해 그리고 거짓 이라는 모든 결과가 필요할 때 사용하자.

그렇지 않은 경우에는 truthy, falsy 를 활용한 short circuit evaluation을 활용하면 좋음

한 조건에 대해 두 경우의 상반된 결과을 리턴시킬 때가 삼항연산자의 사용 의도에 가장 부합할 수 있다.



Truthy Falsy 사용

truthy falsy 를 적절히 활용해 안전하면서도 가독성 높은 간결한 코드를 작성하자!

falsy

0, NaN, '', null, undefined 는 false 로 변경된다.

function helloByName(name) {
//    if(name !== undefined && name !== null) {
//        return "아무도없었다.";    
//    }
	if(!name) {
        return "아무도없었다.";
    }
    return "hi" + name;
}

예를 들어 if(!name)이라는 조건은 undefined, null, 공백 등 비정상적인 값을 모두 의도대로 분기할 수 있다.

단순한 유효성 검사 같은 로직에서는 활용하기 매우 좋고 많은 개발자들이 알고 있는 합의된 방법으로 충분히 소통 가능


short circuit evaluation

truthy falsy를 활용한 단축 평가가 가능하다.

state라는 객체에 fetchedData라는 서버로 부터 얻는 비동기 데이터를 담는 속성이 있습니다.
데이터 패칭이 완료된 경우에는 데이터를 보여주고 그렇지 않으면 로딩중이라는 문구를 리턴해주세요

얼핏 보면 조건에 대한 두가지 처리를 위한 분기를 해야할 것만 같지만

데이터가 없을 수 있다 라는 것을 생각해보면

state라는 객체의 fetchedData라는 키에 아무값도 할당되지 않았다 라는 것을 도출할 수 있다.

// non compliant
function getData1(state) {
	return state.fetchedData ? state.fetchedData : '...loading';
}
// compliant
function getData2(state) {
	return state.fetchedData || '...loading';
}

단축평가는 개인적으로도 많이 쓰는데

익숙해지면 삼항연산자나 if문 보다 훨씬 가독성이 좋고 코드 길이도 간결해져서 좋은 것 같다.

어떤 코드가 보기 더 좋은지 생각해보자!!

function getAuthenticatedUsername(user, isLogin) {
	if(isLogin) {
    	if(user) {
        	if(user.name) {
            	return user.name;
            }
          	return '이름없음';
        }
    }
}

function getAuthenticatedUsername(user, isLogin) {
	if(isLogin && user) {
    	return user.name || '이름없음';
    }
}

// +es2020
function getAuthenticatedUsername(user, isLogin) {
	return isLogin && user?.name || '이름없음';
}


Else, Else If 멈춰!


else if

else if 조건을 사용하는 것 자체가 현재 로직의 어떤 컨디션을 명확하게 정의하고 있지 못하는 상황일 수 있다.

else if 사용 자체를 지양하고 다중 분기가 불가피한 경우 switch 문을 고려할 것.

switch문과 다를 바 없는데 가독성이 후져서 알아보기 힘듬

여러 조건을 처리해야 하는 경우라면 차라리 명확하게 조건을 분리하고 early return 을 사용하자


else

return 을 믿자!

function a() {
	if(val === 1) {
    	return "HI";
    } else {
      // else가 필요할까?
    	return "HELLO";
    }
}

function a() {
  if(val === 1) {
    return "HI";
  }
  return "HELLO";
}

완전히 상반된 결과를 요구할 때 특정 조건과 명확하게 반대되는 (else) 로직으로 처리하는 경우는 괜찮지만

특정 조건에 의해서만 부가적인 역할을 수행하고자 할 경우에는

else 에 의해 반전된 로직으로 처리되어 의도하지 않은 동작을 만들거나 중복된 코드를 만들 수 있다.


// non compliant
function printLog(msg, loggingLevel) {
	if(loggingLevel === 'INFO') {
    	printSomeInfo();
      	printLog(msg);
    } else {
    	printLog(msg);
    }
}


// compliant
function printLog(msg, loggingLevel) {
	if(loggingLevel === 'INFO') {
    	printSomeInfo();
    }
  	printLog(msg);
}

Early Return 적극 활용하기

분기에서 조건을 충족했을 때 즉시 무언가를 리턴시킬 수 있다면 리턴하는 것을 말함.

개인적으로 느끼기에는 특정 분기처리에 대한 동작을 확인할 때 뒤를 보지 않아도 되는 편리함이 있고

들여쓰기 수준을 확 줄여주고 여러 조건들이 명시적으로 나타나 코드 가독성을 확 높여주는 것 같아

자바에서도 늘 애용했다.

강의 예제가 너무너무너무 마음에 들어 그대로 베꼈다.!!



// non compliant
function loginService(isLogin, user) {
	if(!isLogin) {
    	if(!checkToken()) {
        	if(!user.name) {
            	return registerUser(user);
            } else {
            	refreshToken();
              	return 'login success';
            }
        } else {
        	throw new Error("No Token");
        }
    }
}

// compliant
function loginService(isLogin, user) {
  if (isLogin) {
    return;
  }
  if (!checkToken()) {
    throw new Error('No Token');
  }
  if (!user.name) {
    return registerUser(user);
  }
  refreshToken();
  return 'login success';
}

중괄호와 들여쓰기의 지옥을 맛보며 들여쓰기마다 있는 분기의 조건검사를 모두 확인해가며

내부의 내용물을 뜯어보다가 앞의 조건을 까먹어서 다시 볼 것인지

하나하나 조건을 순서대로 체크하고 배제해가며 현재 확인하고자 하는 조건에만 관심을 가지고 볼 것인지

선택하면 될 것 같다!


부정 조건문 지양하기

조건을 보고 생각을 한번 더해야할 수 있다

if (!isNaN(3)) {
  console.log('숫자입니다');  
}

위와 같은 부정조건문(isNaN)이 사용된 코드는 여러 번 생각해야 해서 실수할 수 있기 때문에

명시적으로 긍정조건을 처리하게끔 커스텀 함수를 만드는 것을 고려해보자.

function isNumber(num) {
  return !Number.isNaN(num) && typeof num === 'number';
}

if (isNumber(3)) {
  console.log('숫자입니다');
}

불필요한 추가 분기 처리를 넣어야 할 수 있다.

특정 조건이 충족되었을 경우 에만 무언가를 수행해야 한다고 할 때

부정조건문을 사용한다면 else 를 사용해 첫 if 조건을 충족하지 않는 상황에 대한 처리를 강요하게 되는 상황이 생길 수 있다.

const positive = true;
const not_positive = false;

function a() {
	if(positive) {
    	console.log("항해");
    }
}

function b() {
	if(not_positive) {
    	
    } else {
    	console.log("항해");
    }
}

부정조건문이 유용할 경우

보안관련 처리나 input validation 같은 처리 후 early return 하여 로직 진입을 막고자 할 때


드모르간의 법칙

가독성과 유지보수를 위해 괄호를 벗기자

const isValidUser = true;
const isValidToken = true;

if (isValidToken && isValidUser) {
  console.log('로그인 성공');
}

로그인 성공 확인하는 조건문을

로그인 실패 케이스를 추가로 만든다고 하면, 기존값을 활용하여 아래와 같이 코드를 작성할 수 있다.

if (!(isValidToken && isValidUser)) {
  console.log('로그인 실패');
}

해당 조건 뒤에 연산이 더 붙게 된다면 가독성 떨어질 수 있다.

드모르간의 법칙을 이용해 다음과 같이 구성할 수도 있음

if (!isValidToken || !isValidUser) {
  console.log('로그인 실패');
}
profile
강해지고 싶은 주니어 프론트엔드 개발자

0개의 댓글