1. 함수형 프로그래밍을 지향한다.
(여기선 간단히만 다룸. 중요한 패러다임이니 따로 공부할 예정)
함수형 프로그래밍이란 함수를 기반으로 하는 프로그래밍이다.
이러한 함수형 프로그래밍에선 순수 함수를 사용해야 한다.
- 순수 함수
- 같은 입력이 주어지면 항상 같은 값을 반환해야 한다.
- 부작용(Side effect)이 없어야 한다.
= 함수의 실행이 프로그램의 실행에 영향을 미치지 않아야 한다.
ex 함수 내부에서 인자의 값을 변경하거나 프로그램 상태를 변경하는 행위
프로그램에 변화를 주지 않고, 입력에 대한 결과를 예측할 수 있어서 테스트가 쉬워진다.
또한 함수형 프로그래밍은 데이터를 변경하지 않고 기존 데이터의 복사본을 다뤄야 한다.
복사본을 만들기 위한 JavaScript의 대표적인 순수 함수는 map
, filter
, reduce
가 있다.
// BAD - 반환값 없음. 외부 인자의 값 변경
function addPerson(array) {
array.push("John");
}
// BAD - 인자 대신 외부 변수를 사용
function addPerson() {
return [...globalArray, "John"];
}
// GOOD! - 순수 함수
function addPerson(array) {
return [...array, "John"];
}
2. 조건문은 캡슐화한다.
캡슐화를 하면 조건문의 로직을 내부로 숨기면서 캡슐화의 장점을 적용시킬 수 있다.
또한 내부 로직을 안 보고도 함수명을 통해 어느 정도 예측할 수 있는 장점이 있다.
// BAD
if (fsm.state === "fetching" && isEmpty(listNode)) {
// ...
}
// GOOD! - 조건문을 캡슐화
function shouldShowSpinner(fsm, listNode) {
return fsm.state === "fetching" && isEmpty(listNode);
}
if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}
3. 부정 조건문을 사용하지 않는다.
// BAD
function isDOMNodeNotPresent(node) {
// ...
}
if (!isDOMNodeNotPresent(node)) {
// ...
}
// GOOD!
function isDOMNodePresent(node) {
// ...
}
if (isDOMNodePresent(node)) {
// ...
}
4. 조건문 작성을 피한다.
우리는 조건문이 익숙하기 때문에 조건문 없이 코드를 짜라는 말에 의구심이 들기도 한다.
하지만 앞 게시물에 '함수는 하나의 행동만 해야 한다.'라는 중요한 원칙이 있었다.
함수에 조건문이 쓰였다면 이는 함수가 한 가지 이상의 기능을 하고 있다는 뜻이다.
조건문 대신 다형성을 이용하면 원칙을 지키면서도 동일한 기능의 함수를 만들 수 있다.
// BAD
class Airplane {
// ...
getCruisingAltitude() {
switch (this.type) {
case "777":
return this.getMaxAltitude() - this.getPassengerCount();
case "Air Force One":
return this.getMaxAltitude();
case "Cessna":
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
}
// GOOD! - 다형성을 이용해 함수 분리
class Airplane {
// ...
}
class Boeing777 extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getPassengerCount();
}
}
class AirForceOne extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude();
}
}
class Cessna extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
5. 타입 체킹을 도와주는 여러 방법을 사용한다.
JavaScript는 동적 타입 언어이기 때문에 타입에 있어 자유롭다는 특징이 있다.
하지만 이러한 자유로움 때문에 생기는 여러 버그가 우리의 머리를 아프게 한다..
이때 typeof
, getType()
등의 내부 메서드를 이용해 타입을 체크하는 것보다
아래에 추천하는 좋은 방법들로 타입 체킹 문제를 해결하길 추천한다.
5-1. 일관성 있는 API를 사용한다.
// BAD
function travelToTexas(vehicle) {
if (vehicle instanceof Bicycle) {
vehicle.pedal(this.currentLocation, new Location("texas"));
} else if (vehicle instanceof Car) {
vehicle.drive(this.currentLocation, new Location("texas"));
}
}
// GOOD! - move로 일관성 있게
function travelToTexas(vehicle) {
vehicle.move(this.currentLocation, new Location("texas"));
}
5-2. TypeScript를 사용한다.
TypeScript는 JavaScript의 슈퍼 셋(상위 개념) 언어이다.
즉 JS의 모든 문법을 포함하면서도 interface 등의 문법을 추가로 지원한다.
만약 지금 타입 체킹을 해결하느라 복잡해진 코드와 많은 주석 때문에 스트레스 받는다면
TypeScript를 사용할 좋은 타이밍이다!
// BAD
function add(a, b) {
if (typeof a === "number" && typeof b === "number") {
return a + b;
}
}
// GOOD! - TypeScript
function add(a: number, b: number) {
return a + b;
}
6. 과도한 최적화를 피한다.
최신 브라우저는 런타임 과정에서 많은 최적화 작업을 대신 수행해준다.
오히려 내가 코드를 직접 최적화하는 것이 시간 낭비가 될 수 있다.
// 과거엔 `list.length`를 매번 계산했기 때문에 불필요한 자원 소모가 있었다.
// 하지만 최신 브라우저에서는 캐싱을 통해 이러한 연산을 최적화 한다.
for (let i = 0, len = list.length; i < len; i++) {
// ...
}
7. 죽은 코드는 지운다.
더 이상 호출되지 않는 죽은 코드가 있다면 지우자. 죽은 코드는 중복된 코드만큼 좋지 않다.
언젠가 또 쓰일까봐 함부로 못 지우겠다면 GIT 등의 버전 관리 툴을 이용하자.
그 코드는 내 레퍼지토리에 남아 있으니 안심하고 지울 수 있을 것이다.
// BAD - oldRequestModule는 안쓰임
function oldRequestModule(url) {
// ...
}
function newRequestModule(url) {
// ...
}
const req = newRequestModule;
inventoryTracker("apples", req, "www.inventory-awesome.io");
// GOOD!
function newRequestModule(url) {
// ...
}
const req = newRequestModule;
inventoryTracker("apples", req, "www.inventory-awesome.io");
참조
'프론트엔드 > JavaScript' 카테고리의 다른 글
[JavaScript] 클린 코드 - 5. 클래스 (0) | 2021.07.04 |
---|---|
[JavaScript] 클린 코드 - 4. 객체와 자료구조 (0) | 2021.06.25 |
[JavaScript] 클린 코드 - 2. 함수 (1) (0) | 2021.06.23 |
[JavaScript] 클린 코드 - 1. 변수명 짓는 방법 (0) | 2021.06.23 |
[JavaScript] 배열 메서드 종류 (filter, forEach, map, reduce, sort) (0) | 2021.04.13 |