반응형
Notice
Recent Posts
Recent Comments
Link
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

지식조각모음

3장 긴 코드 조각내기 본문

책/Five Lines of Code

3장 긴 코드 조각내기

y00 2023. 8. 5. 14:53
반응형

이번 장에서 다룰 내용

- 다섯 줄 제한으로 지나치게 긴 메서드 식별하기
- 세부 사항을 보지 않고 코드 작업하기
- 메서드 추출로 긴 메서드 분해하기
- 호출 또는 전달, 한 가지만 할 것(EITHER CALL OR PASS)으로 추상화 수준 맞추기
- if 문은 함수의 시작에만 배치로 if 문 분리하기

첫 번째 규칙

규칙 소개

첫 번째 규칙: 왜 다섯 줄인가?

정의

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

설명

예를 들어 20줄의 메서드가 있을 경우 첫 10줄과 나머지 10줄로 각각 도우미 메서드를 만든다.

특정 수치로 줄 수를 제한하는 것보다 제한이 있다는 것 자체가 중요하다.

스멜

긴 메서드의 모든 논리를 머릿속에 담아야해서 작업이 어렵다. 메서드는 한 가지 작업만 해야 한다. 

의도

20줄인 하나의 메서드보다, 5줄의 코드가 있는 4개의 메서드가 훨씬 빠르고 이해하기 쉽니다. 각 메서드의 이름으로 코드의 의도를 전달할 수 있기 때문이다.

참조

  • 리펙터링 방법: 메서드 추출
  • 클린코드: '메서드는 한 가지 작업만 해야 한다'

리펙터링 패턴 소개

리펙처리 패턴: 메서드 추출

  1. 항상 함수명을 고려하자.
  2. 코드의 형태를 살펴보고 동일한 작업을 하는 데 필요한 줄의 그룹을 식별한다. 이때 일시적으로 빈 줄 또는 주석을 달아서 그룹을 분류한다.
  3. 분류한 그룹을 각각의 메서드로 추출한다.
  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');
	}
}

이 코드는 두 가지 일을 하고 있다.

  1. 숫자를 반복한다(for 문)
  2. 숫자가 소수인지 확인한다(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