if를 쓰지 않는 방식

YI Eun Gook·2020년 6월 27일
1
post-thumbnail

if의 남용을 경계하며, 상태를 배제하는 방식으로 구현하기.. 를 이야기 해보려고 합니다.

1. 상태가 있는 구현 해보기

백오피스의 검색 폼을 같이 만들어볼까요?
보통 기간 검색이 들어가게 되죠. 시작일~종료일
그리고 사용 편의를 위해 1일, 3일, 1주일, .. 이런 느낌으로 버튼이 추가됩니다. 이런 느낌일까요?

<form id="form">
  <input type="date" name="startDt" /> ~
  <input type="date" name="endDt" />
  <input type="text" name="keyword" />
  <br /><br />
  <button type="button">1일</button>
  <button type="button">3일</button>
  <button type="button">1주일</button>
  <button type="button">1달</button>
</form>

여기에 액션을 붙인다면 이런 느낌이 될 것 같아요

// <button type="button">1일</button>
// <button ...

function onclickDate(prev) {
  const today = new Date();
  const day = (1000 *60 * 60 * 24); // ms * s * min * hour
  const startDt = new Date(today.getTime() + (day * prev));
  form.startDt.value = formatDate(startDt);
  form.endDt.value = formatDate(today);
};

function formatDate(date) { /* 생략! */ };

여기서 기획이 추가되어, 1달 버튼을 누를 경우 <1달 검색은 최대 1만건까지만 지원합니다.> 라는 얼럿을 띄워보죠

function onclickDate(prev) {
  /* 생략 1 */
  const aMonth = (prev == -30);
  if (aMonth) { // 1달 버튼을 누를 경우
    alert('1달 검색은 최대 1만건까지만 지원합니다.');
  }
}

그리고 다시 기획이 추가되어, 1달 버튼에서는 키워드 검색을 지원하지 않으며, visible하게 보여주기 위해 폼의 내용도 삭제해주세요. 를 구현해 봅니다.

function onclickDate(prev) {
  /* 생략 1 */
  /* 생략 2 */
  if (aMonth) { // 1달 버튼을 누를 경우
    form.keyword.value = ''; // clear
  }
}

또다시 기획이 추가되어 (놀랄 일은 아니죠?) 사용자의 권한을 체크하여 1달 버튼의 권한이 없을 경우 얼럿과 함께 사용을 제한해주세요. 를 구현해야 하고.. 여기까지만 할게요! 😗

왜냐면 우리는 얼마든지 if문을 만들 수 있고, 얼마든지 구현해낼 수 있으니까요. 이번에는 if를 쓰지 않는 방식으로 해볼까 합니다.

2. 상태가 없는 구현 해보기

그러니까 이런 느낌이 됩니다.

function onclickYesterday() {
  const today = new Date();
  const day = (1000 *60 * 60 * 24); // ms * s * min * hour
  const yesterday = new Date(today.getTime() - day);
  form.startDt.value = formatDate(yesterday);
  form.endDt.value = formatDate(today);
};

function onclick3DaysAgo() {
  const today = new Date();
  const day = (1000 *60 * 60 * 24); // ms * s * min * hour
  const threeDaysAgo = new Date(today.getTime() - (3 * day));
  form.startDt.value = formatDate(threeDaysAgo);
  form.endDt.value = formatDate(today);
};

function onclickAWeekAgo() {
  /* 이후 생략 */

수정해야 할 것 같다 그죠? 잠시만요ㅎㅎㅎㅎㅎ 이제 아까 이야기가 나왔던 1달 버튼의 추가 기능들을 작업해보면 아래와 같은 느낌이 될거에요.

function onclickAMonthAgo() {
  const isAuth = Auth.hasAuth('a_month_ago'); // 권한 a_month_ago: 한 달 버튼
  if (isAuth == false) {
    alert('사용 권한이 없습니다.');
    return false; // early return
  }
  
  alert('1달 검색은 최대 1만건까지만 지원합니다.');
  form.keyword.value = '';
  
  const today = new Date();
  const day = (1000 *60 * 60 * 24); // ms * s * min * hour
  const aMonthAgo = new Date(today.getTime() - (30 * day));
  form.startDt.value = formatDate(aMonthAgo);
  form.endDt.value = formatDate(today);  
}

액션들을 모아 상태값으로 추상화하지 않고, 액션들을 하나하나 구현해 주었습니다. 코드 라인수는 늘어났지만, 대신 얻은 것들이 있습니다. ..를 한 번 그림으로 볼까요?

statefulstateless

어떤가요? 아직 느낌이 안 오신다면 여기에서 1일 버튼을 눌렀을 때의 기획을 추가해볼까요?ㅎㅎㅎㅎㅎ👻 (나쁘다)

if를 쓰지 않는 방식의 장점

  1. 읽기 편하다
    코드를 읽을 때, 상태에 대한 분기를 생각해야 합니다. 변수 내용을 기억해둬야 하죠. 이걸 안 해도 되기 때문에 편합니다.

  2. 기능을 추가하기 편하다
    기능을 추가할 때, 상태에 대한 분기를 생각해야 합니다. 필요한 부분을 찾아야 하고, 다른 곳에 부영향side effect을 주지 않는지 잘 살펴봐야 합니다. 이걸 안 해도 되기 때문에 편합니다.

  3. 테스트하기 편하다
    이 함수는 이제 1가지 일만 합니다. 상태가 1개 뿐이기 때문이죠. 따라서 테스트하기 편합니다.

어떤가요?
if를 쓰지 않는 방식.. 아껴 쓰는 방식도 괜찮죠? 😚

중복 배제는 정말로 정말로 주의해서

사실 이제 form.startDt.value, form.endDt.value를 바꿔주는 부분은 충분히 중복 배제Don't Repeat Yourself를 할 수 있겠죠! 하지만 하지 않았습니다. (;;)

DRY된 코드는 매우 높은 확률로 다시 if가 붙게 됩니다. 우리가 구현해야 하는 서비스는 구구단이나, 용돈기입장이 아니기 때문이죠.

코드가 우리의 통제 하에 있을 때, scope로 상태라는state 목줄을 묶어두는게 좀 더 중요하다고 생각하는 편이어서, 중복 배제는 정말로 정말로 주의해서 하기를 저는 좋아합니다!

혹시 관심이 가셨다면 다음 글도 한 번 읽어보세요!

AHA Programming: The dangers of DRY, the web of WET, the awesomeness of AHA.

profile
= v =?;;

0개의 댓글