2013-04-30 1 views
4

저는 루비 문자열로 몇 가지 작업을 계획하고있는 루비 프로젝트에 참여하고 있습니다. 어떤 연산은 (단어의 수를 세는 것과 같이) 간단하고 (주어진 문자열이 올바른 언어인지 검사하는 것과 같이) 더 복잡한 연산도 있습니다.기본 루비 클래스를 원숭이에게 패치하는 것은 나쁜 습관입니까?

이를 구현하기위한 가능한 방법은 기존의 방법을 수정하지 않고 별도의 방법과 String 클래스, 패치 및 "some string".word_count"some string".cjk? 같은 행동을 추가하는 것입니다.

FileUtils을 기반으로 한 또 다른 접근법은 메서드가 가득한 클래스 또는 모듈을 만들고 OddClassName.word_count("some string")OddClassName.cjk?("some string")과 같이 항상 문자열을 매개 변수로 사용하는 것입니다. 우리는 가독성 때문에 처음부터 더 좋아합니다.

첫 번째 대안에서 설명한대로 기본 클래스에 패치하는 원숭이가 이름 충돌을 가질 수 있음을 이해합니다. 그러나이 라이브러리가 라이브러리가 아닌 기본 응용 프로그램이라면 전혀 걱정하지 않아도됩니까?

그래서, 질문은 다음과 같습니다

  • 는 기본 클래스 나쁜 관행을 루비 방법을 추가? 그렇다면 모든 경우 또는 일부 경우에만 있습니까?
  • 이 작업을 수행하는 가장 좋은 방법은 무엇입니까?
  • 'OddClassName'의 이름은 무엇이 될 수 있습니까?

대안을 제안하십시오.

+1

사용중인 Ruby 버전은 무엇입니까? 나는 2에있는 몇몇 다른 원숭이 헝겊 조각 선택권이다는 것을 믿는다.0 –

+0

@CharlesCaldwell 1.9를 사용하고 있지만 맞는다면 대답에 2.0을 자유롭게 추가하십시오. – fotanus

+1

질문에서 섹션을 표시 할 때 헤더를 사용할 필요가 없습니다. StackOverflow 룩앤필은 좀 더 대화적이고 덜 공식적입니다. 헤더를 제거하면 질문이 매우 잘 전달됩니다. "Ruby"와 같은 것들에 대해 적절한 이름을 대문자로 써야합니다. –

답변

4

원숭이 패치는 당신이 PatchedClass 관련 행동이없는 이상한 방법을 작성하지 않는 나쁜 관행으로 간주되지 않습니다 (예를 들어, String.monkeyPatchForMakingJpegFromString 오히려 나쁜이지만, Jpeg.fromString 충분하다.)

그러나 프로젝트가 상당히 큰 경우 라이브러리에서 사용하는 라이브러리에 충돌 패치가 발생할 수 있으므로 이러한 모든 패치 관련 문제가 하나 더있을 수 있습니다. Ruby 2.0에서는 개량이 도움이됩니다. 그들은 다음과 같이 작동합니다 : module, refine (심지어 핵심) 클래스를 정의한 다음 필요한 곳에 해당 모듈을 사용합니다.

YourClass.new.refinedMethodFromCoreClass #=> some result 

그러나

CoreClass.refinedMethodFromCoreClass 

undefined method 예외를 생성합니다 그래서, 당신의 코드에서 작동합니다.

원숭이 패치는 유용하고 편리하지만 세련미는 코드를보다 안전하고 유지 보수가 잘되며 깔끔하게 만드는 몇 가지 기능을 추가합니다.

+0

답변 해 주셔서 감사합니다. "Monkey patching은 기본적으로 나쁜 습관이라고 생각하지 않습니다."기본 수업에 적용 되었습니까? – fotanus

+0

[인터뷰 승/matz] (http://fredwu.me/post/36493181321/an-interview-with-yukihiro-matz-matsumoto), 6 번째 대답 : – tkroman

+0

감사합니다. 그는 기본 클래스를 확장 할 수 있다고 말합니다. , 그러나 그것이 좋은 연습이다라고 우리에게 이야기하지 않았다. 어쨌든이 점을 고려하십시오. – fotanus

1

단어 수를 늘리고 문서 작업과 같은 소리가 나기 때문에 새로운 클래스를 사용하고 싶습니다. Doc 또는 다른 클래스를 사용합니다.

문자열을 생성자 매개 변수로 사용하고 새 Doc를 반환하는 수정 체인을 지정합니다. 또한 문자열을 반환하는 to_s 메서드를 제공하십시오.

class Doc 
    def initialize(str) 
    @str = str 
    end 

    def to_s 
    @str 
    end 

    define word_count, cjk?, etc. 
end 

Doc.new("Some document").word_count 
# => 2 
관련 문제