[Refactoring] 리팩터링 2판 Chapter.03 (코드에서 나는 악취)
카테고리: Refactoring
이번 포스팅은 3장 입니다. 3장의 제목은 코드에서 나는 악취
입니다. 아주 강렬한 제목이죠.
이 챕터는 언제 리펙터링을 해야 하는지에 대한 내용을 담고 있습니다.
리팩터링을 언제까지 해야하냐? 라는 질문에는 각자의 경험을 통해 감을 익히는것이 중요하다고 말하고 있습니다. 역시 쉽게 얻을 수 있는건 없군요.
3.1 기이한 이름
이 단락은 너무너무 유명한 내용 입니다. 개발자에게 개발할 때 어떤게 가장 힘드냐 라고 물어보면 단연코 상위를 차지하는 것은 변수명 짓기
입니다. 이게 제일 어렵다고 말하는 만큼 많은 사람들이 대충하고 넘어간다고 할 수 있습니다.(이름 대충 지어도 돌아는 가니까)
하지만 기이한 이름으로 코딩하면 나중에는 작성한 사람 조차도 이게 무슨 변수/함수 인지 코드를 다 보고 유추 해야 합니다. 특히 남이 짠 코드를 볼 때는 더 오랜 시간이 걸리겠죠 …
그래서 저자는 다음과 같이 말합니다. “그 이름만 보고도 각각이 무슨 일을 하고, 어떻게 사용해야 하는지 명확히 알 수 있도록 엄청나게 신경써서 이름을 지어야 한다.”
혹시나 아무리 생각해도 마땅한 이름이 떠오르지 않는다면, 그 코드의 구조가 잘못되었을 가능성이 큽니다. 여러가지 로직이 꼬여있다거나 그런 경우겠죠. 이런경우 우선, 리팩터링을 하고, 알맞은 이름을 부여해 줍니다.
저도 예전에 줄임말 같은걸 많이 썼는데, 나중에 변수를 보니 이해하기가 힘들었습니다. 그래서 그때부터 제 변수명을 짓는 기준은 얼마나 자연스럽게 읽히는가? 얼마나 변수에 많은 정보들이 담겨있는가? 가 되었습니다. 그때부터 훨씬 코드 수정하기가 쉬워졌습니다.
3.2 중복코드
요즘의 소프트웨어는 MVC, MVVM, MVP 등의 아키텍쳐로 구성되어 있습니다. 여기서 변하지 않는것이 있죠. 바로 Model
과 View
입니다. 보통 View
단위로 나누어서 작업을 합니다.
1번 View
와 2번 View
에 같은 역할을 하는 함수가 존재한다면, 관리포인트도 늘어나고, 혹시 까먹고 둘 중 하나를 수정하지 않았다면, 다음에 그 코드를 이해하는데 많은 시간이 걸리겠죠.
그래서 이것들을 모아서 추출하는것이 중요합니다.
저도 이 문제를 많이 겪었습니다. 그래서 어떻게 분리를 할까? 하다가 클래스로 만들어서 분리하기 시작하였습니다. 그렇게 하니까 프로젝트를 옮겨서 작업하더라도 개발 시간이 훨씬 많이 줄어들었고, View
에 담기는 코드도 많이 간소화가 되었습니다.
3.3 긴 함수
소프트웨어의 대부분은 함수
로 이루어 져있다고 봐도 무방합니다. 함수를 만들다 보면, 아주 내용이 긴 함수가 탄생하기 마련입니다.
옛날 컴파일러는 함수 호출시, 비용이 커서 함수를 줄여서 사용하는게 일반적이었다고 합니다. 하지만 최근에는 함수를 호출하는데에 비용이 거의 들지 않아서, 알아보기 쉬운 함수로 나누는것이 좋습니다.
함수로 나누다보면 함수가 많아져서 보기 힘들어질 수 있는데, 이것을 이해하기 쉽게 만드는 가장 확실한 방법은 역시 이름
입니다. 이름만 보고도 이 함수가 뭐하는건지 알 수 있도록 하는 것이죠. 즉, 함수 이름에 신뢰성
이 있어야 합니다.
그리고, 함수를 보면 주석이 막 달려있는 경우가 있는데, 이도 좋은 경우는 아닙니다. 함수의 이름으로 의도를 명확하게 표현하지 못하였다는 것이죠. 저도 주석을 막 좋아하지는 않는데(코드를 설명하는 주석인 경우), 함수의 기능이 바뀌어도 주석의 내용은 바뀌지 않는 경우가 있기 때문입니다. 즉, 주석은 신뢰성이 없다 라고 표현할 수 있습니다.
3.4 긴 매개변수 목록
함수를 처음 배우면 제일 처음 접하는 것이 Add(int _a, int _b)
입니다. 매개변수로 더할값을 받아서 실행되는 함수이죠. 여기서 배우는 아주 중요한 것이 매개변수를 활용하여 함수의 재사용성 높이기
입니다.
하지만 로직이 복잡해지고, 한가지 오브젝트를 위해 사용되는 함수라면, 위 내용이 적용되지 않을 수 있습니다. 재사용할곳도 거의 없는데다가, 매개변수를 많이 넣게 되면 가독성이 떨어지기 때문입니다. 가독성이 떨어진다는건 변경하기 어렵다는 말이 됩니다.
즉, 매개변수를 넣음으로서 얻을 수 있는 재사용성의 이점을 얻지 못하고 코드만 복잡하게 만드는 주범이라는 뜻이죠.
3.7 뒤엉킨 변경
이 경우는 하나의 모듈이 서로 다른 이유들로 인해 여러 가지 방식으로 변경되는 일이 많을 때 발생합니다. 즉, 단일책임원칙 (SRP)
이 제대로 지켜지지 않을 때 나타나는 현상입니다.
저도 처음에 이런식으로 코딩을 했습니다. Unity 에서 모든 변수를 public 필드로 만들어 놓고 서로 참조하게 만들었었죠. 만들때는 편했지만, 문제는 버그가 발생했을 때 벌어졌습니다. 한가지 버그를 고치기 위해서 3가지의 함수를 수정해야 하고, 그 3가지 함수들을 수정하면 또 그것과 연관된 함수들을 수정해야하는 상황에 놓이게 되었습니다. 그래서 한가지 버그를 고치는데 엄청난 시간이 들었었습니다.
그 뒤로, 객체지향의 의미를 좀 깨닫게 된 것 같습니다. 클래스가 많아지더라도, 기능별로 다 쪼개서 관리하게 되니까, 훨씬 디버깅하기 쉬워지고, 재사용하기도 쉬워졌습니다.
3.12 반복되는 switch 문
앞선 예제에서 switch 문은 함수 추출하기
로 함수로 의도를 표시하거나, 더 나아가 조건부 로직을 다형성으로 구현하기
를 통해서 분리 했었습니다.
저자가 말하기를 주니어들이 하는 실수 중 모든 if/switch
문을 클래스로 나누고, 조건부 로직이 많아지는것을 죄악시 한다 라고 합니다. 저격 당했습니다. 저도 뭔가 조건문을 쓰는게 죄악처럼 느껴지고, 어떤 객체로 만들어서 객체지향적으로 만들 수 있을것이라고 생각했습니다. 하지만 그것은 환상이라는것을 알게 되었습니다. 필요한 곳에만 다형성으로 구현하면 된다는것을 알게 되었습니다.
결국 모든것이 과유불급
인것 같습니다.
댓글 남기기