Code Refactoring (코드 리팩터링)
Technique리팩터링은 겉으로 드러나는 코드의 기능은 바꾸지 않으면서 내부 구조를 개선하는 방식으로 소프트웨어 시스템을 수정하는 과정이다. 요컨대, 리팩터링한다는 것은 코드를 작성하고 난 뒤에 설계를 개선하는 일이다.
리팩터링 (Refactoring)
소프트웨어 공학에서 '결과의 변경 없이 코드의 구조를 재조정함'을 뜻한다.
리팩터링을 할 때는 기능을 추가하지 않는다.
때로는 리팩터링보다 코드를 새로 작성하는 것이 쉬울 때도 있다.
목적
코드의 품질을 향상시키고 소프트웨어 개발 및 유지 보수를 효율적으로 만들기 위해 다음 목적을 가지고 수행한다.
가독성 향상
- 소프트웨어를 이해하기 쉬워진다.
- 개발자들간에 협업하기 용이해진다.
유지보수성 향상
- 유지보수하는 과정이 간단해진다.
- 코드 중복을 제거하여 잠재적인 버그를 감소시킬 수 있다.
- 구조화와 모듈화를 통해 새로운 기능을 추가하거나 버그를 수정하는 작업이 더 쉬워진다
언제
코드 리뷰: 동료 개발자들과 코드를 검토하면서 품질을 높이고 개선할 수 있다.
기능 추가 직전: 기존 코드에 새로운 기능을 추가하기 쉽게 기존 코드를 리팩터링할 수 있다.
버그 수정: 버그를 수정하는 과정에서 리팩터링을 수행하여 버그를 더 쉽게 이해하고 해결할 수 있다.
정기적인 유지보수: 주기적으로 코드를 개선하고 최적화한다.
방법
하드 코딩된 숫자는 상수로 대체하기
- 전
if (temperature > 100) { // boiling point
// Do something if temperature is above boiling
}
- 후
val BOILING_POINT = 100
if (temperature > BOILING_POINT) {
// Do something if temperature is above boiling
}
중복된 코드 제거하기
- 전
fun process(user: User) {
if (user.status == UserStatus.SPROUT) {
println("======= ## ${user.status} ## =======")
// ...
} else if (user.status == UserStatus.ROSE) {
println("======= && ${user.status} && =======")
// ...
} else if (user.status == UserStatus.TREE) {
println("======= @@ ${user.status} @@ =======")
// ...
}
}
- 후
fun process(user: User) {
if (user.status == UserStatus.SPROUT) {
printStatus(user.status, "#")
// ...
} else if (user.status == UserStatus.ROSE) {
printStatus(user.status, "&")
// ...
} else if (user.status == UserStatus.TREE) {
printStatus(user.status, "@")
// ...
}
}
private fun printStatus(status: UserStatus, decorate: String) {
println("======= $decorate$decorate $status $decorate$decorate =======")
}
간단한 조건문은 삼항 연산자처럼 사용하기 (Kotlin은 삼항 연산자가 없다)
- 전
var text: String
if (zipCode != null) {
text = "$zipCode) $address"
} else {
text = address
}
- 후
val text = if (zipCode != null) "$zipCode) $address" else address
val text = zipCode?.let { "$zipCode) $address" } ?: address
조건이 여러 개인 조건문에 경우 when이 나을 때도 있다.
- 전
val agePeriod = if (age >= 65) "노년기"
else if (age >= 45) "장년기"
else if (age >= 30) "중년기"
else if (age >= 19) "청년기"
else if (age >= 7) "소년기"
else "유년기"
- 후
val agePeriod = when {
age >= 65 -> "노년기"
age >= 45 -> "장년기"
age >= 30 -> "중년기"
age >= 19 -> "청년기"
age >= 7 -> "소년기"
else -> "유년기"
}
긴 메서드 분리하기
- 전
fun process() {
// 유효성 검사에 대한 로직
// ...
// 계산에 대한 로직
// ...
// 상태 변경에 대한 로직
// ...
}
- 후
fun process() {
validation()
caluration()
changeState()
}
fun validation() {
// 유효성 검사에 대한 로직
}
fun caluration() {
// 계산에 대한 로직
}
fun changeState() {
// 상태 변경에 대한 로직
}
의미 있는 이름 사용하기 (변수명, 메서드명 등등)
- 전
fun process(num: Int): Boolean {
return if (num % 4 == 0) !(num % 400 != 0 && num % 100 == 0) else false
}
- 후
fun checkLeapYear(year: Int): Boolean {
return if (year % 4 == 0) !(year % 400 != 0 && year % 100 == 0) else false
}
https://www.techtarget.com/searchapparchitecture/definition/refactoring
https://dev.to/documatic/5-code-refactoring-techniques-to-improve-your-code-2lia
https://woogong80.tistory.com/213#google_vignette
https://velog.io/@rlrhs11/Code-Refactoring코드-리펙토링-이란
https://ikkison.tistory.com/82
https://jeongkyun-it.tistory.com/66
https://dmdwn3979.tistory.com/13
https://2minmin2.tistory.com/72
https://taes-k.github.io/2-where-when-refactoring.html