LISTORY
코드 리팩토링 [중복코드 / 장황한 메서드 / 방대한 클래스] 본문
저번 포스팅에 이어 이번 포스팅에서는 어떠한 경우에 어떻게 코드를 리팩토링 해야하는지에 대해 다뤄보겠다.
오늘 다룰 내용은 중복 코드, 장황한 메서드, 방대한 클래스이다.
중복 코드
아무래도 가장 흔한 코드의 구린내가 아닐까 싶다. 나도 아직 잘 고치지 못한 부분이다.
중복 코드는 똑같은 코드 구조나 기능이 두 군데 이상 있을 경우를 말하고, 이를 하나로 통일하는 리팩토링이 필요하다.
중복 코드의 여러가지 예제를 다루어 보겠다.
① 한 클래스의 두 메서드 안에 같은 코드가 들어있는 경우
말 그대로 한 클래스내의 두 메서드에 중복되는 코드가 있는 경우이다.
이때는 메서드 추출이라는 기법으로 해결할 수 있다.
“메서드 추출”
메소드 안에 코드를 빼내어 그 코드로 다른 메서드를 만드는 것
메세드 추출 방법을 간단히 예제로 표현해 보았다.
위와 같이 Class A에 두 메소드가 존재하고, 두 메소드에는 반복되는 코드, 즉 중복 코드가 들어있다.
메서드 추출은 이 반복되는 코드를 다른 메소드로 분리하는 방법으로, 다음과 같이 적용할 수 있다.
메서드 추출을 적용한 모습이다. 중복되는 코드를 c() 메서드로 뽑아내었고, 코드가 필요한 부분에서 해당 메서드를 호출 할 수 있다.
② 한 클래스의 두 하위 클래스에 같은 코드가 있을 경우
이럴 경우에는 메서드 추출 기법을 적용하여 중복을 없앤 뒤 메서드 상향 기법을 사용할 수 있다.
“메서드 상향 기법”
기능이 같은 메서드가 여러 하위 클래스에 있을 경우, 메서드를 상위 클래스로 옮기는 기법
간단한 예제로 설명해 보겠다.
클래스 A의 하위 클래스 B와 C가 있다. B와 C 클래스는 서로 중복되는 메서드를 가지고 있다.
이럴 경우에는 클래스 A에 중복되는 메서드 a()를 옮기도록 한다.
이제 클래스 B와 C는 메서드 a가 필요할 경우, 클래스 A에서 가져와 사용할 수 있다.
만일 같은 코드가 아닌 비슷한 코드일 경우에는 같은 부분과 다른 부분을 분리하여 사용하면 된다.
두 메서드가 알고리즘만 다르고 기능이 같다면, 두 알고리즘 중 더 간단한 것을 택하여 사용하면 된다.
③ 서로 상관없는 두 클래스 안에 중복 코드가 있을 경우
이럴 경우에는 중복 코드를 추출하여 클래스, 또는 모듈로 떼어내어 사용할 수 있다.
장황한 메서드
메서드 길이가 길수록 코드의 내용을 알기 어렵다.
객체 지향을 지향하는 코드일수록 메서드의 길이가 짧고, 메서드 기능을 쉽게 알 수 있는 이름을 가져야 한다. 메서드 이름이 명확하다면 그 안의 코드를 분석하지 않아도 쉽게 기능을 알 수 있기 때문이다.
여하튼 짧은 메서드를 위해서는 메서드를 과감하게 쪼개야 한다. 이때, 쪼갠 메서드의 이름은 메서드의 기능 수행 방식이 아니라 메서드의 기능을 나타내는 이름으로 정해야 한다.
메서드를 줄이기 위해 메서드 추출 기법을 사용하여 중복되는 코드는 정리하는 편이 좋고, 코드의 가독성을 위해 매개변수와 임시변수를 줄이는 것이 좋다.
매개변수와 임시변수를 줄이는 방법은 여러 가지가 있는데, 일단 임시변수를 줄이기 위해서 임시변수를 메서드 호출로 전환 기법을 사용하는 것이 좋다.
“임시변수를 메서드 호출로 전환”
수식의 결과를 저장하는 임시 변수가 있을 경우, 그 수식 자체를 메서드로 만들어버리는 기법
길게 열거된 매개변수는 매개변수 세트를 객체로 전환하는 기법, 또는 객체를 통째로 전달 기법을 적용할 수 있다.
“매개변수 세트를 객체로 전환”
여러 개의 매개변수가 항상 붙어 다닐 경우, 여러 개의 매개변수들을 하나의 객체로 만들자
“객체를 통째로 전달”
하나의 객체에서 여러 값을 가져와 메서드의 매개변수로 전달 할 경우, 그냥 객체를 통째로 전달하게 하자
이러한 기법들을 적용했음에도 불구하고 여전히 임시변수와 매개변수가 너무 많을 때엔 메서드를 메서드 객체로 전환 기법을 사용하면 된다.
“메서드를 메서드 객체로 전환 기법”
지역 변수로 인하여 메서드를 추출할 수 없는 긴 메서드가 있을 경우, 긴 메서드 자체를 객체로 전환하자
나는 이 부분이 이해가 잘 안갔는데, 정리해 보면 다음과 같은 내용인 듯 하다.
여러 지역변수들과 복잡한 내용을 가진 메서드가 존재한다. 이를 쪼개려해도 많은 지역변수들로 인해 매개변수가 많아지고, 그로 인해 가독성이 떨어지게 된다.
그래서 이 긴 메서드를 하나의 객체로 전환하는 것이다. 메서드가 가지고 있던 지역변수들은 객체의 필드로 만들어서, 메서드들을 쪼갤 수 있게 된다.
조건문과 루프의 경우에도 마찬가지로 메서드 추출을 해야한다.
조건문을 추출하기 위해선 조건문 쪼개기 기법을 사용하고, 루프를 쪼개기 위해선 루프를 컬렉션 클로저 메서드로 전환한 다음, 그 클로저 메서드 호출과 클로저 자체에 메서드 추출을 실시한다.
“조건문 쪼개기 기법”
복잡한 조건문이 있을 경우, if나 else의 내용을 메서드 추출하자
방대한 클래스
기능이 지나치게 많은 클래스에는 엄청난 수의 인스턴스 변수가 들어있는 경우가 많다. 인스턴스 변수가 너무 많으면 중복 코드가 반드시 존재하기 마련이다.
클래스 추출을 실시하면 인스턴스 변수들을 하나로 묶어 줄일 수 있다. 이때 서로 연관된 변수를 골라 클래스로 빼내면 된다.
클래스 추출 시, 하위클래스로 추출하는 것이 적합할 것 같다면 하위클래스로 추출하는 것이 더 간단하다.
변수뿐만이 아니라 코드가 지나치게 많은 클래스도 마찬가지로 중복코드가 있을 가능성이 존재한다. 이의 경우에도 클래스 추출이나 하위클래스 추출로 코드의 양을 줄이는 것이 좋다.
'IT > 리팩토링' 카테고리의 다른 글
코드 리팩토링 [ 강박적 기본 타입 사용 / switch 문 ] (0) | 2018.04.01 |
---|---|
코드 리팩토링 [ 잘못된 소속 / 데이터 뭉치 ] (0) | 2018.04.01 |
코드 리팩토링 [ 기능의 산재 ] (0) | 2018.04.01 |
코드 리팩토링 [과다한 매개변수 / 수정의 산발] (0) | 2018.03.24 |
리팩토링이란 (0) | 2018.03.14 |