지식조각모음
3장 긴 코드 조각내기 본문
반응형
이번 장에서 다룰 내용
- 다섯 줄 제한으로 지나치게 긴 메서드 식별하기
- 세부 사항을 보지 않고 코드 작업하기
- 메서드 추출로 긴 메서드 분해하기
- 호출 또는 전달, 한 가지만 할 것(EITHER CALL OR PASS)으로 추상화 수준 맞추기
- if 문은 함수의 시작에만 배치로 if 문 분리하기
첫 번째 규칙
규칙 소개
첫 번째 규칙: 왜 다섯 줄인가?
정의
메서드는 {와 }를 제외하고 5줄 이상이 되어서는 안 됩니다.
설명
예를 들어 20줄의 메서드가 있을 경우 첫 10줄과 나머지 10줄로 각각 도우미 메서드를 만든다.
특정 수치로 줄 수를 제한하는 것보다 제한이 있다는 것 자체가 중요하다.
스멜
긴 메서드의 모든 논리를 머릿속에 담아야해서 작업이 어렵다. 메서드는 한 가지 작업만 해야 한다.
의도
20줄인 하나의 메서드보다, 5줄의 코드가 있는 4개의 메서드가 훨씬 빠르고 이해하기 쉽니다. 각 메서드의 이름으로 코드의 의도를 전달할 수 있기 때문이다.
참조
- 리펙터링 방법: 메서드 추출
- 클린코드: '메서드는 한 가지 작업만 해야 한다'
리펙터링 패턴 소개
리펙처리 패턴: 메서드 추출
- 항상 함수명을 고려하자.
- 코드의 형태를 살펴보고 동일한 작업을 하는 데 필요한 줄의 그룹을 식별한다. 이때 일시적으로 빈 줄 또는 주석을 달아서 그룹을 분류한다.
- 분류한 그룹을 각각의 메서드로 추출한다.
- 오류가 나는 경우 매개변수를 도입하여 반환 값을 할당한다.
예
// 배열의 최소 항목을 찾는 함수
function minimum(arr: number[][]) {
let result = Number.POSITIVE_INFINITY;
for (let x = 0; x < arr.length; x++) {
for (let y = 0; y < arr[x].length; y++) {
// 추출하고자 하는 코드
if (result > arr[x][y]) {
result = arr[x][y];
}
}
}
return result;
}
// 배열의 최소 항목을 찾는 함수
function minimum(arr: number[][]) {
let result = Number.POSITIVE_INFINITY;
for (let x = 0; x < arr.length; x++) {
for (let y = 0; y < arr[x].length; y++) {
// 일단 메서드를 추출하고
// 그 결과를 할당하고 필요한 매개변수를 전달한다.
result = min(result, arr, x, y);
}
}
return result;
}
// 매개 변수 추가
function min(result: number, arr: number[][],
x: number, y: number) {
if (result > arr[x][y]) {
result = arr[x][y];
}
// 최소값을 전달하기 위해 return문 추가
return result;
}
두 번째 규칙
규칙 소개
호출 또는 전달, 한 가지만 할 것
정의
함수 내에서는 객체에 있는 메서드를 호출하거나 객체를 인자로 전달할 수 있지만 둘을 섞어 사용해서는 안 됩니다.
동일한 추상화를 유지하기 위한 방법인듯?? 한 메서드에서 하나의 변수가 매개변수로 전달되기도 하고, 메서드를 호출하기도 하는 경우 리펙터링이 필요하다.
설명
예를 들어, 배열에 두 가지 작업을 할 수 있다.
- 배열에 인덱스를 설정(코드 조작) -> 낮은 수준의 추상화
- 배열을 더 복잡한 함수에 인자로 전달(호출) -> 높은 수준의 추상화
이렇게 되면 다른 수준의 호출이 공존해서 메서드 이름 사이의 불일치로 가독성이 떨어질 수 있다.
스멜
'함수의 내용은 동일한 추상화 수준에 있어야 한다'. 그러나 추상화 수준을 찾는 것부터 어렵다.
- 인자로 전달된 변수 옆의 '.'(점)으로 쉽게 찾을 수 있다.
의도
메서드에서 내용을 추출해서 추상화를 도입할 때 다른 세부적인 부분도 추출하게 한다. 이렇게 하면 메서드 내부의 추상화 수준이 항상 동일하게 유지된다.
참조
- 리펙터링 방법: 메서드 추출
- 클린코드: '함수의 내용은 동일한 추상화 수준에 있어야 한다'
예
// 변경 전
function average(arr: number[]) {
return sum(arr) / arr.length;
}
// 변경 후
function average(arr: number[]) {
return sum(arr) / size(arr);
}
좋은 함수 이름의 속성
- 함수의 의도를 설명해야 한다.
- 함수가 하는 모든 것을 담아야 한다.
- 도메인에서 일하는 사람이 이해할 수 있어야 한다. 도메인에서 사용하는 단어를 사용하자.
세 번째 규칙
규칙 소개
정의
if 문이 있는 경우 해당 if 문은 함수의 첫 번째 항목이어야 한다.
설명
함수는 한 가지 일만 해야 한다. 무언가를 확인하는 것은 한 가지 일이다. 따라서 if 문이 메서드가 하는 유일한 일이어야 한다.
스멜
함수가 한 가지 이상의 작업을 수행하는 스멜을 막기 위해 존재한다.
예
function reportPrimes(n: number) {
for(let i = 2; i < n; i++) {
if (isPrime(i))
console.log('${i} is prime');
}
}
이 코드는 두 가지 일을 하고 있다.
- 숫자를 반복한다(for 문)
- 숫자가 소수인지 확인한다(if 문)
따라서 아래처럼 두 개의 메서드로 나눠야 한다.
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');
}
🧐 추가로 공부할 것
추상화 수준
반응형
'책 > Five Lines of Code' 카테고리의 다른 글
| 8장 주석 자제하기 (0) | 2023.09.04 |
|---|---|
| 4장 타입 코드 처리하기 (0) | 2023.08.17 |
| 2장 리팩터링 깊게 들여다보기 (0) | 2023.08.01 |
| 1장 리팩터링 리팩터링하기 (0) | 2023.08.01 |
| 스터디 시작 (0) | 2023.07.30 |