[ Code Refactoring ] 코드 리팩토링에 대해서 알아보자
🌈 프로그래밍

[ Code Refactoring ] 코드 리팩토링에 대해서 알아보자

반응형

 

안녕하세요? 수구리입니다.

이번 포스팅에서는 Code Refactoring에 대한 내용에 대해서 알아보려고 합니다.

 

코드 리팩터링이란?

  • 리팩터링은 사용하지 않는 코드 또는 중복된 코드를 지우고, 코드의 로직을 깨끗하고 이해하기 쉽게 디자인하는 것
  • 이 개념은 Martin Fowler와 Kent Beck에 의해서 정의되었다고 한다.
  • 이는 종종 최적화, 디버깅, 방어 코드 추가, 테스트하기 좋은 코드로 만드는 것과 혼동될 수 있다.

 

리팩터링의 목적

  • 흔히 "리팩터링을 한다."라는 의미는 개발자의 실수를 만드는 것을 방지하는 것임에 유의하자
  • 디자인에 작고 안전한 구조적 변화를 추가하는 것으로 리팩토링을 시작할 수 있는데 주의할 점은 항상 같은 동작, 기능을 수행해야 한다는 것이다.
  • 리팩토링을 하면서 지속적으로 코드가 정상 동작을 하는지 확인해야 하고, 동작에 영향을 주어서는 안 된다.

 

리팩터링을 해야 하는 이유?

  • 코드를 고치거나 바꾸는 것이 될 수도 있다.
  • 이 과정은 코드를 쉽게 이해하고 유지보수에 좋게 하는 것에 초점이 맞춰져야 한다.

 

리팩터링과 클린 코드의 차이점?

  • 가깝게 본다면 리팩터링과 클린 코드에 차이점이 별로 없어 보인다.
  • 하지만 좀 더 멀리 떨어져서 본다면 리팩터링이 더 큰 의미를 가지는 것처럼 보인다.
  • 클린 코드는 단순하게 가독성을 높이기 위한 작업이라면
  • 리팩터링은 클린 코드를 포함하여 유지보수를 위한 코드의 개선이라고 볼 수 있다.
  • 클린 코드와 같은 부분은 설계단계에서 잘 이루어져 있는 것이 중요하고, 리팩토링은 결과물이 나온 이후 수정이나 추가 작업이 진행될 때 개선해 나가도록 하자.

 

리팩터링의 과정

  1. 문제 찾기
  • 어떤 부분에서 문제가 있는지?
  • 무엇이 문제가 되는지?

 

  1. 문제 특징짓기
  • 왜 어떤 것을 바꾸어야 하는지?
  • 바꿈으로써 얻는 이점은 무엇인지?
  • 바꿨을 때 위험한 점은 없는지?

 

  1. 솔루션 디자인하기
  • 코드의 최종 목적은 무엇인지?
  • 어떤 코드의 변환이 적당한 상태를 위해 움직일 코드인지?

 

  1. 코드 수정하기
  • 코드 변환이 수행될 것의 코드 기능은 이전에 기능하던 것과 동일하게 되도록 남겨야 한다.

 

리팩터링 방법

  1. Rename 이름 재설정
  • 메서드, 변수, 클래스 등등 이름을 덜 혼동하고 오해가 없도록 수정
  • 개인적으로 클린 코딩 쪽에 더 가깝다고 봄.

 

  1. Move Class 클래스 이동
  • 클래스를 더 잘 맞는 패키지로 이동시킨다.
  • 모든 추가된 구문들은 주어진 클래스를 참조하는 게 좋다.
  • 명확히 이해는 잘 안 가지만 아무튼 재사용과 관련되어서 클래스를 이동시키라는 의미인 것 같다.

 

  1. Extract Method 메서드 추출
  • 긴 메서드를 쪼개서 가독성과 유지성을 높인다.
  • 한 가지 일을 수행하는 코드의 부분을 서술적인 이름의 새로운 메서드로 만든다.
  • 메소드 추출을 통해서 특정 기능을 재사용하도록 해준다.

 

  1. Extract Superclass 슈퍼클래스 추출
  • 구체화시키는 클래스들 중에서 공통된 메서드는 정의를 위로 올린다.
  • 서브 클래스에서 다양한 것들은 추상 메서드로 남겨둔다.
  • 이는 효율적인 코드 재사용을 도와주고 새로운 서브클래스들이 만들고 사용되는 것을 허락해준다.

 

  1. Replace Conditional with Polymorphism 다형성을 조건으로 하는 것을 대체한다.
  • if 나 switch 같은 의사결정 메서드를 만든다.
  • 예를 들면, 너비와 타입에 의해 정의된 모양을 그리는 데에 사용되는 클래스가 있다. 하나는 중복을 방지하기 위해 다형성을 쓴다.
  • 만약 클래스의 동작이 형태에 특정하다면, 코드를 단순화하기 위해서 서브클래스로 내릴 수 있다.
  • 이것은 코드의 큰 변화 없이 다른 모양을 그리기 쉽게 만들어 준다.

 

리팩터링 예제

  • 다음으로는 코드와 함께 리팩토링 과정을 따라가 보자.

직관적인 함수명과 변수명

// before
public int getFoodPrice(int a, int b){
    return a * b;
}

// after
public int getTotalFoodPrice(int price, int quantiry){
    return price * quantity;
}

 

메서드 추출

  • (price * quantiry) 변수 추출
  • 할인율 메소드 추출
  • 할인율 메소드 pricate 선언
// before
public int getTotalPrice(int price, int quantiry, double discount) {
    return (int) ((price * quantiry) * (price * quantiry) * (discount / 100));
}

// after
public int getTotalFoodPrice(int price, int quantiry, double discount) {
    int totalPriceQuantity = price * quantiry;
    return (int) (totalPriceQuantity - getDiscountPrice(discount, totalPriceQuantity));
}

private double getDiscountPrice(double discount, int totalPriceQuantity) {
    return totalPriceQuantity * (discount / 100);
}

 

메소드 명 수정

  • totalPriceQuantity를 getter 메서드로 추출하도록 변경
  • 위의 after 코드에서 메소드 명 수정
// after
public int getTotalFoodPrice(int price, int quantiry, double discount) {
    int totalPriceQuantity = getTotalPriceQuantity(price, quantiry);
    return (int) (totalPriceQuantity - getDiscountPrice(discount, totalPriceQuantity));
}

private double getDiscountPrice(double discount, int totalPriceQuantity) {
    return totalPriceQuantity * (discount / 100);
}

private int getTotalPriceQuantity(int price, int quantiry) {
    return price * quantiry;
}
반응형