제공 : 한빛 네트워크
저자 : Marcelo Giorgi
역자 : 백기선
원문 : Refactoring in Eclipse 3.2
서론
소프트웨어 개발에 있어서 가장 힘들 부분은 유지보수 작업 즉, 시간이 지남에 따라 탄력적으로 반응할 수 있는 역량입니다. 따라서 코드를 단순하고 깨끗하게 유지해야 합니다. 그렇기 때문에 원래는 단순하지만 인간이라는 특성 때문에 복잡해 보이는 코드를 이해하느라 많은 시간을 소비하는 대신 다른 대안을 찾아야 합니다.
Clean Up 마법사
그 작업을 게으르게 하고 있다고 느낄 수 있으면서도 소프트웨어의 품질을 향상 시키는 많은 작업을 자동화 하는 것이 아래에 있는 마법사의 의도이자 목표입니다.
[그림 1]
위 [그림 1]에 보이는 마법사는 코드를 깨끗하게 하기 위한 네 개의 메인 작업을 가지고 있습니다. Code Style, Member Access, Unnecessary Code, Missing Code탭이 있습니다.
개발 팀의 규모가 큰 경우 각 개발자들의 경험들이 각기 다르기 때문에 코딩 스타일의 일관성을 유지하기 힘들 수 있습니다. 그런 형태의 코드를 그대로 사용하는 것은 코드의 유지보수를 힘들게 하기 때문에 바람직하지 못합니다. 사람의 제한된 뇌로 다양한 코딩 습관을 유지 보수 하는 것은 심각한 효율성 저하를 야기 합니다. 따라서 위의 그림에 Code Style탭이 들어있는 것은 코드를 특정 모양으로 수정하기 위한 것입니다.
- Control statements
간단한 예로 if/while/for/do 다음에 있는 한 문장을 항상 블록으로 감싸지도록 또는 절대로 감싸지 않도록 설정 할 수 있습니다. 비슷한 방법으로 “Convert for loops to enhanced” 옵션을 체크하여 for 문을 Java 1.5 스타일로 바꿀 수 있습니다. 이 방법을 사용하여 다운 캐스팅(down-cast) 하는 횟수와 코드의 줄 수를 줄일 수 있습니다.
- Expressions
코드 상에 괄호를 모든 경우에 사용하도록 할 수도 있고 꼭 필요할 때만 사용하게 할 수 있습니다. Expressions 패널에서 적당한 라이오 버튼을 클릭하여 설정할 수 있습니다.
- Variable declarations
가능하면 final 변수를 사용하는 것이 컴파일러 최적화를 위해 좋습니다. 따라서 마법사에 변수(인스턴스 변수, 파라미터 값과 지역 변수)의 선언 부분에 final을 붙여 주는 기능이 있습니다.
Members Access
메소드 안에서 사용하는 객체의 속성들을 빨리 알아내는 방법은 this 키워드를 사용하는 것입니다(게다가 이 방법은 객체의 파라미터를 구분 하는데 도움을 줍니다.). 따라서 마법사의 새 기능을 통해 this 키워드를 필드나 메소드에 붙이도록 설정할 수 있습니다. 예를들어:
private int value;
public int get() {
return this.value + value;
}
만약 “Use ‘this’ qualifier for field access” 속성을 체크하면 다음과 같이 바뀝니다:
private int value;
public int get() {
return this.value + this.value;
}
또 다른 유용한 기능으로 static 멤버와 메소드를 하나의 클래스로 통합할 수 있습니다. 그렇게 만든 클래스에 어떻게 접근 할 지 설정할 수 있습니다.
- 하위타입으로 접근하기
- 객체를 사용하여 접근하기
게다가 “Qualified field class” 와 “Qualified methods access” 체크박스를 선택하면 적당한 방법으로 static 필드와 메소드에 접근할 수 있습니다. 아래 Eclipse 예제는 그것들을 모두 선택했을 때를 보여줍니다.
class E {
public static int NUMBER;
public static void set(int i) {
E.NUMBER= i;
}
public void reset() {
E.set(0);
}
}
class ESub extends E {
public void reset() {
E.NUMBER= 0;
}
}
Unnecessary Code
가장 중요해 보이는 마법사의 기능 중에 하나로, 작성한 코드 중에서 사용되지 않는 코드(수정하려고 할 때 항상 골칫거리 입니다.)를 효율적으로 처리할 수 있도록 해줍니다. 예를 들어, 마법사를 사용하여 필요 없는 import 문이나 private 멤버나 로컬 변수들을 제거하도록 할 수 있습니다.
대부분의 경우 실제 필요한 것 보다 더 자주 캐스팅을 사용합니다. 이쯤 되면 눈치 챘을 수 있겠지만 “Unnecessary code” 패널의 “Remove unnecessary cast” 체크박스를 클릭하면 코드에서 필요 없는 코드를 제거해 줍니다.
아시다시피 일부 문자열을 프로퍼티 파일을 사용하여 외부로 빼내고 싶을 때 Source > “Externalize Strings...”를 사용해 봤을 것입니다. 그렇게 하면 별로 관심도 없는 //$NON-NLS$ 이런 키워드를 해당 문자열의 끝에 자동으로 붙여 줍니다. 코드를 계속 개선 시키다 보면 이런 특수한 키워드들이 문자열과 상관없이 존재하는 것을 발견할 수 있습니다. 그런 키워드들은 제거해 주는 것이 좋으며 “Unnecessary code” 패널의 “Unnecesarry $NON-NLS$” 체크박스를 사용하여 그렇게 할 수 있습니다.
Missing Code
Java 5.0에서 흔히 @Override와 @Deprecated 어노테이션을 자주 사용합니다. 이 것들 매우 유용한데, Override 어노테이션의 경우 실제 오버라이딩을 했는지 확인 해주기 때문입니다. 따라서 이런 어노테이션들이 가능한 곳에 모두 사용하는 것이 유용합니다. 마법사의 “Missing Code” 의 적절한 체크박스를 사용하여 그렇게 하도록 설정할 수 있습니다.
또한 Serializable 인터페이스를 구현한 객체의 versionID를 정의하는 것을 권장합니다. 그렇게 함으로써 해당 클래스가 직렬화 할 때 잘못 사용되지 않도록 방지할 수 있습니다.
Introduce Indirection 리팩토링
대부분 소프트웨어 개발을 진행하면서 배포한 클래스의 행위나 특정 메소드를 수정하게 됩니다. 만약 AOP(Aspect Oriented Programming)가 필요한 상황이 아니거나 minor change 일 때 는 기존에 만든 메소드를 수정할 것입니다. 아니면 “ Introduce Indirection…”를 사용하여 새로운 메소드를 호출하도록 수정할 수 있습니다. 그렇게 하면 이전에 참조하고 있던 메소드를 호출하는 새로운 메소드가 만들어집니다.
이 기능은 아래와 같은 경우에 유용하게 사용할 수 있습니다:
- 라이브러리로부터 제공하는 메소드이기 때문에 변경할 수 없을 때
- API의 메소드이기 때문에 변경할 수 없을 때
- 해당 코드는 그대로 유지하면서 그 코드 전이나 후에 무언가를 추가하고 싶을 때
이 기능을 사용하는 일반적인 방법으로 다음과 같은 메소드를 가지고 있을 때:
public AgentComunication getCommunicationStatus(String path) {
...
}
이 기능을 사용하기 위해서 Refactor > Introduce Indirection 을 실행할 수 있고 ‘Introduce Indirection’ 창이 뜨면 새로운 메소드 이름을 입력합니다.
[그림 2]
그런 다음 예전 코드를 호출하고 있는 새로 만들어진 메소드 내부에 추가하고 싶은 행동을 넣으면 됩니다.
public static AgentComunication getCommunicationStatusWithSecurityCheck
(CommunicationDAOImpl communicationDAOImpl, String agentPath) {
//Security check
...
return communicationDAOImpl.getCommunicationStatus(agentPath);
이런 방법을 통해 메소드들간의 밀집도를 높일 수 있습니다.
Extract Superclass 리팩토링
여러 클래스들에 걸쳐있는 몇몇 기능들이 중복되어 있는 끔찍한 모습을 자주 볼 수 있습니다. 이 문제를 해결하기 위해 가장 먼저 떠오르는 방법은 상위 클래스에서 여러 클래스에 공통적으로 존재하는 행위를 캡슐화 하는 것입니다. 이 때 그 클래스들을 기반으로 상위 클래스를 만들어 주는 Eclipse에 새로 추가한 기능인 “Extract Superclass”를 사용합니다.
[그림 3]
이 기능을 사용하기 위해서는 중복되는 기능을 가진 클래스들 중에서 하위 클래스처럼 처리 할 클래스를 선택해야 합니다. Figure 3은 이 기능을 할 수 있는 마법사를 보여줍니다. 하위 클래스가 될 클래스를 선택했을 때 이런 화면을 볼 수 있으며 상위 클래스를 상속하는 메소드를 선택할 수 있도록 아래에 있는 테이블에 표시가 됩니다.
상위 클래스에 새로 만들 메소드의 형태를 지정할 수 있습니다.
- 하위 클래스로부터 구현된 것을 추출하거나
- 상위 클래스에 추상 메소드를 만들 수 있습니다.
역자 백기선님은 AJN(
http://agilejava.net)에서 자바 관련 스터디를 하고 있는 착하고 조용하며 점잖은 대학생입니다.
요즘은 특히 Spring과 Hibernate 같은 오픈소스 프레임워크를 공부하고 있습니다. 공부한 내용들은 블로그(
http://whiteship.tistory.com)에 간단하게 정리하고 있으며 장래 희망은 행복한 개발자입니다.