Header

  1. View current page

    딥뿔이 자라나는 노트

Profile_image?t=1225424611&type=big
나를 바꾼 똑똑한 생활 습관, 스프링노트 - 여러분도 지금 시작해보세요!
71

method_missing과 친절한 루비씨

이전글: Object#returning - 문법 사탕  전체보기

 

레일스 프로젝트의 개발 환경 테스트 파일(config/environments/development.rb)에는 다음과 같은 내용을 찾아볼 수 있습니다.

 

  1. config.whiny_nils = true

 

이렇게 설정을 하고, 널(nil) 객체의 메서드를 호출하면, 'nil을 기대한 게 아니지? 뭔가 잘못된 부분이 있을 거야. 더 찾아봐'라며 투덜거립니다. 루비에 익숙한 개발자에게라면 일반적인 NoMethodError만으로 충분하겠지만, 아직 익숙하지 않은 개발자라면, 정확히 어느 부분이 문제인지 찾지 못할 수 있습니다. 이런 경우를 위해 친절하게도 조그마한 힌트 메시지를 출력하도록 했습니다. (과도한 친절 같지만, 몇 명에게라도 도움이 된다면야^^)

 

예를 들어 id 메서드를 호출했는데 수신자(호출을 받는 객체)가 nil이라면 nil의 id를 부른 것은 잘못이라고 출력합니다.

 

  1. >> nil.id
    RuntimeError: Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id

 

그 외에도 split 메서드를 호출했는데, 수신자가 nil이면 이 메서드를 호출했을 때는 배열을 기대했을 확률이 높기에 관련 메시지를 출력해줍니다.

 

  1. >> nil.split
    NoMethodError: You have a nil object when you didn't expect it!
    You might have expected an instance of Array.

 

save나 update 같은 ActiveRecord::Base 클래스의 메서드들도 감지합니다.

 

  1. >> nil.save
    NoMethodError: You have a nil object when you didn't expect it!
    You might have expected an instance of ActiveRecord::Base.

 

과연 어떻게 구현했을까요? 전에 설명한 대로 루비의 클래스는 항상 열려있고, 프리미티브 타입이라고 분류될 수도 있는 nil 객체도 얼마든지 확장할 수 있습니다. 그렇다면 NilClass(nil 객체의 클래스)를 열어서 메시지를 출력하도록 하면 됩니다.

 

  1. class NilClass
    1. def id
      1. raise RuntimeError, "Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id", caller
    2. end
  2. end

 

그런데, 위에서 본 예제처럼 split 메서드를 호출했을 때 에러 메시지를 출력하려면, split 메서드를 구현해야 할까요? 그렇다면 친절을 베풀 메서드 목록을 만들고 그 메서드들을 모두 구현해야 할텐데요. 너무 가혹하군요.

 

다행히도 루비는 Kernel#method_missing이라는 메서드를 지원합니다. 이 메서드를 재정의하면, 일반적으로 처리하지 못하는 모든 메서드들을 다룰 수 있습니다. 레일스에서 find_by_user_name, create_or_initialize_by_user_id_and_page_id 와 같은 메서드들이 이런 식으로 처리됩니다.

 

  1. class NilClass
    1. def method_missing(method, *args, &block)
      1. raise_nil_warning_for @@method_class_map[method], method, caller
    2. end
  2. end

 

method_missing은 도메인 언어를 만드는데 꼭 필요한 기능입니다. 이를 활용하면 보다 유연한(풍부한) 언어셋을 정의할 수 있습니다. 하지만 반대로 추적하기 힘든(읽기 힘든) 코드를 만들 수도 있습니다. 꼭 필요한 곳에만 사용해야 합니다.

 

- 강문식

History

Last edited on 06/20/2007 19:59 by deepblue

Comments (0)

You must log in to leave a comment. Please sign in.