Refactoring이 동작하는 매커니즘을 아는 것 만큼 중요한 것은, 언제 Refactoring을 적용할까 하는 것이다.
여기서 딜레마가 온다. 어떻게 인스턴스 변수를 삭제하거나 클래스 계증구조를 만드는가를 표현하는 것은 쉽다. 그건 사소한 문제들이다. 하지만 언제 이러한 것들을 해야 할 것인지 표현하는 것은 쉽지 않다. 나는 (여기서의 I는 Martin Fowler) 프로그래밍 미학이라는 모호한 표현으로 얼버무리지 않고 좀 더 확실한 것을 원했다.
내가 이 문제로 Kent Beck 을 방문했을 때 그는 "언제" 를 설명하기 위해서 "Smell" 이라는 표현을 사용했다. 우리는 많은 코드들을 보았고, 그것들을 보면서 Refactoring이 적용가능한 어떤 구조를 발견했다.
여기에서 우리는 Refactoring이 적용가능한 아주 정확한 척도를 제공하려고는 하지 않을 것이다. 경험상, 어떠한 측정도구들도 숙련된 인간의 직관의 경쟁상대가 될 수는 없었다. 우리가 하려는 것은 Refactoring에 의해 해결될 수 있는 문제들이 있는 몇몇 부분을 지적하려는 것이다.
어떠한 Refactoring을 해야 할 지 확신할 수 없을때 이 부분을 읽어라. 정확하게 똑같은 Smell을 발견할 순 없더라도 Refactoring에 대한 올바른 방향을 가리켜 줄 지침이 될 것이다.
Duplicated Code ¶
중복코드 코드
- 같은 클래스내에 2개이상의 메소드들에 중복코드 존재시 - ExtractMethod
- 두개 이상 서브클래스 내 중복코드시 - ExtractMethod 한뒤 PullUpField
- 코드는 비슷하지만 똑같지는 않은 경우 - 비슷한 부분에 대해서 ExtractMethod
- 다른 알고리즘 내에서 같은 일을 하는 메소드 - SubstituteAlgorithm
- 두개이상의 연관없는 클래스 내의 중복코드 - ExtractClass
Long Method ¶
코드의 길이가 긴 메소드
- 대부분의 경우에 대해서 - ExtractMethod
- ExtractMethod 하는중 parameter를 많이 넘겨야 하거나, 임시변수를 많이 사용하게 되는 경우 - ReplaceTempWithQuery, IntroduceParameterObject, PreserveWholeObject, ReplaceMethodWithMethodObject
- 조건 & 반복문 - DecomposeConditional
Large Class ¶
Long Parameter List ¶
Parameter 인자가 많은 함수. 이해하기 힘들고, 사용하기 어렵다.
- When you can get the data in one parameter by making a request of an object you already know about - ReplaceParameterWithMethod
- to take a bunch of data gleaned from an object and replace it with the object itself - PreserveWholeObject
- logic을 가지지 않는 여러개의 data item을 가지는 경우 - IntroduceParameterObject
Divergent Change ¶
Shotgun Surgery ¶
Feature Envy ¶
Data Clumps ¶
Primitive Obsession ¶
Switch Statements ¶
길이가 긴 Switch-Case 문.
- 대부분의 경우 - polymorphism으로 해결 가능
- switch-case 부분을 ExtractMethod 한 뒤, polymorphism이 필요한 class에 MoveMethod 한다. 그리고 나서 ReplaceTypeCodeWithSubclasses 나 ReplaceTypeCodeWithState/Strategy 를 할 것을 결정한다. 상속구조를 정의할 수 있을때에는 ReplaceConditionalWithPolyMorphism 한다.
- polymorphism을 이용하기에는 너무 작아 오히려 cost가 더 드는 경우 - ReplaceParameterWithExplicitmethods
- 조건 case 에 null 이 있는 경우 - IntroduceNullObject
Parallel Inheritance Hierarchies ¶
Lazy Class ¶
Speculative Generality ¶
일어날 가능성이 거의 없는 일까지 다 대비한 필요없는 코드. 모든 기능들과 절차들은 제대로 이용되었을때 쓸모있다.
- 추상클래스들이 별로 하는 일이 없을때 - CollapseHierarchy
- 불필요한 Delegation - InlineClass
- 사용하지 않는 parameter들을 가진 메소드 - RemoveParameter
- 추상적인 두리뭉실한 메소드 이름 -_-; - RenameMethod 로 지상으로 내려오도록 하라는.. --;
Middle Man ¶
Inappropriate Intimacy ¶
Alternative Classes with Different Interfaces ¶
Incomplete Library Class ¶
Data Class ¶
Refused Bequest ¶
Comments ¶
나쁜 냄새를 가리기 위한 방향제로 사용되는 주석. --;
주석을 쓸 필요가 있다는 느낌이 들때 일단 코드를 리펙토링 하면 주석을 많이 쓸 필요가 없음을 알게 된다.
주석을 이용할 좋은 시기는 도대체 무엇을 해야 할 지 모르겠을 때 이다. 무엇을 할 것인지 주석으로 먼저 서술함으로서 주석은 프로그래머가 무엇을 해야 할 지 확신할 수 없을 때 좋은 지침서가 된다. 주석은 ' 왜 당신이 이것을 하는가' 를 말하기 위한 좋은 장소이다.
전에 JuNe 형이 최한기의 신기통을 언급하면서 Metaphor 로서 'Smell' 이 잘 맞아떨어짐을 이야기하던게 생각. '냄새란 일단 그 자체로 악취를 풍길 뿐만 아니라, 밖으로 점차적으로 퍼지고, 사람에게 배어들 수 있으며, 사람에게 배어들고 나면 그 사람이 냄새에 대해 인식을 하지 못한다.'. Smell 에 민감한 사람들은 작은 Refactoring 도 잘 해낼 수 있다. -- 1002
Refactoring