•
메서드 추출 : 코드 뭉치를 별도의 메서드로 빼내는 것
•
메서드 내용 직접 삽입 : 메서드 추출과 반대, 꺼내고 보니 제 역할을 못하거나 쪼갠 방식을 바꿔야 할 때
•
임시변수를 메서드 호출로 전환 : 없어도 되는 임시변수를 전부 제거
•
메서드를 메서드 객체로 전환 : 임시 변수가 너무 얽혀서 메서드 호출로 전환할 수 없을 때
•
매개변수로의 값 대입 제거 : 매개변수에다가 값을 직접 쓸 때
•
알고리즘 전환 : 메서드를 잘게 쪼갤 때
목차
메서드 추출
동기
•
메서드가 너무 길거나 코드에 주석을 달아야만 의도를 이해할 수 있을 때,
•
직관적인 이름의 간결한 메서드가 좋은 이유
◦
메서드가 적절히 잘게 쪼개져 있으면 재사용성이 좋다.
◦
재정의 하기 수월하다.
◦
상위 계층의 메서드에서 주석 같은 더 많은 정보를 읽을 수 있다.
•
잘게 쪼개려면 일단 메서드 이름을 잘 지어야 함.
•
메서드명은 원리가 아니라 기능을 나타내는 이름이어야 함.
◦
더 이해하기 쉬운 이름ㅇ로 추출하지 않을 바에는 차라리 추출하지 마라
•
가장 문제는 지역변수다.
◦
임시변수 분리 or 임시 변수를 메서드 호출로 전환 등
방법
•
코드 뭉치를 잘라서 새로운 메서드로 만드는 것이다.
•
가장 문제 되는 것은 지역 변수들임
•
이 때, 지역변수가 읽히기만 하고 변경되지 않을 때는 새로 만드는 매서드의 매개변수로 전달.
•
임시변수의 갑이 변경될 때도 있다.
•
임시변수가 추출한 코드 내에서만 사용될 때, 기존 메서드에서 제거하고 새로운 메서드로 이동해서 사용하면 됨.
•
그렇지 않다면 새로운 메서드에서 값을 반환해도록 변경해야함
•
임시변수에 많은 일이 일어난다면 매개변수로 전달해내야한다.
메서드 내용 직접 삽입
동기
•
메서드 기능이 너무 단순해서 메서드명만 봐도 너무 뻔할 땐, 메서드를 합치자.
•
‘메서드 객체로 전환' 기법을 적용하기 전에 이 기법부터 실시하면 좋을 때가 많다.
방법
•
메서드가 재정의되어 있지 않은지 확인하자
◦
재정의되어 있다면 직접 삽입을 실시하면 안 된다.
•
메서드를 호출하는 부분을 모두 찾자
•
메서드 내용으로 교체
•
테스트를 실시
•
메서드 정의 삭제
임시변수 내용 직접 삽입
동기
•
간단한 수식을 대입받는 임시변수로 인해 다른 리팩토링 기법 적용이 힘들 땐, 임시변수를 찹조하는 부분을 전부 수식으로 치환하자.
•
임시변수를 메서드 호출로 전환 기법을 실시하는 도중 병용하게 되는 경우가 많다.
•
이것만 사용하게 되면 오직 메서드 호출의 결과값이 임시 변수에 대입될 때분이다.
•
하지만 임시변수가 메서드 추출 등 다른 리팩토링에 방해가 된다면 임시변수 내용 직접 삽입을 적용해야 함.
double basePrice = anOrder.basePrice();
return (basePrice > 1000);
--------
return (anOrder.basePrice() > 1000);
Java
복사
임시변수를 메서드 호출로 전환
동기
•
수식의 결과를 저장하는 임시변수가 있을 땐, 그 수식을 빼내어 메서드로 만든 후, 임시 변수 참조 부분을 전부 수식으로 교체하자. 새로 만든 메서드는 다른 메서드에서도 호출 가능함.
•
임시변수는 일시적이고 적용이 국소적 범위로 제한된다는 단점이 있다. 임시변수는 자신이 속한 메서드 안에서만 인식되므로, 그 임시변수에 접근하려다 보면 코드는 길어지게 마련이다.
•
클래스 안 모든 메서드가 그 정보에 접근할 수 있도록 메서드로 분리를 하자.
•
대부분의 경우 메서드 추출을 적용하기 전에 적용해야 함.
•
지역변수가 많을 수록 메서드 추출이 힘들어지므로 최대한 많이 메서드 호출로 고쳐야 한다.
•
가장 간단한 상황
◦
임시 변수 값이 한 번만 대입되고 대입문을 이루는 수식에 문제가 없을 때
◦
‘임시 변수 분리'나 ‘상태 변경 메서드와 값 반환 메서드를 분리’를 먼저 적용해야할 때도 있다.
double basePrice = _quantity * _itemPrice;
if(basePrice > 1000)
return basePrice * 0.95;
else
return basePRice * 0.98;
-----------------------
if(basePrice() > 1000)
return basePrice() * 0.95;
else
return basePrice() * 0.98;
double basePrice(){
return _quantity * _itemPrice;
}
Java
복사
방법
•
값이 한 번만 대입되는 임시변수를 찾자
◦
여러 번 대입되면 ‘임시 변수 분리' 기법 실시를 고려하자.
•
임시변수를 final로 선언
•
우변을 빼내어 메서드로 만들자.
◦
private 우선으로, 나중에 접근 제한을 완화하면 됨.
◦
객체 변경 등의 문제가 있다면, ‘상태 변경 메서드와 값 반환 메서드를 분리' 기법을 실시
직관적 임시변수 사용
동기
•
사용된 수식이 복잡할 땐 수식의 결과나 수식의 일부분을 용도에 부합하는 직관적 이름의 임시변수에 대입하자
•
수식이 너무 복잡해져서 이해하기 힘들 수 있다.
◦
이럴 때는 임시변수를 사용해서 수식을 더 처리하기 쉽게 쪼개자.
◦
조건문에서 각 조건절을 가져와서 직관적 이름의 임시변수를 사용해 그 조건의 의미를 설명하려 할 때 많이 사용.
◦
긴 알고리즘에서 임시변수를 사용해서 계산에 각 단계를 설명할 때
•
임시 변수를 남용하지 말자.
•
근데 왜 사용하냐?
◦
어떤 경우에는 덜 지저분하게 만들 수 있다.
◦
임시변수보다 더 좋은 방법을 강구한다.
▪
최대한 메서드 추출
▪
임시변수를 메서드 호출로 변환
◦
지역변수로 인해 메서드 추출이 힘들 때 사용하자!
if( (platform.toUpperCase().indexOf("MAC") > -1 )
&& (browser.toUpperCase().indexOf("IE") > -1 )
&& wasInitialized() && resize > 0 )
{
//기능 설명
}
----------------------------
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = platform.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if(isMacOs && isIEBrowser && wasInitialized() && wasResized){
//기능 코드
}
Java
복사
임시변수 분리
•
루프 변수나 값 누적용 임시변수가 아닌 임시 변수에 여러 번 값이 대입될 땐, 대입마다 다른 임시변수를 사용하자.
double temp = 2*(_height * _width);
System.out.println(temp);
temp = _height * _width;
System.out.println(temp);
------------------------
final double permieter = 2 * (_height + _width);
System.out.println(perimeter);
final double area = _height * _width;
System.out.println(area);
Java
복사
•
사용하다보면 임시변수에 값이 여러번 대입될 수 있다.
◦
값 누적용이나, 루프 변수는 제외한다.
•
계산 결과를 나중에 간편하게 참조할 수 있게 저장하는 용도로 사용하려면, 한 번만 대입되야한다.
•
값이 두번 대입된다는 것은 용도가 여러 번이라는 뜻.
매개변수로의 값 대입 제거
•
매개변수로 값을 대입하는 코드가 있을 땐, 매개변수 대신 임시변수를 사용하게 수정하자.
int discount (int inputVal, int quantity, int yearToDate){
if(inputVal > 50) inputVal -= 2;
}
------------------------------
int discount(int inputVal, int quantity, int yearToDate){
int result = inputVal;
if(inputVal > 50) result -= 2;
}
Java
복사
•
매개변수로 전달받은 객체에 어떠한 처리를 하든 상관없고 일상적인 작업이지만, foo 값을 다른 객체의 참조로 변경하는 것은 절대 안된다.
•
‘값을 통한 전달'과 ‘참조를 통한 전달'을 혼동하게 된다.
•
자바는 매개변수를 final로 선언할 수 있다. 이에 값 대입은 불가능하면서 매개변수가 참조하는 객체를 변경하는 것은 가능하다.
메서드를 메서드 객체로 전환
동기
•
지역변수 때문에 메서드 추출을 적용할 수 없는 긴 메서드가 있을 땐, 메서드 자체를 객체로 전환해서 모든 지역변수를 필드로 만든다. 그런 다음 객체 안의 여러 메서드로 쪼개면 된다.
•
지역변수를 계속 사용하려면 매개변수로 전달해야하니까 그렇구나.
방법
•
전환할 메서드의 이름과 같은 이름으로 새 클래스를 생성
•
원본 메서드가 들어있던 객체를 나타내는 final 필드를 추가하고, 원본 메서드 안의 임시변수와 매개변수에 해당하는 속성을 추가
•
새 클래스에 원본 객체와 각 매개변수를 받는 생성자 메서드를 작성하자
•
새 클래스에 compute라는 이름의 메서드를 작성
•
원본 메서드 내용을 복사해넣자.
•
원본 메서드를 새 객체 생성과 compute 메서드 호출을 담당하는 메서드로 바꾸자.
알고리즘 전환
동기
•
알고리즘을 더 분명한 것으로 교체해야할 땐, 해당 메서드의 내용을 새 알고리즘으로 바꾸자.
•
간단한 알고리즘이 있다면 그걸로 바꾸자.