Posts Tagged ‘Ruby’

Ruby를 배우는 Java 개발자가 알아야 할 10가지 part 3

Tuesday, January 9th, 2007

Java 개발자가 알아야 할 10가지

Item #4 믹스인(Mix-In)을 사용한 클래스 확장

루비는 인터페이스가 없지만 모듈로 정의된 믹스인이 있다.

모듈이란..

  • 네임스페이스이다. (클래스와 유사)
  • 메소드를 가질 수 있다. (클래스와 유사)
  • 객체화될 수 없다. (클래스와 다름)
  • 클래스에 포함될 수 있다.
  • - 모듈의 메소드는 클래스의 메소드가 된다.

믹스인 재사용

module LessComparable
  def >(other)
    other < self
  end
  # Other methods defined in terms of less than:
  #     <=, >=, ==
end
class Pair
  include LessComparable
  attr_accessor :first, :second
  # …
  def <(other)
    (first < other.first) ||
      (first == other.first && second < other.second)
  end
end

Item #3 구문(closure) 감싸기

  • Iteration
  •   [1,2,3].each do |item| puts item end
    
  • Resource Management
  •   file_contents = open(file_name) { |f| f.read }
    
  • Callbacks
  •   widget.on_button_press { puts "Got Button Press" }
    

Item #2 ri 는 당신의 친구, irb 도 당신의 친구

  • ri
  • 루비 정보(Ruby Information). 표준 루비 객체에 대한 메뉴얼 페이지(Man pages)

    $ ri Array
    ---------------------------------------------------------- Module: Array
         Arrays are ordered, integer-indexed collections of any object.
         Array indexing starts at 0, as in C or Java. A negative index is
         assumed to be relative to the end of the array---that is, an index
         of -1 indicates the last element of the array, -2 is the next to
         last element in the array, and so on.
    ------------------------------------------------------------------------
    Includes:
    ---------
         Enumerable(all?, any?, collect, detect, each_with_index, entries,
         find, find_all, grep, include?, inject, map, max, member?, min,
         partition, reject, select, sort, sort_by, to_a, zip)
    Class methods:
    --------------
         [], new
    Instance methods:
    -----------------
         &, *, +, -, <<, <=>, ==, [], []=, assoc, at, clear, collect,
         collect!, compact, compact!, concat, delete, delete_at, delete_if,
         each, each_index, empty?, eql?, fetch, fill, first, flatten,
         flatten!, frozen?, hash, include?, index, indexes, indices, insert,
         inspect, join, last, length, map, map!, nitems, pack, pop, push,
         rassoc, reject, reject!, replace, reverse, reverse!, reverse_each,
         rindex, select, shift, slice, slice!, sort, sort!, to_a, to_ary,
         to_s, transpose, uniq, uniq!, unshift, values_at, zip, |
    
    $ ri Array#last
    ————————————————————- Array#last
         array.last     =>  obj or nil
         array.last(n)  =>  an_array
    ————————————————————————
         Returns the last element(s) of _self_. If the array is empty, the
         first form returns +nil+.
    
            [ “w”, “x”, “y”, “z” ].last   #=> “z”
    
  • irb
  • 루비 콘솔(Interactive Ruby). 콘솔 기반의 루비 실행기(Ruby interpreter)

    $ irb --simple-prompt
    >> 1 + 2
    => 3
    >> Proc.instance_methods(false)
    => ["[]", "==", "dup", "call", "binding", "to_s",
        "clone", "to_proc", "arity"]
    

Item #1 이제 길고 긴 코드 작성은 그만!

동료 개발자 왈…

난 문제 해결을 위해 루비를 사용해보기로 했다. 그리고 코드를 좀 작성했는데, 이런~ 그 순간 이미 문제가 다 해결됐음을 알게됐다.

예제 코드
* Copland (Hivemind의 Ruby 버젼) VS Needle Libraries
* Rake (Make의 Ruby 버젼)

Ruby를 배우는 Java 개발자가 알아야 할 10가지 part 2

Monday, January 8th, 2007

Java 개발자가 알아야 할 10가지

Item #6 객체들은 강한 타입이며 정적 타입이 아니다.

타입은 값들(value)의 집합이다.
타입은 연산(operation)들의 집합이다.

C Code (Weak)

#include 
extern float two();
int main() {
    float x = 1.5   two();
    printf(”%f\n”, x);
    printf(”%d\n”, x);
    return 0;
}

int two() { return 2; }

# Output
nan
0

Java Code (Strong)

public class Main {
  public static
    void main (String args[]) {
    double x = 1.5   Two.two();
    System.out.println(x);
  }
}

public class Two {
  public static int two() {
    return 2;
  }
}

# Output
3.5

Ruby Code (?)

require 'two'

x = 1.5   two
puts x
printf "%d", x

def two
  2
end

# Output
3.5
3

언어의 타입을 안전하게 해주는 것은 무엇일까?

  • 컴파일러가 변수의 타입을 안다.
  • 모든 변수를 선언한다.
  • 컴파일러가 타입 에러를 잡는다.

Or 연산할 때, 컴파일 시에, 런타임에 부적절한 타입을 잡아낸다.

Ruby Code

def factorial(n)
  result = 1
  (2..n).each do |i|
    result *= i
  end
  result
end

puts factorial(20)
puts factorial(21)

# Output
2432902008176640000
51090942171709440000

Java Code

public class Fact {
  static long factorial(long n) {
    long result = 1;
    for (long i=2; i<=n; i  )
      result *= i;
    return result;
  }
  public static
    void main (String args[]) {
    System.out.println(factorial(20));
    System.out.println(factorial(21));
  }
}

# Output
2432902008176640000
-4249290049419214848

Lanaguage Typing Systems

    Java

  • 강한 타입
  • 정적인 타입
  • 명시적 타입
    Ruby

  • 강한 타입
  • 동적인 타입
  • 함축적 타입

Item #5 인터페이스 걱정은 이제 그만

루비는 바보 타입(Duck Typing)을 사용한다.
- 만일 그것이 오리 같이 걷고, 오리 같이 운다면..
- 우리는 그것을 오리라고 여기겠다. (아니면 말고~)

공통 인터페이스를 구현할 필요가 없다

class Duck
  def talk() puts "Quack" end
end
class DuckLikeObject
  def talk() puts "Kwak" end
end
flock = [
  Duck.new,
  DuckLikeObject.new ]
flock.each do |d| d.talk end

Ruby를 배우는 Java 개발자가 알아야 할 10가지 part 1

Sunday, January 7th, 2007

Java 개발자가 알아야 할 10가지

RUBY-DOC.ORG의 “10 Things Every Java Programmer Should Know About Ruby”를 번역한 문서입니다.

Ruby는 OOP이기 때문에 Java 개발자는 매우 익숙하게 다가갈 수 있다. 하지만 Java 스타일로 Ruby 프로그래밍을 하려고 하면 Ruby가 줄 수 있는 많은 가능성을 놓치기 쉽다.

생각과 행동은 사용하는 언어에 의해 영향을 받게 된다. 이 글은 “Ruby가 Java 보다 우수하다”라는 주장의 글이 아니라, Java 개발자가 Java 스타일로 Ruby 프로그래밍하는 것을 피해서 Ruby 방식으로 프래그래밍하는 방법을 발견할 수 있게 해주기 위한 글이다.

프로그래밍에 대해서 생각하는 방식에 영향을 주지 않는 언어는 배울 가치가 없다 ? Alan Perlis

Item #10 Ruby의 규약(Convention)을 익혀라

  • ClassNames (클래스명)
  • method_names and variable_names (메소드명이나 변수명)
  • methods_asking_a_question? (질문형 메소드는 물음표 사용)
  • slightly_dangerous_methods! (중요한 메소드는 느낌표 사용)
  • @instance_variables (클래스 멤버 변수)
  • $global_variables (static 변수)
  • SOME_CONSTANTS or OtherConstants (상수)

Item #9 모든 것은 객체(Object)다

  • 클래스는 객체다!
  • Array는 배열 클래스 객체의 이름이다.
    새로운 객체를 생성하기 위해서는 특별한 문법을 사용할 필요 없이, 클래스 객체에 new 를 보내면 된다.

    a = Array.new
  • 이 방식은 팩토리 패턴을 필요없게 한다.
  • 클래스는 자신의 인스턴스를 만들 수 있기 때문에, 자체로 완전한 팩토리 객체다.

    def create_from_factory(factory)
      factory.new
    end
    obj = create_from_factory(Array)
    
  • Primitives도 없다!
  • 0.zero?    # => true
    1.zero?    # => false
    1.abs      # => 1
    -1.abs     # => 1
    1.methods  # => list of methods for object 1
    2.+(3)     # => 5  (same as 2+3)
    10.class   # => Fixnum
    (10**100).class
               # => Bignum
  • nil 도 객체다! (Java의 null)
  • a = nil
    a.nil?     # => true
    a.methods  # => list of methods
    a.abs      # => NoMethodError

    Java에서 null은 객체가 아니다. method 사용 불가. 참고

  • 객체가 아닌 것들
  • 변수명은 객체가 아니다
    블럭은 객체가 아니다.

Item #8 (거의) 모든 것은 메시지다

  • 이름을 객체에 묶는다. Binding names to objects (assignment)
  • 구조나 연산자를 조절한다. Primitive controls structures (e.g. if/else, while) and operators (e.g. defined?)
  • 객체에 메시지를 보낸다. Sending messages to objects
  • string.index("x")
        Send :index (with argument "x")
    string.length
        Send :length (with no argument)
    run_status_reports
        Send :run_status_reports (to self)
    1 + 2
        Send :+ (with argument 2) to the object 1
    array[i]
        Send :[] (with argument i) to the array

    Ruby 프로그래머는 obj.mothod를 객체에 메시지를 보내는 것으로 생각하는 경향이 있다.
    Java 프로그래머는 obj.method를 객체에서 메소드를 찾아서 그것을 호출하는 것으로 생각하는 경향이 있다.

    이 미묘한 차이는 매우 중요하다. 다음 클래스를 보면, 보내지는 모든 메시지를 저장했다가 그 메시지를 다른 객체에 보내는 클래스를 정의하고 있다.

    class VCR
      def initialize
        @messages = []
      end
      def method_missing(method, *args, &block)
        @messages << [method, args, block]
      end
      def play_back_to(obj)
        @messages.each do |method, args, block|
          obj.send(method, *args, &block)
        end
      end
    end
    
    vcr = VCR.new
    vcr.sub!(/Java/) { "Ruby" }
    vcr.upcase!
    vcr[11,5] = "Universe"
    vcr << "!"
    string = "Hello Java World"
    
    puts string
    # => Hello Java World
    
    vcr.play_back_to(string)
    puts string
    # => HELLO RUBY Universe!
  • 메시지를 사용해서 얻을 수 있는 것들…
  • - Remote Proxies - 원격 객체에 메시지를 자동적으로 보내준다.
    - Auto Loaders - 첫번째 메시지가 올때까지 기다린 후, 메시지를 로드한 후 일반적인 프록시처럼 행동한다.
    - Decorators - 원하는 메시지는 가로채고 나머지는 통과시킨다.
    - Mock Objects - 흉내(mock)낼 메소드를 작성한 후 나머지는 필요에 따라 위임하거나 무시한다.
    - Builders - 빌더에 호출된 메소드에 따라 XML/HTML/등등을 생성한다.

Item #7 Ruby는 매우 동적이다

  • Java는 C++ 보다 동적인 언어다. 하지만 Ruby는 Java보다 몇 단계 더 동적이다.
  • - method_missing
    위의 VCR 클래스 참고

    - 쉬운 리플랙션(Reflection)
    [Java Code]

    public static Object create(Class c, String value)
      throws Exception
    {
      Constructor ctor = c.getConstructor(
        new Class[] { String.class } );
      return ctor.newInstance(
        new Object[] { "Hello" } );
    }
    
    public static void main (String args[])
      throws Exception
    {
      Greeting g =
        (Greeting) create(Greeting.class, "Hello");
      g.show();
    }

    [Ruby Code]

    def create(klass, value)
      klass.new(value)
    end
    
    g = create(Greeting, "Hello")
    g.show

    - 열린 클래스
    언제든지 클래스에 메소드를 추가할 수 있따. 심지어 빌트인 클래스에도 추가할 수 있다.

    class Integer
      def even?
        (self % 2) == 0
      end
    end
    
    p (1..10).select { |n| n.even? }
    # => [2, 4, 6, 8, 10]

    - 싱글턴 객체
    싱글턴 메소드는 클래스가 아닌 개별 객체에 정의될 수 있다.

    class Dog
    end
    
    rover = Dog.new
    fido = Dog.new
    
    def rover.speak
      puts "Red Rover"
    end
    
    rover.speak  # => "Red Rover"
    fido.speak   # => NoMethodError

    - Definition Hooks
    갈고리(Hook)는 사용자가 프로그램 실행 도중 특정 시점에 컨트롤을 가질 수 있게 해준다.

    class MyClass
      def MyClass.method_added(name)
        puts "Adding Method #{name}"
      end
    
      def new_method
        # Yada yada yada
      end
    end
    # => Adding Method new_method

    - 코드 평가

    class Module
      def trace_attr(sym)
        self.module_eval %{
          def #{sym}
    	printf "Accessing %s with value %s\n",
    	  "#{sym}", @#{sym}.inspect
    	@#{sym}
          end
        }
      end
    end
    
    class Dog
      trace_attr :name
      def initialize(string)
        @name = string
      end
    end
    
    Dog.new("Fido").name  # => Accessing name with value "Fido"