Javascript Clean Code(2) - (동시성 및 기타)

huurray·2021년 2월 13일
1

Javascript Clean Code

목록 보기
2/2
post-thumbnail

들어가기

이번에는 원문에서의 동시성 및 기타사항에 대한 항목들을 옮겨보자.
(원문은 글 아래에 링크)

동시성(Concurrency)

1. Callback 대신 Promise를 사용하라.

Callback 지옥을 벗어나기위해 Promise개념을 사용한다.

Bad:

require('request-promise')
  .get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then(response => {
    return require('fs-promise').writeFile('article.html', response)
  })
  .then(() => {
    console.log('File written')
  })
  .catch(err => {
    console.error(err)
  })

Good:

require('request-promise')
  .get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then(response => {
    return require('fs-promise').writeFile('article.html', response)
  })
  .then(() => {
    console.log('File written')
  })
  .catch(err => {
    console.error(err)
  })

2. Async/Await은 Promise보다 더욱 깔끔하다.

Promise도 Callback에 비해 정말 깔끔하지만 ES2017/ES8에선 async와 await이 있다.

이들은 Callback에 대한 더 깔끔한 해결책을 준다.

오직 필요한 것은 함수앞에 async를 붙이는 것 뿐이다. 그러면 함수를 논리적으로 연결하기위해 더이상 then을 쓰지 않아도 된다.

단, ES2017/ES8 문법이기 때문에 사용 가능한 경우를 구분해야한다.

Bad:

require('request-promise')
  .get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then(response => {
    return require('fs-promise').writeFile('article.html', response)
  })
  .then(() => {
    console.log('File written')
  })
  .catch(err => {
    console.error(err)
  })

Good:

async function getCleanCodeArticle() {
  try {
    const response = await require('request-promise').get(
      'https://en.wikipedia.org/wiki/Robert_Cecil_Martin'
    )
    await require('fs-promise').writeFile('article.html', response)
    console.log('File written')
  } catch (err) {
    console.error(err)
  }
}

에러 처리(Error Handling)

에러를 뱉는다는 것은 좋은 것이다. 즉, 프로그램에서 무언가가 잘못되었을 때 런타임에서 성공적으로 확인되면 현재 스택에서 함수 실행을 중단하고 (노드에서) 프로세스를 종료하고 스택 추적으로 콘솔에서 사용자에게 그 이유를 알려준다.

1. 단순히 에러를 확인만 하지마라.

2. Promise가 실패된 것을 무시하지 마라.

단순히 에러를 확인하는 것만으로 그 에러가 해결되거나 대응 할 수 있게 되는 것은 아니다.

console.log를 통해 콘솔에 로그를 기록하는 것은 에러 로그를 잃어버리기 쉽기 때문에 좋은 방법이 아니다.

만약에 try/catch로 어떤 코드를 감쌌다면 그건 당신이 그 코드에 어떤 에러가 날지도 모르기 때문에 감싼 것이므로 그에대한 계획이 있거나 어떠한 장치를 해야한다.

Bad:

try {
  functionThatMightThrow()
} catch (error) {
  console.log(error)
}

Good:

try {
  functionThatMightThrow()
} catch (error) {
  // 첫번째 방법은 console.error를 이용하는 것이다. 
  console.error(error)
  // 다른 방법은 유저에게 알리는 방법이다.
  notifyUserOfError(error)
  // 또 다른 방법은 서비스 자체에 에러를 기록하는 방법이다.
  reportErrorToService(error)
  // 혹은 그 어떤 방법이 될 수 있다.
}

포맷팅(Formatting)

1. 일관된 대소문자를 사용하라.

JavaScript에는 정해진 타입이 없기 때문에 대소문자를 구분하는 것으로 당신의 변수나 함수명 등에서 많은 것을 알 수 있다.

이 규칙 또한 주관적이기 때문에 당신이 팀이 선택한 규칙들을 따라야한다. 중요한건 항상 일관성 있게 사용해야 한다는 것이다.

Bad:

const DAYS_IN_WEEK = 7
const daysInMonth = 30

const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']
const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles']

function eraseDatabase() {}
function restore_database() {}

class animal {}
class Alpaca {}

Good:

const DAYS_IN_WEEK = 7
const DAYS_IN_MONTH = 30

const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude']
const artists = ['ACDC', 'Led Zeppelin', 'The Beatles']

function eraseDatabase() {}
function restoreDatabase() {}

class Animal {}
class Alpaca {}

2. 함수 호출자와 함수 피호출자는 가깝게 위치시켜라.

우리는 코드를 읽을때 신문을 읽듯 위에서 아래로 읽기 때문에 코드를 작성 할 때도 읽을 때를 고려하여 작성해야한다.

Bad:

class PerformanceReview {
  constructor(employee) {
    this.employee = employee
  }

  lookupPeers() {
    return db.lookup(this.employee, 'peers')
  }

  lookupManager() {
    return db.lookup(this.employee, 'manager')
  }

  getPeerReviews() {
    const peers = this.lookupPeers()
    // ...
  }

  perfReview() {
    this.getPeerReviews()
    this.getManagerReview()
    this.getSelfReview()
  }

  getManagerReview() {
    const manager = this.lookupManager()
  }

  getSelfReview() {
    // ...
  }
}

const review = new PerformanceReview(user)
review.perfReview()

Good:

class PerformanceReview {
  constructor(employee) {
    this.employee = employee
  }

  perfReview() {
    this.getPeerReviews()
    this.getManagerReview()
    this.getSelfReview()
  }

  getPeerReviews() {
    const peers = this.lookupPeers()
    // ...
  }

  lookupPeers() {
    return db.lookup(this.employee, 'peers')
  }

  getManagerReview() {
    const manager = this.lookupManager()
  }

  lookupManager() {
    return db.lookup(this.employee, 'manager')
  }

  getSelfReview() {
    // ...
  }
}

const review = new PerformanceReview(employee)
review.perfReview()

주석(Comments)

1. 주석은 단지 그 로직이 복잡하다는 것을 말 할 뿐이다.

주석을 다는것은 사과해야할 일이며 필수적인 것이 아니다. 좋은 코드는 코드 자체로 말한다.

Bad:

function hashIt(data) {
  // 이건 해쉬다.
  let hash = 0

  // lengh는 data의 길이이다.
  const length = data.length

  // 데이터의 문자열 개수만큼 반복문을 실행한다.
  for (let i = 0; i < length; i++) {
    // 문자열 코드를 얻는다.
    const char = data.charCodeAt(i)
    // 해쉬를 만든다.
    hash = (hash << 5) - hash + char
    // 32-bit 정수로 바꾼다.
    hash &= hash
  }
}

Good:

function hashIt(data) {
  let hash = 0
  const length = data.length

  for (let i = 0; i < length; i++) {
    const char = data.charCodeAt(i)
    hash = (hash << 5) - hash + char

    // 32-bit 정수로 바꾼다.
    hash &= hash
  }
}

2. 주석으로 된 코드를 남기지 마라.

버전 관리 도구(Git)가 존재하기 때문에 코드를 주석으로 남길 이유가 없다.

Bad:

doStuff()
// doOtherStuff();
// doSomeMoreStuff();
// doSoMuchStuff();

Good:

doStuff()

3. 코드 기록을 주석으로 남기지 마라.

버전 관리 도구(Git)가 존재하기 때문에 코드를 주석으로 남길 이유가 없다.

Bad:

/**
 * 2016-12-20: 모나드 제거했음, 이해는 되지 않음 (RM)
 * 2016-10-01: 모나드 쓰는 로직 개선 (JP)
 * 2016-02-03: 타입체킹 하는부분 제거 (LI)
 * 2015-03-14: 버그 수정 (JR)
 */
function combine(a, b) {
  return a + b
}

Good:

function combine(a, b) {
  return a + b
}

원문

ryanmcdermott/clean-code-javascript

profile
Frontend Developer.

0개의 댓글