Java 유지보수 코드 리팩토링 2

주어진 코드를 보고 유지보수가 가능한 코드로 만들어보자.

리팩토링 전

Dice.class

import java.util.Random;

public class Dice {

    public static void helloDice() {
        System.out.println("프로그램 시작");

        // 코드 시작
        int random = new Random().nextInt(6) + 1;
        System.out.println("주사위 굴린 결과: " + random);
        // 코드 종료
        
        System.out.println("프로그램 종료");
        System.out.println();
    }

    public static void helloSum() {
        System.out.println("프로그램 시작");

        // 코드 시작
        for (int i = 0; i < 3; i++) {
            System.out.println("i = " + i);
        }
        // 코드 종료
        
        System.out.println("프로그램 종료");
        System.out.println();
    }

    public static void main(String[] args) {
        helloDice();
        helloSum();
    }
}

프로그램 시작
주사위 굴린 결과: 5
프로그램 종료

프로그램 시작
i = 0
i = 1
i = 2
프로그램 종료

주어진 코드에서 중복을 발견할 수 있다. 중복이 아닌 코드는 외부에서 전달 받아 처리가 필요하다. 그렇지만 외부에서 받는 것은 문자열이 아닌 코드(for...)다.

리팩토링을 진행해보도록 한다.


리팩토링 후 - 정적 중첩 클래스 사용

Process.class

public interface Process {
    void run();
}

Dice.class

import org.w3c.dom.ls.LSOutput;

import java.util.Random;

public class Dice {

    public static void hello(Process proc) {
        System.out.println("프로그램 시작");

        // 코드 시작
        proc.run();
        // 코드 종료

        System.out.println("프로그램 종료");
        System.out.println();
    }

    static class ThrowDice implements Process{
        @Override
        public void run() {
            int random = new Random().nextInt(6) + 1;
            System.out.println("주사위 굴린 결과: " + random);
        }
    }

    static class Sum implements Process{
        @Override
        public void run() {
            // 코드 시작
            for (int i = 0; i < 3; i++) {
                System.out.println("i = " + i);
            }
            // 코드 종료
        }
    }

    public static void main(String[] args) {
        Dice dice = new Dice();
        dice.hello(new ThrowDice());
        dice.hello(new Sum());
    }
}

프로그램 시작
주사위 굴린 결과: 2
프로그램 종료

프로그램 시작
i = 0
i = 1
i = 2
프로그램 종료

리팩토링 진행 단계

  • 프로그램 시작과 종료를 출력하는 부분을 구분한다.
  • 코드의 시작과 종료부분이 변해야하는 부분이다.
  • 코드의 시작과 종료 부분을 외부에서 전달 받도록 한다.

코드를 외부에서 전달하는 방법

코드에서 공통된 기능으로 메소드 사용할 것이므로 Process 인터페이스를 만들어 공통으로 run() 함수로 가상 순수 함수로 만들었다.

호출 부에서는 인스턴스를 생성하고 전달해 인터페이스에 정의된 메소드를 실행한다.

  • ThrowDice, Sum 클래스를 만들어 Process 인터페이스로 상속받아 run() 메소드를 각자 구현하였다.
  • Dice 클래스는 정적 중첩 클래스로 사용하였다.
    • 정적 중첩 클래스 뿐 아니라 내부 클래스, 익명 클래스 및 지역 클래스에도 사용할 수 있다.

리팩토링 학습 정리

  • 문자열 데이터를 전달할 때는 String, int 와 같은 타입을 전달하면 되었다.
  • 코드를 메소드로 전달시에는 호출부에서 인스턴스를 받아와 메소드를 호출하여 처리한다.