데이터 항목 여러 개가 이 함수에서 저 함수로 함꼐 몰려다니는 경우를 자주 본다. 나는 이런 데이터 무리를 발견하면 데이터 구조 하나로 모아주곤 한다.
데이터 뭉치를 데이터 구조로 묶으면 데이터 사이의 관계가 명확해진다는 이점을 얻느낟. 게다가 함수가 이 데이터 구조를 받게 하면 매개변수 수가 줄아든다. 같은 데이터 구조를 사용하는 모든 함수가 원소를 참조할 때 항상 똑같은 이름을 사용하기 때문에 일고나성도 높여준다.
하지만 이 리펙터링의 진정한 힘은 코드를 더 근본적으로 바꿔준다는 데 있다. 나는 이런 데이터 구조를 새로 발견하면 이 데이터 구조를 활용하는 형태로 프로그램 동작을 재구성한다. 데티어 구조에 담길 데이터에 공통으로 적용되는 동작을 추출하여 함수로 만드는 것이다(공용 함수를 나열하는 식으로 작성할 수도 있고, 이 함수들과 데이터를 합쳐 클래스로 만들 수도 있다). 이 과정에서 새로 만든 데이터 구조가 문제 영역을 훨씬 간결하게 표현하는 새로운 추상개념으로 격상되면서, 코드의 개념적인 그림을 다시 그릴 수도 있다. 그러면 놀라울 정도로 강력한 효과를 낸다. 하지만 이 모든 것의 시작은 매개변수 객체 만들기부터다.
const station = {
name: "281",
readings: [
{temp: 47, time: "2021-12-10 09:10"},
{temp: 53, time: "2021-12-10 09:10"},
{temp: 58, time: "2021-12-10 09:10"},
{temp: 41, time: "2021-12-10 09:10"},
{temp: 42, time: "2021-12-10 09:10"},
{temp: 48, time: "2021-12-10 09:10"},
]
};
function readingOutsideRange(station, min, max) {
return station.readings.filter(r =>
r.temp < min || r.temp >max);
}
alerts = readingsOutsideRange(station,
operatingPlan.temperatureFloor,
operatingPlan.temperatureCelling);
class NumberRange {
constructor(min, max) {
this._data = {min: min, max: max};
}
get min() {return this._data.min;}
get max() {return this._data.max;}
}
const range = new NumberRange(operatingPlan.temperatureFloor,
operatingPlan.temperatureCelling);
function readingsOutsideRange(station, range) {
return station.readings
.filter(r => r.temp < range.min|| r.temp > range.max);
}
alerts = readingsOutsideRange(station, range);
마틴 파울러 저 리팩터링 2판