복붙노트

[RUBY-ON-RAILS] 어떻게 instance_eval 작업을 수행하고 DHH는 왜 싫어합니까?

RUBY-ON-RAILS

어떻게 instance_eval 작업을 수행하고 DHH는 왜 싫어합니까?

그의 RailsConf 프레 젠 테이션에 대한 19시 마크에서, 데이빗 하이네 마이에 한손은 instance_eval의 단점에 대해 이야기 :

이것은 흥미로운 소리지만) 나는 처음에 어떻게 방법 instance_eval 작품을 모르는 나쁜 / 증가 복잡성이 될 수있는 이유 b)는 이해가 안 돼요.

누군가가 설명 할 수 있습니까?

해결법

  1. ==============================

    1.instance_eval가하는 것은 그것이 다른 인스턴스의 맥락에서 블록을 실행하는 것입니다. 즉,이 경우의 방법과 인스턴스 변수의 의미를 변경하는 수단 자체의 의미를 변경한다.

    instance_eval가하는 것은 그것이 다른 인스턴스의 맥락에서 블록을 실행하는 것입니다. 즉,이 경우의 방법과 인스턴스 변수의 의미를 변경하는 수단 자체의 의미를 변경한다.

    이것은인지 적 분리를 만듭니다 블록이 실행되는 컨텍스트는 화면에 표시되는 상황이 아니다.

    나 @ 매트 브릭스의 예에 약간의 변화와 함께 그을 보여 보자. 의 우리가 대신 형식의 이메일을 구축하고 있다고 가정 해 봅시다 :

    def mail
      builder = MailBuilder.new
      yield builder
      # executed after the block 
      # do stuff with builder 
    end
    
    mail do |f|
      f.subject @subject
      f.name    name
    end
    

    이 경우, @subject는 개체의 인스턴스 변수이며 이름은 클래스의 방법이다. 당신은 좋은 객체 지향 분해를 사용하여 변수에 피사체를 저장할 수 있습니다.

    def mail &block
      builder = MailBuilder.new
      builder.instance_eval &block
      # do stuff with builder 
    end
    
    mail do 
      subject @subject
      name    name # Huh?!?
    end
    

    이 경우, @subject는 메일 빌더 개체의 인스턴스 변수입니다! 심지어 존재하지 않을 수도 있습니다! (또는 더 나쁜, 그것은 존재하고 일부 완전히 바보 같은 값을 포함 할 수 있습니다.) 당신이 개체의 인스턴스 변수에 접근 할 방법이 없습니다. 어떻게 당신은 당신의 오브젝트의 이름 메소드를 호출합니까? 당신이 그것을 호출 할 때마다, 당신은 메일 빌더의 방법을 얻을.

    기본적으로, instance_eval는 하드 DSL 코드 내부에 자신의 코드를 사용할 수 있습니다. 이 필요할 수도 있다는 아주 작은 기회가 어디 그래서, 정말 유일한 경우에 사용한다.

  2. ==============================

    2.좋아, 그래서 여기에 아이디어는 대신이 같은입니다

    좋아, 그래서 여기에 아이디어는 대신이 같은입니다

    form_for @obj do |f|
      f.text_field :field
    end
    

    당신이 뭔가를 얻을

    form_for @obj do 
      text_field :field
    end
    

    첫 번째 방법은 당신이 패턴 결국, 꽤 정직 그 같은 외모

    def form_for
      b = FormBuilder.new
      yield b
      b.fields.each |f|
        # do stuff
      end
    end
    

    양식을 작성 (또는 무엇이든) 당신은 소비자가 메소드를 호출하는 빌더 객체를 산출하고, 그 후에 당신은 실제로에 빌더 객체에 메소드를 호출

    두 번째는 좀 더 마법

    def form_for &block
      b = FormBuilder.new
      b.instance_eval &block
      b.fields.each |f|
        #do stuff
      end
    end
    

    대신 블록에 빌더를 산출이 하나, 우리는 블록을 가지고 빌더의 맥락에서 그것을 평가

    당신이 종류의 범위가 게임을 재생하기 때문에 두 번째 증가의 복잡성, 당신은 그것을 이해할 필요하고, 소비자의 요구는 이해하고, 빌더의 요구를 썼다 누구든지 그것을 이해합니다. 모두가 같은 페이지에있는 경우, 나는 그것이 nessicarily 나쁜 일이라고 모르겠지만, 비용 대 효과가, 내 말 질문, 그것이 F 다만 택 얼마나 어려운 작업을 수행. 당신의 방법 앞에?

  3. ==============================

    3.아이디어는 당신이 확신 할 수 없다 당신이 모든 코드를 읽지 않고 뭔가를 중단하지 않을거야에있는 작은 위험이다 그 개체에 대한 사용자의 사용 instance_eval를 다룬다.

    아이디어는 당신이 확신 할 수 없다 당신이 모든 코드를 읽지 않고 뭔가를 중단하지 않을거야에있는 작은 위험이다 그 개체에 대한 사용자의 사용 instance_eval를 다룬다.

    당신이 말한다면 또한, 많은 인터페이스를 변경하지 않은 라이브러리를 업데이트하지만 당신이 정말로 어떤 피해를 할 수있는 객체의 내부를 많이 바뀌었다.

  4. from https://stackoverflow.com/questions/3071532/how-does-instance-eval-work-and-why-does-dhh-hate-it by cc-by-sa and MIT license