CleanCode JS - 함수

pds·2022년 12월 6일
0

Cleancode

목록 보기
5/5

Robert C. Martin's Cleancode를 Javascript로 적용시킨 레포를 보고 참고하여 기록한 내용입니다.



2개 이하의 매개변수가 이상적이다.

매개변수가 많으면 테스트 경우의 수가 많아지고 그만큼 많은 사례들에 대한 테스팅을 해야 한다.

또한 하나의 역할만 가지고 있지 않을 확률이 높음

destructing 활용하기

어떤 사람이 그 함수의 시그니쳐(인자의 타입, 반환되는 값의 타입 등)를 볼 때 어떤 속성이 사용되는지 즉시 알 수 있습니다.

또한 비구조화는 함수에 전달된 인수 객체의 지정된 기본타입 값을 복제하며 이는 사이드이펙트가 일어나는 것을 방지합니다.

참고로 인수 객체로부터 비구조화된 객체와 배열은 복제되지 않습니다.
Linter를 사용하면 사용하지않는 인자에 대해 경고해주거나 비구조화 없이 코드를 짤 수 없게 할 수 있습니다.

어떤게 사용하기 좋을까?

type Member = {
    id: number;
    name: string;
    age: number;
}

function a(id:number, name:string, age:number) {

}

function aa({id, name, age}: Member) {

}

a(14, "abc", 45);
aa({id: 254,
    name: "hello",
    age: 45})

OCP

함수가 하나 이상의 행동을 한다면 작성도,테스팅도,코드를 읽는 것도 어려워진다.

단일책임원칙을 보장하면 코드 수정이 매우 쉬워진다.

역할에 맞는 함수 하나에만 관심을 두고 수정하고 테스트하면 되기 때문이다.

Non-compliant

function emailClients(clients) {
  clients.forEach(client => {
    const clientRecord = database.lookup(client);
    if (clientRecord.isActive()) {
      email(client);
    }
  });
}

Compliant

function emailClients(clients) {
  clients
    .filter(isClientActive)
    .forEach(email);
}

function isClientActive(client) {
  const clientRecord = database.lookup(client);
  return clientRecord.isActive();
}


추상화 잘하기

뭔가 비슷한 기능을 하는데? 여러 함수를 만들어본 경험이 있다.

아주 조금의 동작 차이때문에 함수 하나를 더 만드는 것이다.

기본적으로 이런 상황에 불편해야 한다.

중복된 코드가 있다는 것은 요구사항이 변경되었을 때 그 수만큼 수정해줘야 한다는 것을 의미한다.


여러가지 사소한 차이점 또한 함수들 간 상호작용으로 모두 처리할 수 있게끔

최소한의 기능을 가진 함수들로 잘 추상화 하여 재사용할 수 있으며 이는 유지보수성으로 이어진다.


사이드이펙트 없애기

함수는 값을 받아서 어떤 일을 하거나 값을 리턴할 때 사이드 이팩트를 만들어냅니다. 사이드 이팩트는 파일에 쓰여질 수도 있고, 전역 변수를 수정할 수 있으며, 실수로 모든 돈을 다른 사람에게 보낼 수도 있습니다.

공유되는 변경가능한 데이터에 직접 접근하여 수정하거나 하는 행위는 의도치 않은 사이드이펙트를 불러올 수 있다.

Non-compliant

let name = 'Ryan McDermott';

function splitIntoFirstAndLastName() {
  name = name.split(' ');
}

splitIntoFirstAndLastName();

console.log(name); // ['Ryan', 'McDermott'];

Compliant

function splitIntoFirstAndLastName(name) {
  return name.split(' ');
}

const name = 'Ryan McDermott';
const newName = splitIntoFirstAndLastName(name);

console.log(name); // 'Ryan McDermott';
console.log(newName); // ['Ryan', 'McDermott'];

기본형 타입을 예시로 들었는데

참조를 전달하는 객체형 타입의 경우는 내부에 직접 변화를 줄 수 있기 때문에

조작할 때 직접 객체를 조작하지 말고

항상 복사해와서 수정하고 복제본을 반환하도록 하자

Non-compliant

const addItemToCart = (cart, item) => {
  cart.push({ item, date: Date.now() });
};

Compliant

const addItemToCart = (cart, item) => {
  return [...cart, { item, date : Date.now() }];
};

profile
강해지고 싶은 주니어 프론트엔드 개발자

0개의 댓글