'디버깅'에 해당되는 글 2건

  1. 2008.07.24 C#의 디버깅과 오류 처리
  2. 2007.06.14 코딩 먼저, 설계는 나중에 좋게 하자!
2008.07.24 09:13

C#의 디버깅과 오류 처리

* 의미적 오류(semantic error) 또는 논리적 오류(logic error)
  : 실행 자체에는 문제를 일으키지 않지만 응용 프로그램의 논리에는 해를 입히는 오류.
* 디버깅(Debugging)
  : 오류가 보고되었으면 언제 어떤 문제가 어떻게 일어나는지를 파악하고 원일을 해결하는 작업.
1. Visual Studio 에서의 디버깅
   1) 프로그램이 디버그 모드 하에서 실행되면, 사람이 작성한 코드 이상의 것이 내부적으로 진행된다. 디버그 필드는 응용 프로그램에 대한 심볼 정보를 유지하며, VS는 그러한 정보를 통해서 코드의 실행을 구체적으로 알아낸다.  
   2) 심볼 정보로 가능한 작업들 (프로젝트 컴파일한 후 Debug 디렉토리의 .pdb 파일에 저장된다.)
      (1) 디버깅 정보를 VS로 출력
      (2) 응용 프로그램 실행 도중에 현재 범위 안의 변수들의 값을 조사, 수정
      (3) 프로그램의 실행을 일시 정지했다가 다시 시작
      (4) 코드의 특정 지점에서 실행을 자동적으로 정지
      (5) 프로그램의 실행을 한 번에 한 줄씩 진행
      (6) 응용 프로그램 실행 도중 변수 값의 변화를 감시
      (7) 함수에 대한 테스트 호출을 수행
2. 비 중단 모드(정상 모드)에서의 디버깅
   1) 응용 프로그램 실행 도중 중요한 지점들에서 디버깅 정보를 출력해두고 나중에 그것을 분석 한다.
   2) 출력 창은 VS 개발 환경 아래쪽의 [작업 목록] 창과 같은 공간을 공유한다. 출력 창에는
     코드의 컴파일과 관한 정보가 출력되며, 컴파일 도중 생긴 오류 등도 이곳에 출력된다.
3. 디버깅 정보의 출력
   1) 런타임(실행 시점)에서 출력 창에 텍스트를 출력하는 것은 매우 간단한 일이다. 그냥
      Console.WriteLine() 대신 다음 두 명령들 중 하나를 사용하면 된다.
      (1) Debug.WriteLine()
           : 디버그 빌드에서만 작동하며, 릴리즈 빌드에서는 아예 컴파일되지 않고 완전히 무시된다.
      (2) Trace.WriteLine()
           : 오직 릴리즈 모드에서만 작동한다.
      ※ 디버그 버전은 모든 종류의 추가적인 분석 정보를 표시하는 반면, 릴리즈 버전은 사용자가 꼭 알아야 할만한 정보만 출력한다.
      (3) Debug.Write()
           : Debug.WriteLine() 함수와 동일한 구문을 사용하나, 출력 끝에서 줄을 바꾸지 않는다.
      (4) Trace.Write()
           : Trace.WriteLine() 함수와 동일한 구문을 사용하나, 출력 끝에서 줄을 바꾸지 않는다.
   2) 그 외에 다른 명령어들
      (1) Debug.WriteLineIf()
      (2) Trace.WriteLineIf()
      (3) Debug.WriteIf()
      (4) Trace.WriteIf()
      ※ 이들은 -If가 붙지 않는 함수들의 두 매개변수들을 가지며, 추가호 하나의 Boolean 매개변수도 가진다.(생략 불가). 이들은 Boolean 매개변수가 참일 때에만 메시지를 출력한다. 따라서 조건에 따라 디버깅 정보를 출력 창에 출력하는 것이 가능하다.
4. 중단 모드에서의 디버깅
   1) 중단 모드란 프로그램의 실행이 일시적으로 정지된 상태를 말한다.
   2) 중단 모드로의 진입
       (1) 응용 프로그램 실행 도중 VS의 아래 해당 버튼을 클릭한다.
            ▣ 모두 중단 : 응용 프로그램을 일시 정지하고 중단 모드로 들어간다.
            ▣ 중지 : 응용 프로그램을 완전히 끝낸다.
            ▣ 다시 시작 : 응용 프로그램을 다시 시작한다.
       (2) 중단 모드로 진입하는 가장 기본적인 방법이나, 단점은 중단 시점을 정밀하게 제어하기 힘들다는 것이다.
   3) 중단점
       (1) 중단 지점을 명시적으로 정의하고자 소스 코드에 표시하는 것으로, 실행이 자동적으로
           중단 모드에 진입하게 만드는 역할을 한다.
       (2) 중단점이 작용하는 방식
            ▣ 중단점에 도달하면 즉시 중단 모드로 진입한다.     
            ▣ 중단점에 도달했을 때, 주어진 부울 표현식이 true이면 중단 모드로 진입한다.
            ▣ 중단점에 일정 횟수 이상 도달했을 때에만 중단 모드로 진입한다.
            ▣ 중단점에 도달했을 때, 이전에 도달한 이후로 변수의 값이 변했으면 중단 모드로 진입한다.
       (3) 중단점은 오직 디버그 빌드에서만 사용할 있다. 릴리즈 모드의 경우에는 모든 중단점이 무시된다.
       (4) 중단점을 소스 코드에 추가하는 방법
            : 중단점에 도달했을 때 무조건 즉시 중단모드로 진입하게 되는 단순한 중단점이라면,
             소스 코드 줄 왼쪽의 회색 영역을 왼쪽클릭하거나, 또는 줄 자체를 오른쪽 클릭하고
             [중단점 삽입]을 선택하면 된다. 그러면 코드 줄이 선택되면서 왼쪽에 빨간 원이 나타
             나는데, 그것이 바로 중단점이다.
       (5) 소스 코드의 모든 중단점들에 대한 정보는 [중단점] 창에서 볼 수 있다. 이 창은 [디버깅] 창에서 [중단점]을 선택하면 화면 아래에서 볼 수 있다. 여기서는 중단점을 해제, 삭제 또는 중단점의 속성을 변경할 수 있다.
       (6) 중단점 창에서 속성에는 [함수],[파일],[주소]라는 세 가지 탭들로 구성되어 있는데, 이 탭들을 통해서 중단점의 위치를 변경할 수 있다. 그리고 [조건]과 [적중 횟수]라는 속성들이 표시되는데, [조건]은 임의의 부울 표현식을 [적중 횟수]는 중단점에 몇 번 도달했 을 때 중단 모드로 진입하게 할 것인지를 설정할 수 있다.
   4) 또 다른 중단 모드 진입 방법
       (1) 처리되지 않은 예외가 던져질 때.
       (2) 어설션(assertion)이 발생했을 때.
           ▣ 어설션은 응용 프로그램의 실행을 중단하고 사용자 정의 메시지를 출력하는 명령이다.
           ▣ 어설션은 종종 개발 과정 도중에 응용 프로그램이 의도한 대로 실행되고 있는지를 시험하기 위한 수단으로 쓰인다.
           ▣ 디버그 버전인 Debug.Assert() 함수와 릴리즈 버전인 Trace.Assert() 함수가 있으며, 디버그 버전은 디버그 빌드에서만 컴파일된다. 이 함수들은 세 개의 매개변수가 있는데, 첫번째는 하나의 부울 값으로 그 값이 false이면 어설션이 발생한다. 두번째와 세번째는 팝업 대화상자와 출력 창에 표시될 메시지들이다.
5. 변수 내용의 감시
   1) 변수의 값은 중단 모드에서 소스 코드 안의 변수 이름에 마우스를 올려놓으면 확인할 수 있다. 또한 표현식 전체를 선택하고 마우스를 올려 놓으면 표현식의 결과를 볼 수 있다. 그러나 이 방법은 좀  제한적이며, 예를 들어서 배열의 내용은 볼 수가 없다.
   2) 디버깅의 중단 모드의 경우 새로운 창에서 다음과 같은 세 가지 탭들이 있다.
      (1) [자동] - 현재와 이전 문장에서 쓰이는 변수들이 나타난다.
      (2) [지역] - 현재 범위 안의 모든 변수들이 나타난다.
      (3) [조사식 N] - 커스텀 가능한 변수들과 표현식들이 나타난다(N은 1에서 4)
      ※ 소스 코드 창에서 변수를 조사식 창에 끌어놓은 식으로 변수를 추가할 수도 있다.
      ※  원하는 변수를 오른쪽 클릭한 후 [간략한 조사식] 을 선택해서 사용할 수도 있다.
   3) 중단 모드 안에서 단계적으로 실행
      (1) 한 단계씩 코드 실행 - 현재 문장을 실행하고 다음 문장에서 멈춘다.
      (2) 프로시저 단위 실행 - 위와 같으나, 내포된 코드 블럭으로는 들어가지 않는다.
      (3) 프로시저 나가기 - 코드 블럭의 끝까지 실행하고, 그 다음 문장에서 멈춘다.
   4) 명령창에는 [명령]과 [직접 실행] 모드가 있다.
      (1) 명령 모드에서는 메뉴 줄이나 버튼 등을 사용하지 않고 VS의 특정 기능을 실행시킬 수
          있다. 실행모드에서는 실행될 실제 코드 줄들 사이에서 임의의 C# 코드를 직접 실행해
          볼 수 있다.
      (2) 명령모드에서는 창의 각 줄에 > 표시가 나타난다. 명령 모드에서 직접 실행 모드로 바꾸려면 그 창에서 "immed"를 입력한 후 엔터를 치면 되고, 다시 명령 모드로 돌아가려면 ">cmd"를 입력하고 엔터를 치면 된다.
   5) 호출 스택 창은 작업 목록이나 출력 창과 같은 공간을 사용하는 또 하나의 창이다.
      (1) 호출 스택은 현재 중단된 위치에 도달한 경로를 알려주는 역할을 한다.
      (2) 오류가 처음 발생했을 때 그 오류 바로 이전에 어떤 일이 일어났는지를 쉽게 추적할 수
          있다.
6. 오류 처리
   1) 예외(exception)은 실행 도중 또는 코드가 호출한 함수 안에서 발생한 오류를 가리킨다.
   2) try...catch...finally
      (1) C# 언어에는 구조적 예외 처리(Structured Exception Handling, SEH)를 위한 구문이
          포함되어 있다. try, catch, finally는 각각 개별적인 코드 블럭을 동반하며, 반드시 순서
          대로 써줘야 한다.
      (2) 기본 구조
           try
           {
               ....
            } 
            catch (<예외형식> e)
            {
               ...
             }
            finally
            {         
               ...
             }
      (3) catch 블럭 없이 하나의 try와 하나의 finally만 존재하는 구조나, 하나의 try에 여러 개의 catch 절들이 들어 있는 구조도 가능하다. catch가 존재하면 finally는 생략할 수 있으나, catch가 없으면 반드시 finally가 존재해야 한다.
      (4) try - 예외를 던질 코드를 감싼다. 여기서 "던진다(throw)"라는 말은 예외를 발생시킨다는 뜻이다.
      (5) catch - 예외가 던져졌을 때 실행될 코드를 감싼다. <예외형식>을 통해서 형식을 지정해야 하며, <예외형식>을 생략하면 모든 종류의 예외들에 반응하게 된다.
      (6) finally- 예외가 던져졌든 그렇지 않든 항상 실행될 코드를 감싼다. finally 코드의 블럭은 예외가 던져지지 않았을 때, 예외가 던져지고 catch에 의해 처리되었을 때, 또는 예외가 처리되지 않아서 응용 프로그램이 종료되어야 할 때 모두 반드시 실행된다. 따라서 여기에는 조건에 상관없이 반드시 실행되어야 하는 코드를 넣는다.
   3) 예외의 나열과 설정
      (1) 예외창 ([디버그 | 예외] 선택 또는 Ctrl+Alt+E) 에는 모든 예외들이 범주별로, 그리고
          .NET 라이브러리 네임스페이스별로 나열된다.
      (2) 창 아래의 라디오 버튼들을 이용해서 발생 또는 처리 방식을 바꿀 수 있다. 기본적으로
          [부모 설정 사용]으로 되어 있는데, 이는 자신이 속한 범주의 설정을 따른다는 것이다
      (3) 옵션중 [중단하고 디버거 실행]은 예외가 던져졌을 때 예외가 처리되기 전에 디버거가
          뜨며, [계속]은 예외를 아예 처리하지 않고 진행하는 것이다.
   4) 예외 처리에서 주의할 점
      (1) catch 블럭은 반드시 범용적인 catch 블럭 전에 나와야 한다. 이를 어기면 컴파일이 실패한다.
      (2) catch 블럭 안에서 예외를 던지는 것도 가능하다. 특정 형식의 예제를 던질 수도 있고,
          throw만 써줄 수도 있다.
          throw;     // catch블럭이 처리한 예외가 다시 던져진다.


출처 : http://blog.naver.com/web28?Redirect=Log&logNo=60010716771
Trackback 1 Comment 0
2007.06.14 15:21

코딩 먼저, 설계는 나중에 좋게 하자!

코딩을 먼저하고 설계를 나중에 좋게 하자니…. "도대체 소프트웨어 공학의 기초를 아는 사람이야?"라는 의문이 들지도 모르겠습니다. 그러나 소프트웨어 개발자라면 처음에 디자인을 완벽하다고 생각될 정도로 상세히 하고 코딩했다 할지라도 코딩을 한참 진행하고 있는 와중에 "아… 코드 정리를 한 번 해주어야 할 텐데… 처음부터 제대로 할 껄"하면서 후회하는 일이 한 두 번이 아닐 것입니다. 나중에는 손을 쓸 수 없는 지경에 이를 때까지 기능 추가와 수정만 계속하다가 스스로 코드에 문제가 있음을 시인하면서도 슬그머니 그대로 두고 다른 새로운 프로젝트를 할 수밖에 없었던 것이 현실이지요. 물론 처음부터 디자인이 훌륭했더라면 좋겠지만 실제 프로젝트에서 훌륭하고 정확한 디자인이 나올 때까지 기다리다가는 프로젝트가 물건너 갈 겁니다. 간단한 디자인으로 코딩을 시작하더라도 코드 정리를 지속적으로 해서 종국에는 충분히 잘 설계된 깔끔한 코드로 만들고자 하는 것이 이달 키워드로 살펴볼 리팩토링의 기본 사상입니다.

박성희 eyry00@hanmail.net

필자는 소프트웨어 컴포넌트 전문 컨설팅 업체 컴포넌트비젼의 책임 컨설턴트로 재직하고 있으며 컴포넌트 개발 및 컴포넌트 기반 개발과 XP(eXtreme Programming) 등에 많은 관심을 갖고 있다.

리팩토링이란 코드의 외부 행동은 바꾸지 않으면서 내부 구조를 변경하는 과정입니다. 복잡하고 어려운 코드를 수정하기 쉽고 읽기 쉬운 코드로 바꾸기 위해서이지요. 마틴 파울러는 리팩토링이 필요한 코드들의 증상을 분류해 각 증상별로 버그를 최소화하면서 코드를 정리하는 방법을 공식화해서 카탈로그로 만들어 놓았습니다. 경험으로부터 우러난 많은 리팩토링 아이디어들을 살펴보면 대부분의 개발자들은 무릎을 탁 칠 것입이다. 그동안 당연하게 코드를 수정해 오던 패턴도 포함되어 있을 뿐만 아니라 생각하지 못한 부분들도 명확하게 정리해 놓은 데서 오는 깨달음일 겁니다.
코드 중 문제가 발생하는 부분을 찾아서 리팩토링하는 많은 방법들을 한정된 지면을 통해 다 소개할 수는 없으므로 몇 가지 리팩토링 방법을 맛보는 정도로 만족해야 할 것 같습니다. 백문이 불여일견이라고 한 번 보면 개발자의 본능으로 모든 것을 파악할 수 있으리라 봅니다.

리팩토링 맛보기
리팩토링 중 가장 많이 쓰이면서도 많은 개발자가 인지하지 못하고 있는 작업이 메쏘드 추출(Extract Method)일 겁니다. 메쏘드 추출 방법은 <리스트 1>의 적용 이전 코드와 <리스트 2>의 적용 이후 코드를 비교해 보면 쉽게 이해될 겁니다.
메쏘드 추출 방법
지나치게 긴 메쏘드를 보거나, 코드가 무슨 일을 하는지 알려주기 위해 주석이 주렁주렁 달려 있다면 이 방법을 이용해서 메쏘드를 분리해 냅니다. 왜 짧은 메쏘드로 분리해야 하는가는 길이가 짧고 이해하기 쉬운 이름이 붙여진 메쏘드가 편리한 이유를 보면 명확합니다. 일단 메쏘드가 짧으면 다른 메쏘드에서 사용하기 쉬우므로 재사용율이 높아집니다. 두번째로 호출하는 편에서 보면 메쏘드 호출만 하더라도 마치 일련의 주석을 읽는 것처럼 이해하기가 쉽습니다. 물론 메쏘드의 이름이 적절하고 쉽게 이해할 수 있어야만 가능한 일이므로 메쏘드 이름은 잘 지어야 합니다.
메쏘드 추출 방법은 일단 메쏘드를 새로 만들고 무엇을 하는 메쏘드인지 이름을 잘 정합니다. 그 다음, 원래 메쏘드에서 뽑아내고자 하는 부분을 복사해 새 메쏘드로 옮긴 다음 원래 메쏘드에서 사용되는 지역변수가 뽑아낸 부분에도 있는지 확인합니다. 있다면 새 메쏘드의 지역변수나 파라미터가 돼야 할 겁니다. 뽑아낸 코드 내에서 지역변수 값이 수정된다면 수정된 결과를 관련 변수에 값을 저장할 수 있도록 반환 값으로 처리돼야 합니다. 이렇게 조심 조심 코드를 수정한 다음 컴파일을 하고 원래 메쏘드에서 뽑혀져 나간 부분은 새로 만든 메쏘드를 호출하도록 바꿔주고 테스트를 합니다. 이상이 없다면 리팩토링 끝!

다형성을 이용한 조건문 변경
하나 더 리팩토링 예를 보도록 하지요. 다형성을 이용한 조건문 변경(Replace Conditional with Polymorphism) 방법이 있습니다. 조건문 대신 객체지향 개념의 다형성을 이용하자는 것이지요. <리스트 3, 4>의 코드에서 보는 바와 같이 switch문을 상속구조와 다형성을 반영하여 서브 클래스들의 메쏘드로 멋지게 변경한 것을 볼 수 있을 겁니다(<그림 1>). 훨씬 객체지향적이죠?
이와 같이 리팩토링은 변경이 필요할지도 모르는 코드들(이들을 ‘냄새’라고 부릅니다.)을 정형화해서 냄새 리스트(박스기사 참조)로 정리하고 각 냄새마다 리팩토링 해결책을 제시합니다. 좀더 많은 해결 비법을 알고 싶다면 참고자료 ?, ?를 참고하기 바랍니다. 참고자료 ?은 ?의 번역본입니다.

리팩토링을 언제 할까
리팩토링의 시작은 테스트입니다. 모든 코드는 그 코드에 대한 테스트 프로그램을 먼저 작성한 후 코드를 작성합니다. 코드에 작은 변경이 있을 때마다 항상 테스트를 실행하여 코드의 외부행동에 변화가 없는지를 체크해야 합니다. 그래야 그 코드를 사용하는 다른 코드에 영향을 미치지 않겠지요.
익스트림 프로그래밍을 지지하는 사람들은 리팩토링을 이용해 시스템을 구축합니다. 익스트림 프로그래밍(참고자료 ?)이라는 방법론에서는 간단한 설계→테스트 코드 작성→코딩→리팩토링을 반복하면서 전체 시스템을 확장시키는 방법으로 시스템을 개발합니다.
그렇다면 언제 리팩토링을 해야 할까요? 세 번이나 비슷한 코딩을 하게 될 때, 기능을 새로 추가해야 할 때, 버그를 수정해야 할 때, 코드 검토를 할 때 등을 열거하고 있습니다. 사실 리팩토링은 따로 시간을 내서 하는 것이 아니라 틈틈이 계속 해야 하는 일입니다. 기존의 코드 내용을 잊기 전에 하는 것이 더 좋습니다. 한 달이나 지난 후에 리팩토링하자면 기존 코드를 이해하느라 많은 시간을 보내야 하기 때문입니다.
그러나 모든 것이 다 그렇듯이 리팩토링도 만병통치약은 아닙니다. 대표적으로 데이터베이스 스키마를 수시로 바꾼다면 곤란하겠죠. 또 이미 상호간에 약속으로 정한 인터페이스를 마구 바꾸는 것도 문제가 될 겁니다.

코딩 속도를 향상시키려면
매일 아침 30분을 투자해 하루 계획을 짜면 그 30분 동안은 실제로 행한 일은 없지만 하루 동안 많은 시간의 절약 효과를 가져오는 것을 느껴본 적이 있을 겁니다. 리팩토링도 마찬가지입니다.
리팩토링 그 자체는 기존의 코드를 재정리하는 작업으로 겉으로 봐서는 전혀 생산성이 없는 일입니다. 새로운 기능은 전혀 추가되지 않았음에도 불구하고 시간을 잡아 먹었기 때문이지요. 관리자가 좋아할 리가 없습니다. 그러나 리팩토링에 투자한 시간은 소프트웨어의 디자인을 향상시켜서 더 이해하기 쉽게 만들어 줄 뿐 아니라 버그를 찾는 시간도 줄여줍니다. 그럼으로써 향후 프로그램을 더욱 빨리 작성할 수 있도록 도와줍니다.
코딩 속도를 향상시키고 싶습니까? 그렇다면 리팩토링에 투자해 보기 바랍니다.

정리 : 이종림 nowhere@korea.cnet.com

흠흠 냄새가 난다, 바로 여기를 고쳐야겠는걸!

‘냄새’란 리팩토링이 필요한, 아니면 리팩토링 해달라고 비명을 지르는 코드 구조를 말합니다. 파울러와 같이 작업한 켄트 벡이 갓 태어난 딸의 체취 때문인지 몰라도 리팩토링이 필요한 관점을 냄새의 관점에서 표현한 데서 기인했지요. 내 코드가 다음의 냄새 리스트에 해당된다면 리팩토링할 필요가 없는지 살펴봐야 합니다. 이름 번역은 참고자료 ?을 따랐습니다.

·중복된 코드(Duplicate Code) : 중복은 제발 피하자.
·긴 메쏘드(Long Method) : 긴 메쏘드는 이해하기도 유지보수하기도 어렵다.
·거대한 클래스(Large Class) : 클래스 하나가 너무 많은 일을 하면 역시 유지 보수하기 어렵다.
·긴 파라미터 리스트(Long Parameter List) : 긴 파라미터 리스트는 사용하기도 어렵고 다른 데이터가 필요할 때마다 고쳐야 한다.
·확산적 변경(Divergent Change) : 한 클래스가 다른 이유 때문에 계속 변경되어야 한다면 문제가 있다.
·산탄총 수술(Shotgun Surgery) : 하나를 변경하기 위해 여기 저기를 고쳐야 한다면? 빼먹기도 쉬울 것이다.
·기능에 대한 욕심(Feature Envy) : 메쏘드가 다른 클래스에 있는 정보를 더 많이 사용한다면? 그 메쏘드는 옮겨주는 게 더 낫다.
·데이터 덩어리(Data Clumps) : 데이터 여러 개가 같이 몰려다닌다면 하나의 객체로 만들어주는 게 낫다.
·기본 타입에 대한 강박관념(Primitive Obsession) : Date 클래스와 같이 기본 타입으로 월 일 숫자를 쓰는 것 보다 묶어서 객체로 만들어주는 게 훨씬 편리하다.
·Switch문(Switch Statements) : Switch문이 많다면 객체의 다형성을 고려해 보라.
·평행 상속 구조(Parallel Inheritance Hierarchies) : 한 클래스에 서브 클래스를 만들 때마다 비슷한 다른 클래스에도 또 서브 클래스를 만들어 줘야 한다면 문제가 있다.
·게으른 클래스(Lazy Class) : 하는 일 별로 없이 자리만 차지하는 클래스가 있으면 명예롭게 죽을 수 있도록 해주자.
·추측성 일반화(Speculative Generality) : ‘나중에 필요할지도 몰라’라는 의견 때문에 코드가 점점 복잡해진 적은 없는가? 사용되지 않는 것은 제거하라.
·임시 필드(Temporary Field) : 임시 필드가 왜 존재하는지를 파악하기란 참 힘들다.
·메시지 체인(Message Chains) : 어떤 객체를 얻기 위해 다른 객체에게 물어 보고 또 그 객체는 다른 객체에게 물어 보고…. 중간에 어떤 관계가 변경되면 변경될 게 많아진다.
·미들 맨(Middle Man) : 메쏘드 대부분이 다른 클래스에게 위임을 한다면 그 클래스에게 실제 해야 할 일이 뭔지를 알려줄 때가 온 것이다.
·부적절한 친밀(Inappropriate Intimacy) : 클래스가 서로 너무 친해서 사적인 부분을 보느라 너무 많은 시간을 보낸다면? 떼놓도록!
·다른 인터페이스를 가진 대체 클래스(Alternative Classes With Different Interfaces) : 같은 일을 하지만 인터페이스가 다른 메쏘드들이 있다면 프로토콜이 같아질 때까지 수정하고 이름을 동일하게 하라.
·불완전한 라이브러리 클래스(Incomplete Library Class) : 수정할 수도 없는 라이브러리가 불완전하다면 리팩토링 방법을 강구하자.
·데이터 클래스(Data Class) : 단순히 Get/Set 밖에 없는 클래스라면 좀더 책임을 주자.
·거부된 유산(Refused Bequest) : 서브 클래스가 부모 클래스의 상속을 거부하고 싶을 수도 있다. 심각하지 않으면 그냥 둬도 되지만 인터페이스를 거부한다면 신경을 써야 한다.
·주석(Comments) : 주석은 좋은 것이지만 코드가 복잡해서 알기 어려울 때 사람들은 길다란 주석을 단다. 코드가 제 스스로 자기가 하는 일을 설명하게 하자.


출처 : 마소
Trackback 0 Comment 0