Skip to content

java 리팩토링에 대한 개념

리펙토링이 도대체 무엇일까?

Image title

그림 - 리펙토링

리팩토링 이란 프로그램의 실행 구조는 바뀌지 않으면서, 내부 구조를 변경하는 행위라고 생각하면 된다.

리팩토링을 하면서 얻을 수 있는 이점

리팩토링은 코드의 가독성1 및 편한 유지보수를 위해서도 사용이 가능하다. 아래의 예제를 살펴보자.

before.java
package com.fromitive.MyFirstPackage;
public class MultiplicationTable {
    void print() {
        for (int i = 1; i <= 9; i++) {
            System.out.printf("%d * %d = %d", 5, i, 5 * i).println();
        }
    }

    void print(int table) {
        for (int i = 1; i <= 9; i++) {
            System.out.printf("%d * %d = %d", table, i, table * i).println();
        }
    }

    void print(int table, int from, int to) {
        for (int i = from; i <= to; i++) {
            System.out.printf("%d * %d = %d", table, i, table * i).println();
        }
    }

    public static void main(String[] args) {
        MultiplicationTable multi = new MultiplicationTable();
        multi.print(); // execute print() method
        multi.print(6); // execute print(int form) method
        multi.print(8, 2, 18); // execute print(int table, int from, int to)
    }
}

main 메소드에서 각 print 메소드를 호출하는데, 요구사항이 아래와 같이 변경되었다고 가정해보자

* 를 X로 변경 필요

*를 X로 변경하는 것만으로도 print메소드 안의 코드를 3줄 수정해야 하는 작업이 발생하기 때문에, 리팩토링 작업으로 중복을 최소화하여 코드의 유지보수 및 가독성을 끌어올려야 한다.

그래야만, 코드를 수정할 때 시간을 절약할 수 있기 때문이다.

다음은 리펙토링을 진행하여 코드의 중복을 제거한 버전이다.

after.java
package com.fromitive.MyFirstPackage;
public class MultiplicationTable {
    void print() {
        print(5);
    }

    void print(int table) {
        print(table,1,9);
    }

    void print(int table, int from, int to) {
        for (int i = from; i <= to; i++) {
            System.out.printf("%d * %d = %d", table, i, table * i).println();
        }
    }

    // 코드의 구조가 변경되지 않음
    public static void main(String[] args) {
        MultiplicationTable multi = new MultiplicationTable();
        multi.print(); // execute print() method
        multi.print(6); // execute print(int form) method
        multi.print(8, 2, 18); // execute print(int table, int from, int to)
    }

이로써 main함수의 구조를 변경하지 않고 코드를 유지보수 하기 쉽게 그리고 읽기 쉽게 변경되었음을 볼 수 있다.

하지만, 개인적으로 5번째 줄처럼 무조건 중복을 제거하는게 맞는건지 판단이 서지 않는다. 왜냐하면 print() 함수를 분석할 때, print(int table)을 본 후 마지막으로 print(int table, int from, int to)를 분석해야 하기 때문이다.

메인으로 사용하는 함수만 분석할 수 있게 최종적으로 아래와 같이 리펙토링을 하면, 더욱 가독성 있게 보이지 않을까? 생각된다.

after2.java
package com.fromitive.MyFirstPackage;
public class MultiplicationTable {
    void print() {
        print(5,1,9); // print(int table, int from, int to) 만 분석할 수 있게 변경
    }

    void print(int table) {
        print(table,1,9);
    }

    void print(int table, int from, int to) {
        for (int i = from; i <= to; i++) {
            System.out.printf("%d * %d = %d", table, i, table * i).println();
        }
    }

    // 코드의 구조가 변경되지 않음
    public static void main(String[] args) {
        MultiplicationTable multi = new MultiplicationTable();
        multi.print(); // execute print() method
        multi.print(6); // execute print(int form) method
        multi.print(8, 2, 18); // execute print(int table, int from, int to)
    }



  1. 리펙토링은 코드의 가독성 뿐만아니라 유지보수를 쉽게 하는 것 이외에도 여러가지 이유가 있다. 하지만, 현재는 가독성 및 편한 유지보수에 이점에만 집중하였다. 

Comments