코드를 읽기 좋게
이름 짓기와 함수 분리, 조기 반환을 다룹니다.
코드는 쓰는 시간보다 읽는 시간이 깁니다
한 번 작성한 코드를 여러 번 읽고 고칩니다. 읽는 사람은 대개 몇 달 뒤의 자신입니다.
여기서는 바로 오늘 적용할 수 있는 넷만 봅니다. 동작은 그대로이고 읽기만 달라집니다.
- 이름을 뜻대로 짓습니다.
- 함수 하나가 한 가지 일만 하게 나눕니다.
- 맞지 않는 경우를 먼저 걸러 냅니다.
- 주석은 왜를 적습니다.
이름이 설명을 대신합니다
function f(a, b) { return a - a * b / 100; } console.log(f(10000, 15));
function applyDiscount(price, percent) { return price - price * percent / 100; } console.log(applyDiscount(10000, 15));
결과는 같습니다. 다만 뒤엣것은 주석 없이도 무엇인지 알 수 있습니다.
- 무엇인지를 적습니다 —
a✕ →price - 함수는 동사로 시작합니다 —
applyDiscount,loadUser - 참·거짓은
is·has로 시작합니다 —isMember i는 반복문 안에서만 씁니다. 그 밖에서는 뜻이 없습니다.
한 가지 일만 하게
아래 함수는 세 가지를 합니다 — 거르고, 계산하고, 화면 문구를 만듭니다. 그래서 이름을 붙이기도 어렵습니다.
function process(products) { let sum = 0; for (const p of products) { if (p.stock > 0) { sum += p.price; } } return `합계 ${sum}원`; } const products = [ { name: "연필", price: 1000, stock: 3 }, { name: "공책", price: 2000, stock: 0 } ]; console.log(process(products));
const inStock = products => products.filter(p => p.stock > 0); const totalPrice = products => products.reduce((sum, p) => sum + p.price, 0); const won = amount => `합계 ${amount}원`; const products = [ { name: "연필", price: 1000, stock: 3 }, { name: "공책", price: 2000, stock: 0 } ]; console.log(won(totalPrice(inStock(products))));
셋으로 나누니 각각 이름을 붙일 수 있고, 따로 시험할 수 있고, 다른 데서도 쓸 수 있습니다. 3부의 배열 메서드가 그대로 쓰였습니다.
맞지 않는 경우를 먼저 걸러 냅니다
중첩이 깊어지면 어느 조건 안에 있는지를 계속 세어야 합니다. 아닌 경우를 먼저 끝내면 중첩이 사라집니다. 이것을 조기 반환 이라고 합니다.
function checkout(user, cart) { if (user) { if (user.isMember) { if (cart.length > 0) { return "결제합니다"; } else { return "장바구니가 비었습니다"; } } else { return "회원만 결제할 수 있습니다"; } } else { return "로그인이 필요합니다"; } } console.log(checkout({ isMember: true }, ["연필"])); console.log(checkout(null, []));
function checkout(user, cart) { if (!user) return "로그인이 필요합니다"; if (!user.isMember) return "회원만 결제할 수 있습니다"; if (cart.length === 0) return "장바구니가 비었습니다"; return "결제합니다"; } console.log(checkout({ isMember: true }, ["연필"])); console.log(checkout(null, []));
마지막 줄이 정상인 경우입니다. 위의 것들은 모두 예외입니다. 4.7 과 5.6 에서 이미 이렇게 적었습니다.
주석은 왜를 적습니다
// price 에 0.9 를 곱합니다 const sale = price * 0.9;
// 회원 할인 10% 는 계약상 소수점을 버립니다. // 반올림하면 총액이 청구서와 1원씩 어긋납니다. const sale = Math.floor(price * 0.9);
무엇을 하는지는 코드가 이미 말합니다. 주석에는 코드가 말할 수 없는 것을 적으세요 — 까닭, 정한 배경, 이렇게 하지 않으면 생기는 일.
고칠 때 함께 고치지 않은 주석은 틀린 설명이 되어 없느니만 못합니다.
처음에 자주 걸리는 것
usrNm, tmp,
data2 는 몇 글자 아끼고 읽는 시간을 훨씬 더
씁니다. 길어도 뜻이 분명한 편이 낫습니다.
process1,
handleData 로 나누면 오히려 찾기 어려워집니다.
이름을 붙이기 어렵다면 아직 한 가지 일이 아닌 것입니다.
읽기 좋게 고치는 일과 기능을 바꾸는 일은 따로 합니다. 함께 하면 무엇 때문에 깨졌는지 알 수 없습니다.
직접 해보기
아래 이름들을 뜻이 분명하게 고쳐 보세요.
아래 함수를 조기 반환으로 고쳐 중첩을 없애세요. 동작은 그대로여야 합니다.
이 단원의 정리
- 이름은 무엇인지 적습니다. 함수는 동사로, 참·거짓은
is·has로 시작합니다. - 함수 하나가 한 가지 일만 하게 나눕니다. 이름을 붙이기 어렵다면 아직 하나가 아닙니다.
- 맞지 않는 경우를 먼저
return하면 중첩이 사라집니다. - 주석에는 무엇이 아니라 왜를 적습니다.
- 읽기 좋게 고치는 일과 기능을 바꾸는 일은 따로 합니다.