자바로 배우는 리팩토링

리팩토링이란?

킹차니 2021. 12. 22. 00:46

 

 

 

리팩토링 : 외부에서 보는 프로그램 동작은 바꾸지 않고 프로그램의 내부 구조를 개선하는 것.

  • 리팩토링을 해도 외부에서 보는 프로그램 동작은 변하지 않는다.
  • 리팩토링을 하면 프로그램의 내부 구조가 개선된다.

 

🛠 버그 수정은 리팩토링이 아니다.

: 버그를 수정하면 프로그램의 외부 동작이 바뀐다.

 

🛠 기능 추가는 리팩토링이 아니다.

: 기능을 추가하면 외부에서 보는 프로그램 동작이 변한다.

 

🛠 리팩토링과 유닛테스트

: 리팩토링을 한다면 적어도 유닛 테스트 정도는 반드시 해야한다.

리팩토링할 부분을 테스트하고, 리팩토링을 한 뒤에도 테스트 결과가 같은 지 확인한다. 그러므로 리팩토링 단계마다 유닛테스트를 해야한다.

 


리팩토링의 목적

  • 버그를 발견하기 쉽게 만든다.
  • 기능을 추가하기 쉽게 만든다.
  • 코드 리뷰하기 쉽게 만든다.

 

리팩토링의 한계

  • 프로그램이 아직 동작하지 않을 때는 리팩토링을 할 수 없다.
  • 시간이 촉박할 때는 리팩토링을 할 수 없다. -> 리팩토링은 시간이 지나면서 효과를 본다.

리팩토링과 악취

프로그램에서 개선이 필요한 부분을 '악취'가 난다고 한다.

아래와 같은 부분이 악취가 나는 부분이다.

  • 이해하기 어려운 부분
  • 수정하기 어려운 부분
  • 확장하기 어려운 부분

 

중복 코드 같은 코드가 곳곳에 중복되어 있다.
너무 긴 메서드 메서드가 너무 길다.
방대한 클래스 클래스의 필드나 메서드가 너무 많다.
과다한 매개변수 메서드가 받는 매개변수 개수가 너무 많다.
변경 발산 사양 변경이 있을 때 수정 내용이 곳곳에 흩어져 있다.
변경 분산 어떤 클래스를 수정하면 다른 클래스도 수정해야 한다.
속성, 조작 끼어들기 언제나 다른 클래스 내용을 수정하는 클래스가 있다.
데이터 뭉치 합쳐서 다뤄야 할 데이터가 한 클래스에 모여 있지 않다.
기본 타입 집착 클래스를 만들지 않고 int같은 기본 타입만 사용한다.
스위치 문 switch, if같은 분기문으로 동작을 나눈다.
평행 상속 하위 클래스를 만들면 클래스 계층의 다른 곳에도 하위 클래스를 만들어야 한다.
게으른 클래스 클래스가 별로 하는게 없다.
의심스러운 일반화 '언젠자 확장을 하겠지'라고 너무 일반화한다.
임시 속성 임시로만 쓰는 필드가 있다.
메시지 연쇄 메서드 호출 연쇄가 너무 많다.
중개자 맡기기만 하고 자신은 일을 안하는 클래스가 있다.
부적절한 관계 그럴 필요가 없는데도 양방향 링크를 걸거나 IS-A 관계가 없는데 상속을 사용한다.
클래스 인터페이스 불일치 클래스 인터페이스(API)가 적절하지 않다.
불완전한 라이브러리 클래스 기본 라이브러리 클래스를 사용하기 어렵다.
데이터 클래스 필드와 getter, setter 메서드 뿐인 클래스가 있다.
상속 거부 상속한 메서드인데 호출하면 문제가 발생한다.
주석 코드의 모자란 점을 설명하기 위해 자세한 주석이 붙어있다.

 

위에 악취를 나타내는 말이 너무 많은데.. 줄이면 여섯가지로 줄일 수 있다.

 

1. 겹친다.(중복 코드)

  ➡️  메서드 추출, 클래스 추출, 널객체 도입으로 해결

 

2. 너무 길다.(너무 긴 메서드) 

➡️  메서드 추출, 클래스 추출로 해결

 

3. 너무 많다.(방대한 클래스)

  ➡️  클래스 추출, 중개자 제거, 클래스 인라인화, 메서드 인라인화로 해결

 

4. 이름이 안맞는다.(적절하지 않은 클래스,메서드,변수 명) 

➡️  메서드 추출, 메서드명 변경, 설명용 변수 조입, 임시 변수 분리로 해결

 

5. 너무 공개적이다.(지나친 public 남발) 

➡️  필드 캡술화, 생성자를 팩토리 메서드로 치환으로 해결(정보 은닉)

 

6. 객체 지향답지 않다. 1. switch if문  2.instanceOf  3.int만 쓰고 전용 클래스를 사용하지 않음 

➡️  분류 코드를 클래스로 치환, 분류코드를 하위 클래스로 치환으로 해결

 


 

리팩토링 에센스 (스텝 바이 스텝)

리팩토링은 단계별로! 스텝 바이 스텝으로 하자!

 

1. 두 가지 수정을 한꺼번에 하지 않기

ex) A1 -> B1 -> A2 -> B2 가 아닌 A1 -> A2 -> 작업A 확인, B1 -> B2 -> 작업B 확인

 

2. 되돌리기 쉽게 하기

수정을 되돌려야할 수 있다. 이때 스텝 바이 스텝으로 리팩토링을 했다면 되돌리기 쉬워진다.

 

3. 단계마다 확인

특정 단계의 리팩토링을 마치면 테스트를 하여 확인한다. 이렇게 테스트를 하면 어느정도까지가 리팩토링의 범위였는지도 확인할 수 있다.

 

4. 오래된 것을 새로운 것으로 바꿈

'모든 것을 부수고 새로 만든다'가 아니라 '동작하는 상태를 유지하면서 새로운 코드를 추가해서 오래된 것이 모두 새로워지면 오래된 것을 제거한다.'