이번 강의에서는 점진적 리팩터링에 대해 공부하였습니다.
점진적 리팩터링(Incremental Refactoring)은 한 번에 많은 코드를 바꾸는 것이 아니라, 여러 작은 단계로 나누어 변경하는 방법입니다.
기존 코드를 변경하는 일은, 해당 코드를 사용하는 곳에서 예기치 못한 오류를 발생시키거나 컴파일 에러가 발생할 수도 있습니다.
다른 블로그의 포스팅을 인용하자면 "굴러가는 자동차의 바퀴를 바꾸는 행위와 같다." 라고 말하고 있습니다.
다시 말해, 잘 돌아가는 코드를 개선하기 위한 목적이었지만, 그만큼 리스크를 가진다는 의미입니다.
class Lotto(private val numbers: List<Int>) {
fun match(lotto: List<Int>): Int {
numbers.count { lotto.contains(it }
}
}
// match()를 호출하는 모든 영역에서 compile error 발생!
fun main() {
Lotto(listOf(1,2,3,4,5,6))
.match(listOf(1,2,3,4,5,6))
}
만약, match() 메서드의 인자 lotto를 List<Int>에서 Lotto로 바꾼다면 어떻게 될까요?
해당 메서드를 사용하고 있는 모든 영역(테스트 코드, 의존 객체)에서 컴파일 에러가 발생할 것입니다.
우리는 이를 해결하기 위해 점진적 리팩터링을 시도해볼 수 있습니다.
Step1 새로운 메서드 추가(오버로드, 함수명 변경 등등)
class Lotto(private val numbers: List<Int>) {
fun match(lotto: List<Int>): Int {
numbers.count { lotto.contains(it }
}
fun match(lotto: Lotto): Int {
numbers.count { lotto.numbers.contains(it }
}
}
// compile error 발생 X
fun main() {
Lotto(listOf(1,2,3,4,5,6))
.match(listOf(1,2,3,4,5,6))
}
기존 메서드를 제거하지 않고 오버로드 메서드를 추가하면, 기능을 확장하면서 아직 기존 기능을 사용할 수 있기 때문에 Lotto 클래스를 의존하고 있는 영역에서 컴파일 에러가 발생하지 않습니다.
만약 메서드명 변경이 필요하다면, match 대신 변경하고자 하는 메서드명을 작성해도 무관합니다.
Step2 기존 메서드 대체
class Lotto(private val numbers: List<Int>) {
fun match(lotto: List<Int>): Int {
numbers.count { lotto.contains(it }
}
fun match(lotto: Lotto): Int {
numbers.count { lotto.numbers.contains(it }
}
}
// compile error 발생 X
fun main() {
Lotto(listOf(1,2,3,4,5,6))
.match(Lotto(listOf(1,2,3,4,5,6)))
}
현재 match() 메서드를 오버로드하고 있기 때문에, list 대신에 Lotto 객체를 전달하도록 대체해도 컴파일 에러가 발생하지 않습니다.
지금은 오버로드하고 있지만, 만약 match2()와 같이 메서드명이 다르다면 match()를 사용하는 전체 부분을 match2()로 변경해주면 됩니다.
IDE에서 Shift + F6 단축키를 사용하면 한 번에 변경이 가능합니다.
Step3 기존 메서드 제거
class Lotto(private val numbers: List<Int>) {
fun match(lotto: Lotto): Int {
numbers.count { lotto.numbers.contains(it }
}
}
fun main() {
Lotto(listOf(1,2,3,4,5,6))
.match(Lotto(listOf(1,2,3,4,5,6)))
}
이제 더 이상 리스트를 받는 match() 메서드는 사용되지 않으므로 기존 메서드를 제거할 수 있습니다.
이러한 스텝을 반복하여 다른 리팩터링도 문제없이 진행할 수 있습니다.
예를 들어, Lotto 클래스 생성자로 List<Int>를 받고 있지만, 이를 List<LottoNumber>로 변경해준다면, 바로 주생성자를 바꿔주는 것이 아니라 우선 부생성자를 만들어주는 방식을 채택할 수 있습니다.
정리하자면, 한 번에 많은 코드를 변경하려고 하다보면, 의도치 않은 오류나 컴파일 에러가 발생할 수 있습니다.
그렇기 때문에 점진적 리팩터링은 기존 메서드를 우선 유지합니다.
그리고 리팩터링하고자 하는 메서드를 오버로드하거나 다른 이름으로 작업한 후에, 기존 메서드를 호출하는 코드를 리팩터링한 메서드로 변경해줍니다.
그러면 더 이상 기존 메서드를 사용하지 않기 때문에 자연스럽게 기존 메서드를 제거할 수 있습니다.
'대외활동 > 우아한테크코스' 카테고리의 다른 글
[우아한테크코스] 우아한테크코스 한 달 생활기 (2) | 2023.03.05 |
---|---|
[우아한테크코스] 원시값 포장과 일급컬렉션은 무엇이고, 어디까지 감싸야 할까? (1) | 2023.02.27 |
[우아한테크코스] 2주차 - 로또(자동) 미션 회고 및 피드백 (4) | 2023.02.19 |
[우아한테크코스] 2주차 - TDD(Test Driven Development) (1) | 2023.02.15 |
[우아한테크코스 5기] 1주차 회고 - (양념 반 후라이드 반) 설렘 반 걱정 반 (6) | 2023.02.13 |