logo
새로운 블로그로 이전하였습니다.

(리팩터링 2판) ch06.8 매개변수 객체 만들기

  • 리팩터링
  • 매개변수 객체화

✅ 매개변수를 객체로 만들었을 때의 장점

1️⃣ 데이터 사이의 관계가 명확해진다

각각의 매개변수들을 여러 개 전달하지 않고, 이를 객체로 묶어서 전달하면 데이터 사이의 관계가 명확해진다.

2️⃣ 매개변수의 수가 줄어든다

객체로 묶은 매개변수 하나만 받아도 되므로 자연스레 매개변수의 수가 줄어든다.

3️⃣ 코드 일관성이 높아진다

같은 데이터 구조를 사용하는 모든 함수가 원소를 참조할 때 항상 똑같은 이름을 사용하기 때문에, 코드의 일관성도 좋아진다.

⭐ 4️⃣ 코드를 근본적으로 좋게 바꿔준다

데이터 구조에 담길 데이터에 공통으로 적용되는 동작을 함수로 추출하면,

새로 만든 데이터 구조가 문제 영역을 훨씬 간결하게 표현하는 새로운 추상개념으로 격상되면서

코드의 개념적인 그림을 다시 그릴 수 있게 된다.


✅ 절차

1. 적당한 데이터 구조가 아직 마련되어 있지 않다면 새로 만든다.
2. 테스트한다.
3. `함수 선언 바꾸기`로 새 데이터 구조를 매개변수로 추가한다.
4. 테스트 한다.
5. 함수 호출 시 새로운 데이터 구조 인스턴스를 넘기도록 수정한다. 
하나씩 수정할 때마다 테스트한다.
6. 기존 매개변수를 사용하던 코드를 새 데이터 구조의 원소를 사용하도록 바꾼다.
7. 다 바꿨다면 기존 매개변수를 제거하고 테스트한다.

🧑🏻‍🏭 리팩토링 실습

예시 코드

온도 측정값 배열에서 정상 작동 범위를 벗어난 것이 있는지 검사하는 코드를 살펴보고, 리팩토링 해보자

1. 온도 측정값을 표현하는 데이터

const station = { name: "ZB1",
	readings: [
	{temp: 47, time: "2016-11-10 09:10"},
	{temp: 53, time: "2016-11-10 09:20"},
    {temp: 58, time: "2016-11-10 09:30"},
    {temp: 53, time: "2016-11-10 09:40"},
	{temp: 51, time: "2016-11-10 09:50"},
    ]
}

2. 정상 범위를 벗어난 측정값을 찾는 함수

function readingsOutsideRange(station, min, max) {
	return station.readings.filter(r => r.temp < min || r.temp > max);
}

3. 호출문

alerts = readingsOutsideRange(station, 
operatingPlan.temperatureFloor, // 최저 온도
operatingPlan.temperatureCeiling); // 최고 온도
  • operatingPlan의 데이터 항목 두 개를 쌍으로 가져와서 readingsOutsideRange()로 전달한다.
  • operatingPlan은 범위의 시작과 끝 이름을 readingsOutsideRange() 와 다르게 표현한다.
  • 범위 range 는 객체 하나로 묶어 표현하는 게 나은 대표적인 예다.

리팩토링

1. 묶은 데이터를 표현하는 클래스 선언

class NumberRange {
	constructor(min, max) {
		this._data = {min: min, max: max};
	}
	get min() {return this._data.min;}
	get max() {return this._data.max;}
}
  • 객체가 아니라 클래스를 사용한 이유 : 이 리팩토링 방식은 새로 생성한 객체로 동작까지 옮기는 더 큰 작업의 첫 단계로 수행될 때가 많기 때문이다.
  • 값 객체로 만들 가능성이 높기 때문에 setter는 만들지 않는다.

2. 새로 만든 객체를 readingsOutsideRange() 의 매개변수로 추가하도록 함수 선언 변경

function readingsOutsideRange(station, min, max, range) {
	return station.readings.filter(r => r.temp < min || r.temp > max);
}

3. 온도 범위를 객체 형태로 전달하도록 호출문 수정

const range = new NumberRange(operatingPlan.temperatureFloor, operatingPlan.temperatureCeilng);
alerts = readingsOutsideRange(station, 
    operatingPlan.temperatureFloor, 
    operatingPlan.temperatureCeiling,
    range); 

4. 기존 매개변수 사용하는 부분 변경

함수 선언부

function readingsOutsideRange(station, range) {
	return station.readings.filter(r => r.temp < range.min || r.temp > range.max);
}

함수 호출부

const range = new NumberRange(operatingPlan.temperatureFloor, 
operatingPlan.temperatureCeilng);
 
alerts = readingsOutsideRange(station, range);