Javascript [CleanCode]

이진우·2021년 11월 24일
0


소개(Introduction)

“클린코드는 코드를 처음 보는 사람도 동작을 직관적으로 파악할 수 있도록 하는 것을 목표로 합니다. 여기서 코드를 처음 보는 사람은 우리 팀원들, 유지 보수를 할 후임자들, 오픈소스나 API 사용자, 그리고 3달 뒤의 자기 자신​이 있습니다.
우리는 코드를 읽는 것이 아니라, 해석합니다. 가독성 확보는 코드 해석에 드는 비용을 줄이는 작업입니다.
심지어 우리는 코드를 몇 번이나 반복해서 읽습니다. 클린코드에서는 코드를 짜는 것과 읽는 것의 비중이 1:10 정도라고 이야기합니다. 조금 과장하자면 가독성 확보는 전체 코딩 업무의 90%에 대한 효율화 작업이라고 할 수 있겠습니다.”

[출처] [네이버클라우드 개발자 스토리] 좋은 코드란 무엇일까?🤔 #클린코드 이야기|작성자 NAVER Cloud Platform

현업에서 개발을 하다보면 "시간에 쫒겨서" "기획이 자주 바뀌어서" "기능이 추가돼서"
"동료가 내 코드를 건드려서" 등등 많은 이유로 코드가 더티해 지기 마련입니다,
저 또한 그렇습니다.
처음 코드를 작성할 때의 마음은 어디가고 "바빠 죽겠는데 나중에 리팩토링 해야지"하고 넘기는 경우도 더러 있습니다.
사실 바쁘다는 핑계일 뿐이고 클린코드 작성이 아직 습관화 되지 못한 탓이겠죠.
우리가 작성하는 클린 코드는 가독성을 높여주고 유지보수를 유연하게 해주며
작은 실수로 생기는 오류들을 최소화 시켜줍니다.
미래의 나를 위해서, 옆자리 동료를 위해서, 훌륭한 커뮤니케이션을 위해서 클린코드 작성을 시작해 봅시다!!



1.변수(Variables)

의미 있고 발음하기 쉬운 변수 이름을 사용하세요

Bad 👎🏻

const yyyymmdstr = moment().format('YYYY/MM/DD');

good 👍🏻

const currentDate = moment().format('YYYY/MM/DD');


불필요한 단어를 추가하지 마세요.

Bad 👎🏻

let nameValue;
let clientData;

good 👍🏻

let name;
let client;


변수가 정확히 무엇을 의미하는지 알 수 있도록 명명해 주세요.

Bad 👎🏻

Array.forEach( p => {
  doSomting1();
  doSomting2();
});

good 👍🏻

Array.forEach( product => {
  doSomting1();
  doSomting2();
});


검색 가능한 이름을 사용하세요.

Bad 👎🏻

setTimeout(function, 86400000);

good 👍🏻

const MILLISECONDS_IN_A_DAY = 86400000;
setTimeout(function, MILLISECONDS_IN_A_DAY);


2.함수(Variables)

함수는 하나의 행동만 해야 합니다.

‘함수는 한 가지 책임을 갖는다’ 이를 단일 책임 원칙이라고 부릅니다.

Bad 👎🏻

function notifyUsers(users) {
  users.forEach(user => {
    const userRecord = database.lookup(user);
    if (userRecord.isVerified()) {
      notify(user);
    }
  });
}

good 👍🏻

function notifyVerifiedUsers(users) {
  users.filter(isUserVerified).forEach(notify);
}

function isUserVerified(user) {
  const userRecord = database.lookup(user);
  return userRecord.isVerified();
}


2.함수의 인자는 2개 이하가 이상적입니다.

매개변수 제한은 함수의 테스트를 쉽게 만들어 줍니다.
3이상의 매개변수가 필요하면 객체를 이용할 수 있습니다.

Bad 👎🏻

function createMenu(title, body, buttonText, cancellable) {
  ///
}

good 👍🏻

function createMenu({ title,body, buttonText, cancellable }) {
  ///
}

createMenu({
  title: 'userInfomation',
  body: 'Bar',
  buttonText: 'submit',
  cancellable: true,
})


함수 이름은 함수의 동작을 설명할 수 있어야 합니다.

Bad 👎🏻

function AddToDate(date, month) {
  // ...
}

const date = new Date();

// 뭘 추가하는 건지 이름만 보고 알아내기 힘듭니다.
AddToDate(date, 1);

good 👍🏻

function AddMonthToDate(date, month) {
  // ...
}

const date = new Date();
AddMonthToDate(date, 1);


중복된 코드를 작성하지 마세요.

중복된 코드는 유지 보수를 어렵게 합니다.

Bad 👎🏻

function drawDeveloperList(developers) {
  const data = new Object();
  users.forEach( developer => {
    const expectedSalary = developer.calculateExpectedSalary();
    const experience = developer.getExperience();
    const githubLink = developer.getGithubLink();
    const data = {
      expectedSalary,
      experience,
    };
  });
  return data;
}

function drawManagerList(managers) {
  const data = new Object();
  users.forEach( manager => {
    const expectedSalary = manager.calculateExpectedSalary();
    const experience = manager.getExperience();
    const portfolio = manager.getMBAProjects();
    const data = {
      expectedSalary,
      experience,
    };
  });
  return data;
}

good 👍🏻

function drawEmployeeList(employees) {
  const data = new Object();
  users.forEach( employees => {
    const expectedSalary = employees .calculateExpectedSalary();
    const experience = employees .getExperience();
    
    //다른 부분만 찾아서 로직을 나눠줍니다.
    let portfolio = employee.getGithubLink();
    if (employee.type === 'manager') {
      portfolio = employee.getMBAProjects();
    }
    
    const data = {
      expectedSalary,
      experience,
    };
  });
  return data;
}


매개변수로 플래그를 사용하지 마세요.

플래그를 사용하는 것 자체가 그 함수가 한 가지 이상의 역할을 하고 있다는 것을 뜻합니다.

Bad 👎🏻

function createFile(name, temp) {
  if (temp) {
    fs.create(`./temp/${name}`);
  } else {
    fs.create(name);
  }
}

good 👍🏻

function createFile(name) {
  fs.create(name);
}

function createTempFile(name) {
  createFile(`./temp/${name}`);
}


외부 변수를 함수에서 참조 변경하지 마세요.

전달 받은 파라미터의 값을 반환하며 전역 상태에 영향을 미치거나 영향 받지 않아야 합니다.
이를 순수 함수라고 합니다.

Bad 👎🏻

let name = 'Didier Drogba';

function splitIntoFirstAndLastName() {
  name = name.split(' ');
}
//전역 변수를 참조했기 때문에 이제 name은 배열이 됩니다.
//name을 사용하는 또 다른 함수가 있다면 프로그램이 망가집니다.
splitIntoFirstAndLastName();

console.log(name); //['Didier', 'Drogba']

good 👍🏻

function splitIntoFirstAndLastName(name) {
  return name.split(' ');
}
//전역 변수는 변경시키지 않고
const name = 'Didier Drogba';
//새로운 변수에 값을 참조합니다.
const newName = splitIntoFirstAndLastName(name);

console.log(name); // 'Didier Drogba';
console.log(newName); // ['Didier', 'Drogba'];


함수에 전달된 객체 참조 변수를 변경하지 마세요.

Object, Array와 같은 참조 변수를 인자로 전달 받고 변경하지 마세요.
새로운 Object, Array를 만들어서 결과 값으로 전달해야 합니다.

Bad 👎🏻

let user = { name: 'Drogba', age: 32 };

function increaseAge(user) {
  user.age = user.age + 1;
  return user;
}

good 👍🏻

let user = { name: 'Drogba', age: 32 };

function increaseAge(user) {
  //Spread Operater 새로운 객체로 결과 값을 반환
  return {...user, age: user.age + 1};
}


과도한 최적화를 지양하세요.

최신 브라우저들은 런타임에 많은 최적화 작업을 수행합니다.
과도한 최적화로 코드를 복잡하게 만들지 마세요.
조건문을 최적화 하려고 하기보다는 보기 좋고 읽기 편하게 변경하세요.

Bad 👎🏻

//오래된 브라우저의 경우 캐시되지 않은 `list.length`를 통한 
//반복문은 높은 코스트를 가졌습니다.
//그 이유는 `list.length`를 매번 계산해야만 했기 때문인데, 
//최신 브라우저에서는 이것이 최적화 되었습니다.
for (let i = 0, len = list.length; i < len; i++) {
  // ...
}

good 👍🏻

for (let i = 0; i < list.length; i++) {
  // ...
}


죽은 코드를 지우세요

Bad 👎🏻

function oldRequestModule(url) {
  // ...
}

function newRequestModule(url) {
  // ...
}
//const req = oldRequestModule;
const req = newRequestModule;

good 👍🏻

function newRequestModule(url) {
  // ...
}

const req = newRequestModule;


Early Return, Early Exit을 사용하세요.

함수를 작성 할 때는 최대한 빨리 return 하거나 함수를 빠져 나오는 쪽으로 작성 하세요.

Bad 👎🏻

function updateUser(user) {
  if(user.point > 30) {
    //Do Something
  }
 }

good 👍🏻

function updateUser(user) {
  //조건이 맞지 않으면 빠르게 리턴
  if(user.point <= 30) {
    return;
  }
  //Do Something Here!
 }


3.조건문

부정 조건문을 사용하지 마세요.

부정 조건문은 프로그램 개발, 유지 보수에 혼돈을 가져옵니다.

Bad 👎🏻

function isDOMNodeNotPresent(node) {
  // ...
}
if (!isDOMNodeNotPresent(node)) {
  // ...
}

good 👍🏻

function isDOMNodePresent(node) {
  // ...
}
if (isDOMNodePresent(node)) {
  // ...
}


복잡한 조건문은 캡슐화 하세요.

복잡한 조건문을 캡슐화 하면 어떤 조건인지 직관적으로 유추할 수 있습니다.

Bad 👎🏻

if (fsm.state === 'fetching' && isEmpty(listNode)) {
  // ...
}

good 👍🏻

function shouldShowSpinner(fsm, listNode) {
  return fsm.state === 'fetching' && isEmpty(listNode);
}

if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
  // ...
}


다중 조건일 때 or연산자 나열한 것을 축약하세요.

Bad 👎🏻

let col = "score"
if (col === "score" || col === "age" || col === "mobile" || col === "email") {
	// 조건에 따른 로직
}

good 👍🏻

if (["score", "age", "mobile", "email"].include(col)) {
	// 조건에 따른 로직
}


삼항연산자를 사용하세요.

흔한 if, else 문입니다.
삼항연산자를 사용하면 한줄로 간결하게 정리할 수 있습니다.

Bad 👎🏻

let color = "";
if (score > 90) {
  color = "blue";
} else {
  color = "yellow";
}

good 👍🏻

// 삼항연산자를 사용해서 축약
let color = (score > 90) ? "blue" : "yellow"


Null, undefined, 빈 값 체크를 간결하게 하세요.

자바스크립트는 동적타입 언어이기 때문에 null, undefined, 빈 배열 또는 빈 문자열 등의 false 값 체크는 필수입니다.
여러개의 조건을 나열하는 대신 || 연산자를 사용하면 간결하게 정리할 수 있습니다.

Bad 👎🏻

if (member !== null || member !== undefined || member !== "") {
  let student = member;
}

good 👍🏻

let student = member || "";
profile
FRONT-END DEVELOPER KARL

0개의 댓글