만베거
newminkyung
15 2

파이브 라인스 오브 코드

3장. 긴 코드 조각 내기

DRY 및 KISS 지침들이 어려웠던 이유

DRY: Don't Repeat Yourself (반복하지 말라는 뜻)

KISS: Keep It Simple Stupid (단순하게 만들라는 뜻)

  • 메서드가 여러가지 다른 일을 수행한다.
  • 낮은 수준의 원시 연산을 사용한다.
  • 주석과 적절한 메서드와 변수명 같이 사람이 읽을 수 있는 텍스트가 부족하다

왜 다섯줄인가?

  • 메서드는 {}를 제외하고 5줄 이상이 되어서는 안된다.

  • 모든 메서드를 이 규칙을 준수하도록 바꿀 수 있다.

  • 스멜

    • 메서드가 길다는 것 자체가 냄새가 나는 것이다.
    • 긴 메서드의 모든 논리를 머릿속에 담아야해서 작업하기 어렵다.
  • 의도

    • 시간이 지남에 따라 추가되는 기능들로 인해 메서드가 커지는 경향이 있다.
    • 5줄의 코드가 있는 4개의 메서드가 20줄인 하나의 메서드보다 훨씬 빠르고 이해하기 쉽다.
  • 코드를 이해하기 위한 첫번재 단계는 항상 함수명을 고려하는 것


리팩터링: 메서드 추출

메서드를 더 작은 조각으로 분해하는 리팩터링 기법이다.

  1. 원하는 이름으로 새로운 빈 메서드 생성

  2. 그룹의 맨 위에서 새로운 메서드 호출

  3. 그룹의 코드를 잘라내어 새로운 메서드의 본문에 붙여넣기

  4. 컴파일

  5. 매개변수를 도입하여 호출하는 쪽의 오류를 발생시키기

  6. 매개변수 중 하나를 반환 값으로 할당해야하는 경우

    • 새로운 메서드의 마지막에 반환값을 추가
    • 새로운 메서드를 호출하는 쪽에서 반환값을 할당
  7. 컴파일

  8. 호출 쪽 인자 설정

  9. 사용하지 않는 코드와 주석 제거

  • 이 절차는 아무것도 손상시키지 않는다.
  • 코드가 수행하는 작업을 아직 살펴보지 않는 경우에는 아무것도 고장내지 않았다는 확신이 가장 중요함

규칙: 호출 또는 전달, 한가지만 할 것

  • 함수 내에서는 객체에 있는 메서드를 호출하거나 객체를 인자로 전달할 수 있지만 둘을 섞어 사용해서는 안됨
  • 많은 메서드 및 여러가지 매개변수를 전달하는 경우, 결국 해당 함수의 책임이 고르지 않게 됨
function average(arr: number[]) {
  return sum(arr) / arr.length
}
 
 
function average(arr: number[]) {
  return sum(arr) / size(arr)
}
  • 위 함수는 높은 수준의 추상화와 낮은 수준의 arr.length를 모두 사용
  • 스멜
    • 함수의 내용은 동일한 추상화에 이썽야한다.
    • 전달된 인자의 메서드가 어떻게 사용되는지 식별하는 방법은 인자로 전달된 변수 옆의 .을 통해 찾을 수 있다.
  • 의도
    • 메서드에서 몇가지 세부적인 부분을 추출해서 추상화를 도입할 때 연관된 다른 세부적인 부분도 추출하게 한다.
    • 이러면 메서드 내부의 추상화 수준이 동일하게 유지

좋은 함수의 이름의 속성

  • 정직해야한다
    • 함수의 의도를 설명해야한다
  • 완전해야한다
    • 함수가 하는 모든 것을 담아야한다
  • 도메인에서 일하는 사람이 이해할 . 수있어야한다.
  • 함수명을 지을 떄는 항상 나중에 함수가 더 작아졌을 때, 이름을 개선할 수 있는지를 평가해야한다.

규칙: if문은 함수의 시작에만 배치

  • if문이 있는 경우, 해당 if문은 함수의 첫번째 항목이어야한다.
  • 함수는 한가지 일만 해야한다
    • 무언가를 확인하는 것은 한가지 일 즉 if 가 있는 경우 함수의 첫번째 항목이어야 하고, 그 후에는 아무것도 해서는 안된다.
  • if 문을 분리하가 위해 메서드 추출을 사용한다.
function reportPrimes(n: number) {
  for (let i = 2; i < n; i++) {
    if (isPrime(i)) {
      console.log(`${i} is prime`);
    }
  }
}
 
 
function reportPrimes(n: number) {
  for (let i = 2; i < n; i++) {
    reportIfPrime(i);
  }
}
 
function reportIfPrime(n: number) {
  if (isPrime(i)) {
    console.log(`${i} is prime`);
  }
}
  • 스멜

    • 다섯 줄 제한과 같이 이 규칙은 함수가 한가지 이상의 작업을 수행하는 스멜을 막기 위해 존재
  • 의도

    • if 문이 하나의 작업이기 때문에 이를 분리할 때 이어지는 else if 는 if 문과 분리할 수 없는 원자 단위로 봄