▶ 리팩토링(Refactoring) 


1. refactoring 이란?

     * 리팩토링은 외부 동작을 바꾸지 않으면서 내부 구조를 개선하는 방법으로, 소프트웨어 시스템을 변경하는 프로세스다.

     * 디자인을 먼저 한 후 코드를 만드는 것이 아니라 일단 돌아가는 코드를 작성하고, 그 후에 그 코드가 더 좋은 구성을 갖도록 바꾼다는 것.

     * 여러 곳에 산재된 중복 코드 정리 

     

 2. refactoring 하는 이유?

     * 코드 간결성 및 가독성 증대

     * 무엇인가 소스의 변경이 필요할 때(기능 추가나 삭제,수정 작업이 일어날 때) 소스의 리팩토링은 포장이사처럼 편하게 작업하도록 도와준다.

     * 리팩토링은 소스의 중복된 부분을 모듈화 시켜준다. 모듈화는 입출력이 명확하기 때문에 이식성을 높여준다. 

     * 리팩토링을 통해 시스템 복잡도를 줄일 수 있다. 

     

 3. 활용

     * coffeeList 조회 결과 coffee1 값이면 아메리카노, coffee2 값이면 카페라떼를 반환해주는 로직

     * 기존: OriginalImpl.java 클래스 내 메소드 selectMenuList(), selectMenu(), updateMenu() 등에 소스 반복

     * 활용: 여러 메소드 내에 반복되는 소스를 리팩토링 하여 하나의 메소드로 생성(convertCoffee(resultMap))

                            

@Service("originalService")

public class OriginalImpl implements OriginalService {


    public static final String AMERICANO = "coffee1";

    public static final String CAFELATTE= "coffee2";

    public static final String AMERICANO_VAL = "아메리카노";

    public static final String CAFELATTE_VAL= "카페라떼";

    

    // 메뉴리스트 조회

    public List<Map<Stirng, Object>> selectMenuList() throws Exception {

   

        ......


        List<Map<Stirng, Object>> resultList= originalDaoImpl.selectMenuList();

        String coffee= resultList .get("coffee").toString();

        

        if(coffee.equalsIgnoreCase(AMERICANO)) {

            coffee = AMERICANO_VAL;

        } else if (coffee.equalsIgnoreCase(CAFELATTE)) {

            coffee = CAFELATTE_VAL;

        } else {

            throw new DataFormatException(); 

        }


        resultList.put("coffee", coffee);


        ......


    }

      

    // 메뉴 조회

    public Map<String,Object> selectCoffee() throws Exception {


        ......

     

     Map<String,Object> resultMap =  originalDaoImpl.selectMenu();


     String coffee= resultMap .get("coffee").toString();

         

        if(coffee.equalsIgnoreCase(AMERICANO)) {

            coffee = AMERICANO_VAL;

        } else if (coffee.equalsIgnoreCase(CAFELATTE)) {

            coffee = CAFELATTE_VAL;

        } else {

            throw new DataFormatException(); 

        }


        resultList.put("coffee", coffee);


        ......


    }



   // 메뉴 업데이트

    public Map<Stirng, Object> updateMenu() throws Exception {

         ......


     // 메뉴 업데이트 후 메뉴 조회 서비스 (업데이트 반영)

     Map<String,Object> resultMap =  originalDaoImpl.selectMenu();


     String coffee= resultMap .get("coffee").toString();

         

        if(coffee.equalsIgnoreCase(AMERICANO)) {

            coffee = AMERICANO_VAL;

        } else if (coffee.equalsIgnoreCase(CAFELATTE)) {

            coffee = CAFELATTE_VAL;

        } else {

            throw new DataFormatException(); 

        }


        resultList.put("coffee", coffee);


        ......


   }



위의 코드에 주황색으로 표시 된 부분이 여러 method에서 반복되고 있는 소스다. 


반복되는 소스는 시스템 복잡도를 높일 뿐만 아니라 소스에 변경사항이 발생하는 경우 해당 소스를 포함하고 있는 각 메소드 마다

일일이 수정해줘야하는 번거로움이 생긴다. 


이러한 문제를 해결하기 위해 아래와 같이 리팩토링을 한다.


   * 반복되는 소스 전체 선택 후 우클릭 > Refactor > Extract Method 선택

   * Method 명 설정









 // extract method 결과 - convertCoffee(Map<String, Object> resultMap) 생성

   private void convertCoffee(Map<String, Object> resultMap) throws DataFormatException {

       String coffee= resultMap .get("coffee").toString();

     

       if(coffee.equalsIgnoreCase(AMERICANO)) {

     coffee = AMERICANO_VAL;

} else if (coffee.equalsIgnoreCase(CAFELATTE)) {

             coffee = CAFELATTE_VAL;

        } else {

     throw new DataFormatException(); 

}


        resultMap.put("coffee", coffee);

 } 



 // 메뉴리스트 조회

    public List<Map<Stirng, Object>> selectMenuList() throws Exception {

        ......


        List<Map<Stirng, Object>> resultList= originalDaoImpl.selectMenuList();

        resultList = convertCoffee(resultList);

        ......

   }



// 메뉴 조회

   public Map<String,Object> selectCoffee() throws Exception {

        ......

     

       Map<String,Object> resultMap = originalDaoImpl.selectMenu();

       resultMap = convertCoffee(resultMap);

        ......

   }



 // 메뉴 업데이트

    public Map<Stirng, Object> updateMenu() throws Exception {

         ......


     // 메뉴 업데이트 후 메뉴 조회 서비스 (업데이트 반영)

     Map<String,Object> resultMap =  originalDaoImpl.selectMenu();

     resultMap = convertCoffee(resultMap);

        ......

   }



convertCoffee 라는 method를 생성함으로써 각 method에서는 얘를 호출하여 coffee 명을 가져올 수 있게 된다.


기존 코드보다 훨씬 간결해진 모습을 확인할 수 있다. (주황색 부분이 파란색 부분으로 변경됨!)


나같은 경우도 처음에는 각 method마다 동일 소스를 계속 반복하여 사용했었다..'재활용성'에 대한 개념이 아예 없었다. 

다행히 리팩토링은 처음부터 적용하려는 의도로 나온 애가 아니라, 소스코드 작성 후 코드 품질 최적화를 위해 

적용할 수 있는 부분에 쓰는 애다. ㅎㅎ  물론 미리 알고 썼더라면, 리팩토링하는 시간도 줄었겠지만.... 앞으로 잘쓰면 되지~~


처음엔 반복되는 코드를 작성했었더라도 이제 리팩토링 개념과 효과를 알았으니 내 코드 최적화를 위해 

리팩토링을 요리조리 잘 써먹어야 겠다. 


이번 포스팅에는 리팩토링의 정말 기본 내용만 담고 있지만, 앞으로 리팩토링 해보면서 좀 더 깊이 있게 쓰게되면

리팩토링 2.0 버전으로 새 글 리포팅해야겠다 :) 


__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅은 아래의 reference 들을 참고하여 내용을 덧붙인 글입니다. 혹시, 문제가 되는 경우 알려주시면 조치하도록 하겠습니다.


  - http://belong2jesus.tistory.com/62

  - http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039161606&type=det&re= 

  

'JAVA' 카테고리의 다른 글

예외처리 관련 참고문서  (0) 2017.06.11
로깅(Logging) 참고문서  (0) 2017.06.11
JAVA - 향상된 for 문 (from Java1.5)  (0) 2017.02.26
system32와 systemWOW64  (0) 2017.02.26
SAPJCO 연동 설정  (0) 2017.02.26

+ Recent posts