[TIL] 프로처럼 코드짜기

mocha·2021년 3월 18일
0

TIL

목록 보기
9/10
post-thumbnail

💡 이 내용은 유튜브를 보고 정리한 내용입니다.

단계별로 임의대로 초보 / 주니어 / 시니어라고 칭했습니다...

🚫 시니어가 보기에 별거 아닐 수도 있음 주의

예제 1

조건

  • 주어진 숫자가 음수면 괄호 안에 절대값을 넣어서 반환
  • 주어진 숫자가 정수면 그냥 숫자 반환
  • -4 👉 (4)
  • 5 👉 5

초보의 코드

function toAccounting(n) {
  if (n < 0) {
    return '(' + Math.abs(n) + ')';
  } else if (n >= 0) {
    return n;
  }
}

console.log(toAccounting(0));
console.log(toAccounting(10));
console.log(toAccounting(-5));

리뷰

  1. n과 같은 모호한 변수명을 사용
  2. toAccounting와 같은 모호한, 목적이 불명확한 함수명
  3. 백틱사용 안해서 덜 깔끔함
  4. 불필요한 if 조건문 반복 사용
    • if(n < 0)을 걸렀다면 자연히 남은 건 n >= 0인데 굳이 필요없는 else if 사용함
  5. 초보가 가장 많이 하는 실수
    1. 타입에 대해 생각을 안함
      • 음수는 괄호 때문에 string으로 반환되지만,
      • 정수는 그냥 반환하기때문에 Number로 반환됨
      • 동일한 string type으로 반환되어야 함.
    2. 매개변수로 undefined 또는 null이 올 수 있다는 점을 생각 안함. 그래서 오류가 발생
console.log(toAccounting(undefined)); // 오류 발생

주니어의 코드

function numberToAccountingString(number) {
  if (number != null) {
    if (number < 0) {
      return `(${Math.abs(number)})`;
    } else {
      return number.toString();
    }
  }
}

리뷰

  1. 더 정확하고 구체적인 변수명, 함수명을 사용
  2. number != null으로 매개변수가 undefined일때 undefined을 그대로 반환 가능
    • 🤔 typeof number === 'number'로 걸러내는게 좋지않나?
    • 뭔가 더 구체적이자너...🤔🤔🤔🤔
    • 그냥 더 짧고 깔끔해서 그런걸까?
  3. 백틱사용으로 더 깔끔하게 읽을 수 있다.

⚡ 시니어의 코드 (아무튼 프로의 코드)

대부분의 사람들은 주니어의 코드에서 멈출 수 있다.
엄청 나쁘고 읽기 힘든 게 아니니까.
하지만 진정한 프로라면 한발 더 나아간 클린코드를 작성 할 것이다.

function numberToAccountingString(number) {
  if (number == null) return;
  if (number < 0) return `(${Math.abs(number)})`;
  return number.toString();
}

리뷰

  1. 딱봐도 그냥 깔끔하고 읽기 좋다!
  2. 조건문이 간단해졌다.
    • 주니어의 조건문처럼, 조건문 안에 조건문이 있다면 무척 읽기 힘들다.
    • 별거 아닐 수 있지만 생각을 깊게 안해도 되어 좋음

예제 2

조건

  • 주어진 가격, 개수, 세금, 할인, 배송비를 이용하여 결제할 금액을 계산하라.
  • 세금은 1.1% 이다

초보

function cacluateTotal(items, options) {
  let t = 0;
  items.forEach((i) => {
    t += i.price * i.quan;
  });

  t = t - t * (options.dis || 0);
  t = t * 1.1;
  t = t + (options.ship || 5);
  return t;
}

const testItems = [
  { price: 15, quan: 2 },
  { price: 20, quan: 1 },
  { price: 5, quan: 4 },
];

console.log(cacluateTotal());
console.log(cacluateTotal(testItems));
console.log(cacluateTotal(testItems, { ship: 0 }));
console.log(cacluateTotal(testItems, { dis: 0.75 }));
console.log(cacluateTotal(testItems, { ship: 12 }));
  • 불명확한 함수명 : 무슨 일을 하는지 짐작이 안간다!
  • 불명확한 변수명 t, quan, dis ...
  • 불명확한 t * 1.1에서 1.1의 의미
    • 정말 모든게 확실한게 없다 🤔 불친절해서 정말 혼란스럽다!
  • 첫번째의 예제와 같이 undefined,null에 대한 대비가 없다.
  • 논리합 || 을 사용하여, ship(배송비)이 0 이어도 5를 반환한다.
  • 버그 : 아무것도 사지 않아도, ship(배송비)를 5$ 를 내야한다.
console.log(cacluateTotal([], {}); // 5

주니어

const TAX_RATE = 1.1;
const SHIPPING_DEFUALT = 5;

function cacluateTotal(items, options = {}) {
  if (items == null || items.length === 0) return 0;

  let total = 0;
  items.forEach((item) => {
    total += item.price * item.quantity;
  });
  total = total - total * (options.discount || 0);
  total = totla * TAX_RATE;
  if (options.shipping !== 0) {
    total = total + (options.shipping || SHIPPING_DEFUALT);
  }
  return total;
}

const testItems = [
  { price: 15, quantity: 2 },
  { price: 20, quantity: 1 },
  { price: 5, quantity: 4 },
];

리뷰

  • 상수 변수를 사용하여 정확한 변수명을 줌.
    • TAX_RATE, SHIPPING_DEFUALT
  • items가 null이거나 없을때 {}를 대비했다.
  • 매개변수 options에 default value을 줘서 options를 주지않을 때의 에러를 대비했다.
  • 변수명이 더 명확한 값을 가리킨다.

시니어

const TAX_RATE = 1.1;
const SHIPPING_DEFUALT = 5;

function cacluateTotal(
  items,
  { shipping = SHIPPING_DEFUALT, discount = 0 } = {}
) {
  if (items == null || items.length == 0) return null;

  const itemCost = items.reduce((total, item) => {
    return total + item.price * item.quantity;
  }, 0);
  const discountRate = 1 - discount;

  return itemCost * discountRate * TAX_RATE + shipping;
}

리뷰

  • 읽을 때 조금 덜 생각해도 될 정도로 깔끔하다
function cacluateTotal(
  items,
  { shipping = SHIPPING_DEFUALT, discount = 0 } = {}
)
  • 매개변수의 options을 destructuring하여 사용했다.
    • shipping이나 discount가 따로 주어지지 않는다면 default값을 사용할 것이다.
    • options가 아예 주어지지 않을 때를 대비하여 {} = {}와 같이 대비했다.
  • forEach가 아닌 reduce를 사용하여 하나의 값을 반환하도록 했다.
    • 덕분에 코드가 더 짧아지고 더욱 읽기 쉬워진다!
  • 주니어에선 total을 계속 업데이트하고 total을 반환했지만, 시니어는 각각의 값을 변수로 만든 뒤 마지막에 계산한 값을 반환한다.
    • 계속 새롭게 업데이트 되는 값을 추적하기엔 신경이 많이 쓰인다.
    • 하지만 const로 정의한 각각의 값은 절대 변하지않으므로 신경을 덜 쓸 수 있다.
    • 이렇게하면 나중에 코드를 수정할 일이 있을 때, 더 간단하게 수정할 수 있다.

📖 느낀점

초보자와 주니어의 차이는 아주 작다. 조금만 신경을 써도 충분히 작성 가능하다!
보통은 첫작성시엔 초보-주니어의 사이에 있는 코드를 작성한다.
그러니 시간이 날 때마다 리팩토링 하는 연습을 해보자.
이제 클린코드는 어떤 생각을 하며 짜야하는지 알았으니 주의해보자 ✏️

테스트 케이스를 다양하게 만들어서 버그에 대비하자

profile
고양이를 사랑하는 개발자😽

0개의 댓글