[Java]if-else 리팩토링

오늘 회사에서 업무중에 아무 생각없이 if-else 중첩으로 코딩하고 “기능적으로”  잘

돌아가는 것을 확인한 뒤, 해당 업무를 접으려고 했습니다.

그런데 문득 이런 생각을 해보았습니다.

왜 맨날 분기로직은 if-else로만 짜야할까… 과연 내가 아닌 다른 사람이

내 코드를 유지보수한다면 저걸 얼마나 이해하고 작업할 수 있을까

그래서 과감하게 if-else 로직을 걷어내고 리팩토링 하기로 결정하고 구글링을 통해 그런

사례가 있는지 찾아서 테스트코드를 만들었습니다.

아래 참고 url은 꼭 한번 읽어보시기 바랍니다.

소소코드참고 url에서 다운받아서 인터페이스를 구현한 enum class의 메서드에서

String Object를 리턴하도록 약간 수정하였습니다.

1. 먼저 기존 if-else class입니다.

public class IfThenElse {

    public String invoke(String operationName) {
    	String result = null;

        if (StringUtils.equals(operationName, "operation1")) {
            result = operation1();
        } else if (StringUtils.equals(operationName, "operation2")) {
        	result = operation2();
        } else if (StringUtils.equals(operationName, "operation3")) {
        	result = operation3();
        }

        return result;
    }

    public String operation1() {
    	return "operation_1";
    }

    public String operation2() {
    	return "operation_2";
    }

    public String operation3() {
    	return "operation_3";
    }
}

2. 두번째로 if-else 분기문을 enum 클래스로 리팩토링한 코드입니다.

public class NewIfThenElse {

    private interface IOperation {
        String apply(String name);
    }

    private enum Operation implements IOperation {

        OPERATION_1("operation1") {
            public String apply(String name) {
                return "operation_1";
            }
        },
        OPERATION_2("operation2") {
            public String apply(String name) {
            	return "operation_2";
            }
        },
        OPERATION_3("operation3") {
            public String apply(String name) {
            	return "operation_3";
            }
        };

        private static Map<String, Operation> requestLookup;

        static {
            requestLookup = new HashMap<String, Operation>(3);
            requestLookup.put(OPERATION_1.getName(), OPERATION_1);
            requestLookup.put(OPERATION_2.getName(), OPERATION_2);
            requestLookup.put(OPERATION_3.getName(), OPERATION_3);
        }

        private final String name;

        private Operation(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return "Operation{" + "name='" + name + '\'' + '}';
        }

        public static Operation getOperationByName(String name) {
            return requestLookup.get(name);
        }
    }

    public String invoke(String operationName) {
    	String result = null;
        Operation operation = Operation.getOperationByName(operationName);
        if (operation != null) {
            result = operation.apply(operationName);
        }

        return result;
    }
}

3. 마지막으로 저 두개의 클래스를 단위테스트하는 코드입니다.

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * if-else Refactoring 테스트케이스
 *
 * @author bluepoet
 *
 */
public class IfElseRefactoringTest {
	Logger logger = LoggerFactory.getLogger(IfElseRefactoringTest.class);
	private String result;

	@Test
	public void procedural() {
		IfThenElse obj = new IfThenElse();

		result = obj.invoke("operation2");
		logger.debug("결과 : {}", result);
		assertThat(result, is("operation_2"));
	}

	@Test
	public void refactor() {
		NewIfThenElse obj = new NewIfThenElse();
		result = obj.invoke("operation1");

		result = obj.invoke("operation1");
		logger.debug("결과 : {}", result);
		assertThat(result, is("operation_1"));
	}

}

단위테스트 결과는 물론, 녹색막대가 뜨며 두개의 메서드 모두 통과로 나옵니다.

로그도 위와같이 console창에서 출력됩니다.

이번에 리팩토링을 진행하면서 기존의 if-else문 자체를 완벽히 거둬내지는 못했지만,

관심대상을 별도의 클래스로 분리해 독립적으로 구현하는 것에는 일부분 성공했습니다.

OOP적인 부분에서는 절반의 성공은 했다고 생각됩니다.

그리고 기존의 코드를 최대한 안 건드리려고 한 부분도 일부분은 만족스럽게 구현했구요.

이것도 예제의 일부분일 뿐이고, 아마 더 좋은 구현사례가 많이 있을 것입니다.

혹시 좋은 리팩토링 사례가 있다면 댓글 남겨주시구요.

오늘 회사 선배개발자님과 커피를 마시며 한 대화중에 떠오르는 말이 있네요

리팩토링은 새로운 기능을 개발할 때 할 수 있는게 아니라 비교적 여유가 있을 때,

기존의 코드를 고치며 하는 것이 더 바람직하다. 그리고 오히려 그렇게 리팩토링을

하는 것이 실력향상에 더 도움이 된다.

리팩토링의 길은 멀고도 험하지만, 그것을 해냈을 때 프로그래머로써 느끼는 “쾌감“은

다른 무엇과도 비교할 수 없는 달콤한 열매겠죠? ^^

*참고 url

Advertisements

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

w

%s에 연결하는 중