상세 컨텐츠

본문 제목

리팩토링 첫번째 시간

자바강좌/리팩토링

by somiyuralove 2020. 1. 5. 18:25

본문

* 본글은 " 자바로 배우는 리팩토링 입문 " (유키 히로시 지음, 서수환 옮김) 책을 참고하였음을 알려드립니다.

 

* 리팩토링( refactoring ) : 외부에서 보는 프로그램의 동작은 바뀌지 않고 프로그램 내부 구조를 개선
방대한 클래스가 있을때 뭉칠 수 있는 필드와 메서드를 따로 빼내서 새 클래스를 만듬 ( 클래스 추출 )

- 버그 수정은 리팩토링이 아님.
- 기능 추가는 리팩토링 아님.
- 소스정리(?) -> 소스코드를 정리하다가 프로그램의 동작에 변화가 생길수도 있음, 단순히 소스코드를 정리하는 것이 아니고
 외부에서 보는 프로그램에 변화가 없음을 확인해야 함.

리팩토링 하고 난 후 적어도 유닛테스트( 단위테스트) 수행.

* 리팩토링의 목적
- 버그를 발견하기 쉽게 함
- 기능을 추가하기 쉽게 함
- 리뷰하기 쉽게 만듬

* 리팩토링의 한계
- 프로그램이 정상적으로 아직 동작하지 않을때는 리팩토링을 하지 않는다.
- 납품기일이 촉박할때도 리팩토링을 하지 않는다. 리팩토링의 효과는 시간이 지나면서 나타나기 때문

* 리팩토링과 악취
- 악취가 나는 프로그램은 리팩토링의 고려 대상임.

* 코드의 악취

- 중복코드
- 너무 긴 메서드
- 방대한 클래스
- 과다한 매개변수
- 변경 발산 ( 사양 변경이 있을 때 수정 내용이 곳곳에 흩어져 있음)
- 변경 분산 ( 어떤 클래스를 수정하면 다른 클래스도 수정해야 함 )
- 속성, 조작 끼어들기
- 데이터 뭉치 ( 합쳐서 다뤄야 할 데이터가 한 클래스에 모여 있지 않음)
- 메서드 호출 연쇄가 너무 많음
- 중개자 ( 맡기기만 하고 자기는 일하지 않는 클래스)

* 리팩토링의 필수적인 고료사항
- 스텝바이스텝 ( 한번에 하나씩 리팩토링 )
- 되돌리기 쉽게
- 단계마다 확인
- 오래된걸 새로운것으로 바꿈

* 매직넘버를 기호 상수로 치환 ( Replace Magic Number with Symbolic Constant )
- 매직 넘버의 의미를 알기 어려움
- 매직 넘버는 수정하기 어려움

public class Robot {
private final String _name;

// 기존 코드스멜 방법
// public static final int COMMAND_WALK = 0;
// public static final int COMMAND_STOP = 1;
// public static final int COMMAND_JUMP = 2;

// RobotCommand 타입의 클래스를 적용한 방법
// public static final RobotCommand COMMAND_WALK = new RobotCommand("WALK");
// public static final RobotCommand COMMAND_STOP = new RobotCommand("STOP");
// public static final RobotCommand COMMAND_JUMP = new RobotCommand("JUMP");

// enum 방법
public enum Command {
WALK,
STOP,
JUMP,
}

public Robot(String name) {
_name = name;
}

// 코드스멜일때
// public void order(int command) {

// RobotCommand 타입의 클래스를 적용한 방법 
// public void order(RobotCommand command) {

// enum Type을 적용한 방법
public void order(Robot.Command command) {
// if(command == COMMAND_WALK) {
// System.out.println(_name + " walks.");
// } else if(command == COMMAND_STOP) {
// System.out.println(_name + " stops.");
// } else if(command == COMMAND_JUMP) {
// System.out.println(_name + " jumps.");
// } else {
// System.out.println("Command error. command = " + command);
// }

if(command == Command.WALK) {
System.out.println(_name + " walks.");
} else if(command == Command.STOP) {
System.out.println(_name + " stops.");
} else if(command == Command.JUMP) {
System.out.println(_name + " jumps.");
} else {
System.out.println("Command error. command = " + command);
}
}
}

 

 

public class Main {
public static void main(String[] args) {
Robot robot = new Robot("Andrew");

// 코드스멜
// robot.order(0); // work
// robot.order(1); // stop
// robot.order(1); // jump

// RobotCommand 사용
// robot.order(Robot.COMMAND_WALK); // work
// robot.order(Robot.COMMAND_STOP); // stop
// robot.order(Robot.COMMAND_JUMP); // jump

robot.order(Robot.Command.WALK); // work
robot.order(Robot.Command.STOP); // stop
robot.order(Robot.Command.JUMP); // jump
}
}

 

public class RobotCommand {
private final String _name;

public RobotCommand(String name) {
_name = name;
}

public String toString() {
return "[ RobotCommand: " + _name + " ]";
}
}

 

위의 프로그램은 코드리팩토링 중 매직넘버를 제거하는 예제입니다.

코드스멜 -> RobotCommand 타입으로 변환 -> enum 사용에 대한 내용을 확인하실 수 있습니다. 주석을 참고하세요.

 

위의 프로그램을 각각 실행해보면 눈치 빠르신분이라면 이해하실 수 있으실 겁니다.

 

그럼 즐코딩하세요. ^^;

관련글 더보기

댓글 영역