2013-02-24 2 views
2

최근에 Ruby 클래스에서 load을 두 번 호출하면 버그가 발생하는 문제가 발생했습니다 (여기에 real-world example). 이는 클래스 본문에서 stateful 메서드 호출이 발생하고 load이이 메서드를 두 번 실행하게했기 때문입니다. 간단한 예는 다음과 같다 :Ruby 클래스 정의에서 클래스 수준 메소드 호출이 멱등수입니까?

base.rb :

class Base 
    def foo 
    puts "BASE" 
    end 
end 

derived.rb하십시오 REPL에서

require "./base" 

class Derived < Base 
    alias_method :foo_aliased, :foo 

    def foo 
    puts "DERIVED!" 
    end 
end 

실행이 예에서는

$ load './derived.rb' 
> true 
$ Derived.new.foo 
> DERIVED! 
> nil 
$ Derived.new.foo_aliased 
> BASE 
> nil 
$ load './derived.rb' 
> true 
$ Derived.new.foo 
> DERIVED! 
> nil 
$ Derived.new.foo_aliased 
> DERIVED! 
> nil 

, 제 load 원인 alias_method을 원래 앨리어스를 깨뜨리는 것. . 결과적으로 원본 메소드에 별명이없는 코드를 사용하지 못했습니다.

무차별 클래스 다시로드는 크게 load의 사용을 금지하는 것이 쉬운 일이 아닙니다 것을 (예를 들어, 당신은 그것을 Spork를 사용 RSpec에 구성에 대한 each_run 절에 많은 참조) 충분히 일반적입니다. 따라서 버그를 방지하는 유일한 방법은 클래스 정의가 "멱등수"가되도록하는 것입니다. 즉, 클래스 정의에서 호출하려는 메소드가 호출 횟수에 관계없이 동일한 결과를 생성해야합니다. 재로드가 더 많은 코드를 깨뜨리지 않는다는 사실은 무언의 관행을 제안하는 것처럼 보입니다.

루비 클래스 디자인을위한 스타일 가이드가 있습니까? 그렇다면 이러한 의미를 적용하는 일반적인 기술은 무엇입니까? 일부 메소드의 경우 동일한 메소드로 동일한 메소드를 재실행하지 못하도록 일부 메모를 수행 할 수 있지만 alias_method과 같은 다른 것들은 해결하기가 더 어려워 보입니다.

답변

1

당신은 완전히 틀렸어. 모든 클래스 메소드가 멱등수라고 가정하면 코드가 여러 번로드 될 때 코드가 중단되지 않을만큼 충분하거나 필수 조건이 아닙니다.

따라서 자연스럽게이를 적용 할 스타일 가이드가 없다는 결론을 얻었습니다.

+0

충분합니다. 파일이 모듈/클래스 만 정의한다는 추가 가정을 통해 클래스가 여러 번로드 될 때 다르게 동작 할 수있는 일반적인 경우를 알고 있습니까? –

+0

예를 들어 임의의 숫자를 사용하여 상수를 정의하고이를 시드로 사용하여 일부 문자열을 인코딩한다고 가정합니다. 로드 할 때마다 다르게 인코딩되며, 마지막로드에서 가져온 시드를 사용하여 디코딩하려고하면 이전에 인코딩 된 시드와 관련된 문제가 발생합니다. – sawa

+0

또한 충분하지만 공정한 요구 사항을 확장하면 클래스 정의 (메서드 호출 및 할당 포함)에 모든 상태 저장 표현식이 포함되므로 다시로드하는 것이 안전하다는 의미입니까? –