기존의 것을 바꾸는 건 새로 만드는 것보다 힘들다.
당장 몇 달전에 MVVM 연습한다고 간단하게 만든 앱도 지금 다시보니 X판이라..
외부 동작을 바꾸지 않으면서 내부 구조를 개선하는 방법입니다.
그렇다면 리팩토링이 필요한 코드들은 어떤게 있을까 하고 살펴보면
위와 같이 많은 리팩토링 대상이 있는데 지금까지 구현한 많은 코드들이 위에 상황에 해당했다.
그렇다면 위와 같은 상황을 해결할 수 있는 리팩토링 기법은 뭐가 있을까..🤔
위와 같은 리팩토링 기법들이 있는데 이름만 들어도 어떤 느낌일지 알 수 있습니다!
몇 가지 코드로 예를 들어보면
그룹으로 함께 묶을 수 있는 코드 조각이 있으면 코드의 목적이 잘 드러나도록 메소드의 이름을 지어 별도의 메소드로 추출하는 기법
fun print() {
for (i in 0 until count) {
for (j in 0..i) {
print("*")
}
println("")
}
for (i in 0 until count) {
for (j in 0..i) {
print("-")
}
println("")
}
for (i in 0 until count) {
for (j in 0..i) {
print("*")
}
println("")
}
}
위의 print()
함수는 일반적인 별찍기와 중간에 하이픈를 찍는 코드인데 여기서 보면 별찍는 코드가 중복이 되는걸 볼 수 있습니다. 이걸 메소드 추출 기법을 사용하면
fun print(count: Int) {
printStar(count)
printHyphen(count)
printStar(count)
}
private fun printStar(count: Int) {
for (i in 0 until count) {
for (j in 0..i) {
print("*")
}
println("")
}
}
private fun printHyphen(count: Int) {
for (i in 0 until count) {
for (j in 0..i) {
print("-")
}
println("")
}
}
위와 같이 리팩토링 전에는 세 가지 기능이 print()
메소드안에 모두 들어있었지만 printStar()
, printHyphen()
별도 메소드로 분리하였습니다.
메소드 몸체가 메소드의 이름 만큼이나 명확할 때는 호출하는 곳에 메소드의 몸체를 넣고 메소드를 삭제하는 기법
private fun isPass() = score > 80
private fun getPass() = if(isPass()) "Pass" else "Non-Pass"
위의 코드를 보면 score
가 80 이상이면 Pass 아니면 Non-Pass를 리턴하도록 되어있는 코드입니다.
이 코드에 Inline Method기법을 사용해보면 아래와 같이 리팩토링할 수 있습니다.
private fun getPass() = if (score > 80) "Pass" else "Non-Pass"
알고리즘을 보다 명확한 것으로 바꾸고 싶은 경우, 메소드의 몸체를 새로운 알고리즘으로 교체하는 기법
fun checkAnimal(animalList: Array<String>):String {
for(i in animalList) {
return when (i){
"Cat" -> "Cat"
"Dog" -> "Dog"
"Bird" -> "Bird"
else -> ""
}
}
return ""
}
위의 코드를 보면 animalList
라는 동물의 리스트를 받아 Cat, Dog, Bird가 리스트에 포함되어 있으면 해당 동물 이름을 출력하는 메소드입니다.
이 코드에 Substitute Algorithm
기법을 사용해서 리팩토링 해보면 아래와 같이 리팩토링 할 수 있습니다.
fun checkAnimal(animalList: Array<String>):String {
val animals = arrayOf("Cat","Dog","Bird")
for(animal in animalList) {
return if(animals.contains(animal)) animal else ""
}
return ""
}