JavaScript 클린코드 지키기!

최예준·2023년 10월 18일

공부

목록 보기
2/19
post-thumbnail

공들여 쓰레기를 만들지 말자..

Introduction

우리가 글을 쓸때 논리정연하게 자신의 의견을 잘 들어내며, 때로는 독자에게 보다 더 쉽고 몰입감 있게 읽힐 수 있도록 글을 깨끗하게 잘 쓸 필요가 있다.

이는 코드도 마찬가지다.

때론 보다 더 나은 성능을 위해, 때론 읽기 쉬운 코드를 위해
우린 깨끗하게 코드를 짜야한다.

그러기 위해서 몇 가지 기본적인 규칙들을 통해서 보다더 깨끗한 코드를 작성 할 수 있도록 해보자

1. Strong type checks

== 대신 === 사용하기

=== 가 더 강력하다,
이렇게 써야 null 과 undefined 를 구별 할 수 있을 뿐만 아니라 타입 또한 같은지도 판별 할 수 있다.

아래 예시코드를 보자

0 == false // true
0 === false // false
2 == "2" // true
2 === "2" // false

// example
const val = "123";

if (val === 123) {
  console.log(val);
  // it cannot not be reached
}

if (val === "123") {
  console.log(val);
  // it can be reached
}

2. Variables

변수의 용도와 의도를 드러내는 이름으로 짓기

변수의 이름만 봐도 용도름 짐작할 수 있고 검색이 가능하도록 단순하면 좋다

예시코드를 보자

Bad 👎🏻

let daysSLV = 10;

let y = new Date().getFullYear();

let ok;

if (user.age > 30) {
  ok = true;
}

good 👍🏻

const MAX_AGE = 30;

let daysSinceLastVisit = 10;

let currentYear = new Date().getFullYear();

...

const isUserOlderThanAllowed = user.age > MAX_AGE;

불필요한 단어 추가하지 않기

Bad 👎🏻

let nameValue;
let theProduct;

good 👍🏻

let name;
let product;

변수의 의미를 외우거나 유추하도록 하지 않게 하기

Bad 👎🏻

const products = ["T-Shirt", "Shoes", "Watches", "Bags"];

products.forEach(p => {
  doSomething();
  doSomethingElse();
  // ...
  // ...
  // ...
  // ...
  // What is `p` for?
  register(p);
});

good 👍🏻

const products = ["T-Shirt", "Shoes", "Watches", "Bags"];

products.forEach(product => {
  doSomething();
  doSomethingElse();
  // ...
  // ...
  // ...
  register(product);
});

같은 타입의 변수에는 같은 단어 쓰기

Bad 👎🏻

getUserInfo();
getClientData();
getCustomerRecord();

good 👍🏻

getProduct();

3. Functions

길어도 묘사가 잘 되는 이름 사용하기

줄여쓰지 말자 딱 변수명 봤을때 뭐하는 놈인지 바로 알 수 있도록 길더라도 풀네임으로 쓰자
제발

Bad 👎🏻

function email(user) {
  // implementation
}

good 👍🏻

function sendEmailUser(emailAddress) {
  // implementation
}

많은 수의 인자를 넣는것은 피하자
이상적으로, 한 함수에서 최대 2개까지 사용하는 것이 좋다. 인자가 적을수록, 함수를 테스트 하기도 쉬워진다.

Bad 👎🏻

function getProducts(fields, fromDate, toDate) {
  // implementation
}

good 👍🏻

function getProducts({ fields, fromDate, toDate }) {
  // implementation
}

getProducts({
  fields: ['id', 'name', 'price', 'units],
  fromDate: '2020-07-01',
  toDate: '2020-07-22'
});

conditionals 대신 default arguments 사용하기

Bad 👎🏻

function createShape(type) {
  const shapeType = type || "circle";
  // ...
}

good 👍🏻

function createShape(type = "circle") {
  // ...
}

한 함수에서 여러가지 동작 피하기

주인장이 가장많이 하는 짓...
중요중요

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();
}

default objects 지정할 때 Object.assign 사용하기

Bad 👎🏻

const shapeConfig = {
  type: "circle",
  width: 150,
  height: null
};
function createShape(config) {
  config.type = config.type || "circle";
  config.width = config.width || 300;
  config.height = config.height || 300;
}
createShape(shapeConfig);

good 👍🏻

const shapeConfig = {
  type: "circle",
  width: 150
  // Exclude the 'height' key
};

function createShape(config) {
  config = Object.assign(
    {
      type: "circle",
      width: 300,
      height: 300
    },
    config
  );
  ...
}
createShape(shapeConfig);

파라미터로 flags 쓰지 않기
flags를 파라미터로 사용하는 것은 함수가 해야할 일 보다 더 하고 있다는 의미!

Bad 👎🏻

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

good 👍🏻

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

function createPublicFile(name) {
  createFile(`./public/${name}`);
}

Globals 오염시키지 않기

이미 존재하는 객체를 extend해야 한다면 ES Classes와 상송성을 이용하고 native 객체의 prototy chain에 함수를 만드는걸 지양하자

Bad 👎🏻

Array.prototype.myFunction = function myFunction() {
  // implementation
};

good 👍🏻

class SuperArray extends Array {
  myFunc() {
    // implementation
  }
}

4. Conditionals

부정 조건(negative conditionals) 지양하기

Bad 👎🏻

function isPostNotPublished(post) {
  // implementation
}
if (!isPostNotPublished(post)) {
  // implementation
}

good 👍🏻

function isPostPublished(user) {
  // implementation
}
if (isPostPublished(user)) {
  // implementation
}

conditional shorthand 사용하기
사소해 보일지 모르지만, 짚고 넘어갈만 하다.
값이 boolean이거나 undefined 혹은 null값이 아니라고 확신할 때 쓰는게 좋다.

Bad 👎🏻

if (isValid === true) {
  // do something...
}
if (isValid === false) {
  // do something...
}

good 👍🏻

if (isValid) {
  // do something...
}
if (!isValid) {
  // do something...
}

꼭 필요한 상황이 아니면 조건은 지양하기
다형성(polymorphism)과 상속성(inheritance)을 이용하자 👀

Bad 👎🏻

class Dog {
  // ...
  getBreed() {
    switch (this.type) {
      case "GermanShepherd":
        return this.getStandardSize("GermanShepherd");
      case "JackRussellTerrier":
        return this.getStandardSize("JackRussellTerrier");
      case "ShibaInu":
        return this.getStandardSize("ShibaInu");
    }
  }
}

good 👍🏻

class Dog {
  // ...
}

class GermanShepherd extends Dog {
  // ...
  getStandardSize() {
    return this.standardSize;
  }
}

class JackRussellTerrier extends Dog {
  // ...
  getSize() {
    return this.standardSize;
  }
}

class ShibaInu extends Dog {
  // ...
  getSize() {
    return this.standardSize;
  }
}

5. ES Classes

ES Classes는 JavaScript의 새로운 개꿀문법이다.

진짜 코드 깔끔해진다 꼭 쓰자

prototype 과 동작원리는 비슷하다

Bad 👎🏻

const Product = function(name) {
  if (!(this instanceof Product)) {
    throw new Error("Instantiate Product with `new` keyword");
  }
  this.name = name;
};

Product.prototype.getSize = function getSize() { /**/ };

const Tshirt = function(name, color) {
  if (!(this instanceof Tshirt)) {
    throw new Error("Instantiate Tshirt with `new` keyword");
  }
  Product.call(this, name);
  this.color = color;
};

Tshirt.prototype = Object.create(Product.prototype);
Tshirt.prototype.constructor = Tshirt;
Tshirt.prototype.printColor = function printColor() { /**/ };

good 👍🏻

class Product {
  
  constructor(name) {
    this.name = name;
  }
  
  getDiscount() {
    /* ... */
  }
}

class Tshirt extends Product {
  
  constructor(name, color) {
    super(name);
    this.color = color;
  }
  
  getSize() {
    /* ... */
  }
}

6. Lint 사용하기

클린코드를 쓸 수 밖에 없게 만들어주는 고오급 도구
처음 쓸땐 많이 불편하겠지만 익숙해지면 깨끗해지는 코드를 볼 수 있을 것이다.

7. 평소에 피해야할 것들

  • 반복적인 코드 작성하지 않기
  • 사용되지 않는 함수나 죽은 코드 남겨두지 않기

참고사이트

profile
개발도 잘하고픈 행복한 개발자

0개의 댓글