[리팩터링 2판] 11. API 리팩터링

Ash·2021년 12월 19일
0

11.1 질의 함수와 변경 함수 분리하기

겉보기 부수효과가 있는 함수와 없는 함수는 명확히 구분하는 것이 좋다.

11.2 함수 매개변수화하기

두 로직이 아주 비슷하고 단지 리터럴 값만 다르다면 다른 값만 매개변수로 받아 처리하는 방법을 사용하면 중복을 해결할 수 있다.

// bad case
function tenPercentRaise(aPerson) {
	aPerson.salary = aPerson.salary * 1.1;
}

function fivePercentRaise(aPerson) {
	aPerson.salary = aPerson.salary * 1.05;
}

// good case
function raise(aPerson, factor) {
	aPerson.salary = aPerson.salary * (1 + factor);
}

11.3 플래그 인수 제거하기

플래그 인수: 호출되는 함수가 실행할 로직을 호출하는 쪽에서 선택하기 위한 전달인수

// bad case
function  setDimension(name,value) {
	if (name === "height") {
    	this._height = value;
        return ;
    }
    if (name === "width") {
    	this._width = value;
        return;
    }
}

// good cse
function setHeight(value) {
	this._height = value;
}

function setWidth(value) {
	this._width = value;
}

11.4 객체 통째로 넘기기

하낭의 레코드에서 값 2개 이상을 가져와 인수로 넘기는 경우 레코드를 통째로 넘기는 것이 좋다.
단, 객체로부터 값 몇개를 얻은 후 그 값들만으로 무언가를 하는 로직이 있다면, 그 로직을 객체 안으로 집어넣어야 함을 알려주는 악취로 봐야한다.

// bad case
const low = aRoom.daysTempRange.low;
const high = aRoom.daysTempRange.high;
if (aPlan.withRange(low, high))

// good case
if (aPlan.withRange(aRoom.daysTempRange))

11.5 매개변수를 질의 함수로 바꾸기

// bad case
availableVacation(anEmployee, anEmployee.grade);

function availableVacation(anEmployee, grade) {
// 연휴 계산
}

// good case
function availableVacation(anEmployee) {
	const grade = anEmployee.grade;
}

매개변수를 제거하면 값을 결정하는 책임 주체가 달라진다.
매개변수가 있다면 결정 주체는 호출자가, 매개변수가 없다면 결정 주체는 피호출 함수가 된다.
매개변수를 질의 함수로 변경하면 안되는 경우
매개 변수를 제거하면 피호출 함수에 원치 않는 의존성이 생기는 경우

11.6 질의 함수를 매개변수로 바꾸기

함수 안에 두기에 적절하지 않은 참조가 있는 경우 매개변수로 바꾸자

// bad case
targetTemparature(aPlan)

function targetTemparature(aPlan) {
	currentTemparature = thermostat.currentTemparature;
}

// good case
targetTemparature(aPlan, thermostat.currentTemparature);

function targetTemparature(aPlan, currentTemparature) {

}

참조 투명성: 똑같은 값을 건네면 매번 똑같은 결과를 내는 경우

11.7 세터 제거하기

// bad case
class Person {
	get name() {}
   	set name(aString) {}
}

// good case
class Person {
	get name() {}
}

세터 메서드가 있다는 뜻 -> 필드가 수정될 수 있다는 뜻
객체 생성 후 수정되지 않기를 원하는 필드가 있다면 세터를 제공하지 않을 것이다. (불변으로 만들기 위함)

세터 제거가 필요한 2가지 경우
1. 사람들이 무조건 접근자 메서드를 통해서만 필드를 다루려 할 때
2. 클라이언트에서 생서어 스크립트를 사용해 객체를 생성할 때
-> 스크립트가 완료된 뒤 객체의 필드 혹은 전부가 변경되지 않기를 기대함.

11.8 생성자를 팩터리 함수로 바꾸기

// bad case
const leaEngineer = new Employee(document.leadEngineer, 'E');

// good case
const leaEngineer = new createEngineer(document.leadEngineer);

function createEngineer(name) {
	return new Employee(name, 'E');
}

11.9 함수를 명령으로 바꾸기

11.10 명령을 함수로 바꾸기

11.9와 11.10은 반대되는 리팩토링 개념으로 비교하면서 읽어야 이해하기쉽다.
함수가 하나의 정해진 일을 수행하고 그 로직이 복잡하지 않다면 11.10 명령을 함수로 바꾸기 방법이 적절하며,
로직이 복잡하고 함수에서 다양한 일을 한다면 11.9 함수를 명령으로 바꾸기방법이 적절하다.
소스코드를 보고 이해하기.

11.11 수정된 값 반환하기

// bad case
let totalAscent = 0;
calculateAsscent();

function calculateAsscent() {
	for(let i=1; i<points.length; i++) {
    	const verticalChange = points[i].elevation - points[i-1].elevation;
        totalAscent += (verticalChange > 0) ? verticalChange : 0;
    }
}
// good case
const totalAscent = calculateAsscent();
function calculateAsscent() {
	let result = 0;
	for(let i=1; i<points.length; i++) {
    	const verticalChange = points[i].elevation - points[i-1].elevation;
        result += (verticalChange > 0) ? verticalChange : 0;
    }
    return result;
}

상위에 변수를 이미 선언하고 아래 함수에서 이미 선언된 변수의 값을 변경시키는 방식 -> 함수를 미리 뜯어보지 않는 이상 변수의 값이 어디서 변화되는지 찾기 힘들다.
(개인적으로 리팩토링 단계보다는 처음 코드를 짤 때부터 당연히 적용되어야하는 방식이라고 생각함.)

11.12 오류 코드를 예외로 바꾸기

예외는 예상밖의 동작인 경우만 사용되어야한다. (정상 동작 범주가 아닌 경우)
정상 동작 되지 않을 것 같다면 예외 대신 오류를 검출하고 프로그램을 정상 흐름으로 되돌리게끔 처리해야한다. (무작정 throw 처리 X)

11.13 예외를 사전확인으로 바꾸기

예외는 11.12 처럼 예상밖의 동작인 경우에만 사용되어야한다.
무조건 예외를 던지는 것이 아니라, 예상되는 특정 상황의 경우는 조건을 검사해야한다.

// bad case
double getValueForPeriod (int periodNumber) {
	try {
    	return values[periodNumber];
    } catch(ArrayIndexOutOfBoundsException e) {
    	return 0;
    }
}
// good case
double getValueForPeriod (int periodNumber) {
	return (periodNumber >= values.length) ? 0 : values[periodNumber];
}

소스코드
https://github.com/yeoj1n/JS-study/blob/master/refactoring-study/chapter11/API%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81.js

profile
기록남기기👩‍💻

0개의 댓글