Search

Chapte06 - 메서드 정리

메서드 추출 : 코드 뭉치를 별도의 메서드로 빼내는 것
메서드 내용 직접 삽입 : 메서드 추출과 반대, 꺼내고 보니 제 역할을 못하거나 쪼갠 방식을 바꿔야 할 때
임시변수를 메서드 호출로 전환 : 없어도 되는 임시변수를 전부 제거
메서드를 메서드 객체로 전환 : 임시 변수가 너무 얽혀서 메서드 호출로 전환할 수 없을 때
매개변수로의 값 대입 제거 : 매개변수에다가 값을 직접 쓸 때
알고리즘 전환 : 메서드를 잘게 쪼갤 때

목차

메서드 추출

동기

메서드가 너무 길거나 코드에 주석을 달아야만 의도를 이해할 수 있을 때,
직관적인 이름의 간결한 메서드가 좋은 이유
메서드가 적절히 잘게 쪼개져 있으면 재사용성이 좋다.
재정의 하기 수월하다.
상위 계층의 메서드에서 주석 같은 더 많은 정보를 읽을 수 있다.
잘게 쪼개려면 일단 메서드 이름을 잘 지어야 함.
메서드명은 원리가 아니라 기능을 나타내는 이름이어야 함.
더 이해하기 쉬운 이름ㅇ로 추출하지 않을 바에는 차라리 추출하지 마라
가장 문제는 지역변수다.
임시변수 분리 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 메서드 호출을 담당하는 메서드로 바꾸자.

알고리즘 전환

동기

알고리즘을 더 분명한 것으로 교체해야할 땐, 해당 메서드의 내용을 새 알고리즘으로 바꾸자.
간단한 알고리즘이 있다면 그걸로 바꾸자.