The Ruby Way #2

Tags:

사실 너무 바빠서, 그리고 중간에 다른 책을 읽느라(디지로그, 책 읽어주는 남자), 셤공부하느라 몇장 걷어보지는 못했지만 인상 깊은 구절을 소개할까 합니다.

Let Ruby be Ruby.

이 책의 저자는 독일어를 배우던 중에 detusch 라는 단어는 고유명사(언어를 나타내는 명사니까)임에도 불구하고 왜 소문자로 기록하는가를 그의 선생님에게 묻습니다. 너무 이해가 안가서요. 그 선생님이 그러자 싱긋 웃으면서 이렇게 말했다고 합니다. “Don’t fight it.” 언어는 비록 많은 불규칙성을 갖고 있고 그들 중 일부는 이해가 안가보이지만 그대로 바라보라는 것이죠.

루비도 마찬가지입니다. 루비에서는 size가 있으면 length가 있습니다. 둘의 기능은 같죠. 또, collect/map 이 같습니다. 이것은 orthogonality에 문제되지 않는가? 왜 다른 언어처럼 표현방식을 최소화하지 않는가? 왜 private은 같은 클래스의 인스턴스끼리 접근할 수 없는가. 모두 Ruby를 Ruby이게 놔두란 말로 대답할 수 있습니다.

또한가지 저를 괴롭혔던 문제중에 하나인데, 예를들어 루비의 array는 다음과 같이 동작합니다.

irb(main):001:0> ary = %w{A B C D E}
=> ["A", "B", "C", "D", "E"]
irb(main):002:0> ary.shift
=> "A"
irb(main):003:0> ary
=> ["B", "C", "D", "E"]

그러나 우리는 분명히 Ruby에서의 파괴적인 동작을 하는 메소드에는 ! 가 붙어있음을 알고 있습니다. 따라서 shift에는 !가 있어야 할텐데 왜 그렇지 않은가. 이에 대한 대답은 어떤 메소드는 항상 파괴적이다란 것입니다. 이런 메소드에는 read가 있죠. 어떤 스트림에서 무언가를 read한다면 그것은 현재의 상태 – file descriptor라던가 – 를 무효화해버립니다. 하지만 이런 메소드들은 본질적으로 파괴적입니다. 따라서 별도로 !를 사용해 이 메소드가 파괴적임을 표시하지 않습니다. 이것이 루비에서 파괴적인 모든 메소드에 !가 붙지 않는 이유입니다. 그렇지 않다면 이 저자가 말한대로 프로그램이 마치 다단계 판매의 카달로그처럼 보여버리게 될테니까요.

그러면 어떤 메소드에는 !가 있어야하고 어떤 메소드에는 없어도 되는가. 여기에 Matz는 이렇게 대답합니다. “Follow your heart.”

이 외에 이 책의 1장은 SamKong님 말마따나 잘 쓰여진 OOP 에 대한 설명을 담고 있습니다. 예를들어, interface inheritance와 implementation inheritance의 구별이 그것입니다. 첫번째는 자바로 치면 implements 를 사용해 공통된 인터페이스를 제공하는 경우를 들 수 있습니다. 만약 C++이라면 typename T 를 받은뒤 T::some_method() 와 같이 메소드를 호출하는 경우를 들 수 있습니다. 물론 C++은 완전 추상 메소드를 사용해 인터페이스를 구현해서 쓸 수도 있습니다. implementation inheritance는 구현상속인데요, 이것은 우리가 흔히 알고 있는 자바의 extends, C++의 class Child: public Parent, Ruby의 class Child < Parent 가 그것입니다. 사실 읽어보면 다들 아시는 내용이겠지만, 한곳에 모아서 보는 것은 정말 오랜만인듯. 나머지 부분들은 대부분 howto 입니다. 또, 그 howto는 역색인 형태입니다. 예를들어 보통의 reference는 String의 메소드들을 줄줄이 나열하면서 이건 이렇고 저건 저렇고를 말하지만 이 책은 어떤 작업을 먼저 소개하고, 그 뒤 그 작업에 필요한 메소드들을 모아서 보여주는 식이죠. 이 책의 한가지 흥미로운 부분은 class instance variable에 대한 저자의 견해인데요. 그는 한마디로 딱 잘라, "이걸 어디다 쓰는지 모르겠다" 라더군요. ㅎㅎ (저도 모름)

Comments

6 responses to “The Ruby Way #2”

  1. 공성식 Avatar
    공성식

    >>그러면 어떤 메소드에는 !가 있어야하고 어떤 메소드에는 없어도 되는가.

    저도 처음에는 일관성이 없다고 느꼈었는데, 사실 그렇지는 않더군요.
    메소드가 modifier와 query 두 가지가 모두 존재할 때만 modifier에 !를 붙이더라구요.
    sort와 sort!처럼요.
    만약 모든 modifier에 !를 붙였다면 Hal의 말처럼 코드가 무척 지저분해졌을 거예요.
    루비만큼 신택스 정책을 잘 정한 언어는 못 봤습니다.

    >>class instance variable에 대한 저자의 견해인데요. 그는 한마디로 딱 잘라, “이걸 어디다 쓰는지 모르겠다” 라더군요.

    글쎄요, 사실 전 정반대의 견해를 갖고 있습니다.
    @@를 붙이는 class data는 사실 다른 언어에는 없는 개념입니다.
    자바의 static field는 루비의 class instance variable에 해당하죠.
    class data는 per-class가 아닌 per-hierarchy이기 때문에 때론 혼란을 야기합니다.
    상위 클래스에 동일 이름의 클래스 데이터가 추가되어 이름 충돌이 생길 경우 버그를 찾기가 쉽지 않습니다.
    그런데 사실 상위 클래스는 하위 클래스의 상황을 고려하지 않고 필드를 추가할 수 있는 거잖아요.

    아주 단순한 예제를 만들어 봤습니다.

    class Animal
    end

    class Dog 3
    puts Cat.number_of_cats #=> 3

    예상했던 대로 결과가 잘 나왔습니다.
    그런데 만약 Animal 클래스가 다음과 같이 변했다고 해보죠.

    class Animal
    #@@count = 0
    end

    그러면 위의 코드 결과는 다음과 같이 됩니다.

    puts Dog.number_of_dogs #=> 6
    puts Cat.number_of_cats #=> 6

    심플한 경우에야 상관없겠지만 클래스 계층이 복잡해지면 아주 미묘한 버그를 만들어 낼 수가 있거든요.
    그래서 제 생각엔, 가급적 class instance variable을 accessor를 만들어 사용하는 게 더 좋은 방법일 것 같습니다.
    OOP적인 관점에서도 그렇구요.(minimize data scope!!)

    루비 그룹 내에서도 이에 관해서는 두 그룹으로 의견이 나뉘어져 있더군요.

  2. MKSeo Avatar
    MKSeo

    제 생각엔 상황에 따라 용도는 두가지 모두에 대해 만들 수 있을 것 같습니다. 다만 저는 책의 저자가 ‘모르겠다’고 하다는게 좀 그랬어요;; 뭐 옛날에 나온 책이라 그럴 수도 있겠지만.

  3. 공성식 Avatar
    공성식

    지금 다시 보니 코드가 잘렸네요.
    왜 그럴까요?
    다시 올립니다.

    class Animal
    end

    class Dog

  4. 공성식 Avatar
    공성식

    어라 또 깨지네요.
    게시판이 루비 코드를 별로 안 좋아하나봐요.
    다음 링크에 올렸습니다.

    http://123.writeboard.com/99b52ecd894deabea

  5. MKSeo Avatar
    MKSeo

    ㅎㅎ 네이버 블로그에 올리고 트랙백하시지..

  6. 무책 Avatar

    ㅎㅎ 공성식님 그게 저도 전에 여기 코멘트 올리다 보니까 서브클래싱하는 기호가 HTML 태크 시작 기호랑 같아서 (아 이거 말로 풀어쓰려니…ㅋㅋ) 그것만 들어가면 왕창 날아가더라구요.

    서민구님 서평 잘 읽었습니다. 또 읽으시다가 좋은 얘기 나오면 소개해 주시길. 2판 나오면 꼭 사야겠습니다.

Leave a Reply

Your email address will not be published. Required fields are marked *