segunda-feira, março 17, 2008

Avanço tecnológico às avessas...

Não sei se porque ando lendo coisas subversivas mas ando com a nítida impressão que estamos andando em círculos ao invés de fazer avanços na área de software... Alguns fatos me deram essa impressão: 1 - "Redescoberta" de closures -> coisa que antes do hype do Ruby ninguém dava bola, e agora é a discussão do momento. Só que isso existe desde 58 com LISP. Ou, se vc quiser uma roupagem mais moderna, desde 78 com Smalltalk. (Clipper tb tinha, alguém lembra?) 2 - Domain Driven Development -> não entrei muito a fundo, mas me parece basicamente o que o pessoal do movimento O.O. de 1970 e uns quebrados pregava. 3 - TDD -> okay, mesmo o Kent Beck confessava que isso não era novidade. 4 - Uma entrevista com John McCarthy (criador do LISP) na InfoQ -> Tem uma pergunta quase no final da entrevista sobre LISP sendo citado como influência para novas linguagens: "...many modern programming languages like Ruby are claiming big influences from Lisp..." McCarthy confessa que não conhece Ruby, mas pergunta: "Does it use, for example, list structures as data?" O entrevistador responde negativamente, e McCarthy completa: "So if you want to compute with sums and products, you have to parse every time? So, in that respect Ruby still isn't up to where Lisp was in 1960." Interessante... Existem alguns outros pequenos fatos aqui e ali, pequenos demais pra eu estar totalmente consciente deles, mas ando sentindo um "deja vu" desgramado. Será que sei pouco e na verdade há um avanço nessas coisas que não estou percebendo ou será que sei o suficiente e realmente estamos andando em círculos em algumas coisas? Como eu sempre assumo que não sei o suficiente, a questão agora está em saber o que não estou percebendo. Toca estudar mais... :)

quarta-feira, março 12, 2008

Sobrecarga de métodos em Ruby

Uma das coisas muito legais que o Java possui é sobrecarga de métodos (várias vezes confundido com polimorfismo) que é a capacidade de possuir métodos diferentes com mesmo nome, mas com parâmetros diferentes. Bom, isso não existe em Ruby, mas nada impede que isso seja implementado. Rascunhei isso aqui: class Object
  
  def self.generate_method_name_for(method_name, *parameter_types)
    # Usamos espaços no nome dos métodos gerados para evitar chamadas acidentais
    "#{method_name}_#{parameter_types.collect{|it| it.to_s}.join(' ')}".to_sym
  end
  
  def self.def_method(method_name, *parameter_types, &block)
  
    # Definindo o método genérico da classe,
    define_method method_name.to_sym do |*params|
      send("#{method_name}_#{params.collect{|it| it.class.to_s}.join(' ')}", *params)
    end unless self.method_defined?(method_name.to_sym)
    
    #Definindo cada método específico
    specific_method = generate_method_name_for(method_name, *parameter_types)
    
    define_method(specific_method, &block)
    
  end
end
E para usar: class Test
  def_method :test, String, String do |a, b|
    puts "Duas strings"
  end
  
  def_method :test, String do |a|
    puts "Uma string"
  end
  
  def_method :test, Fixnum do |a|
    puts "Um número"
  end
end


x = Test.new

x.test("a", "b")
x.test("a")
x.test(1)
É lógico que isso custa desempenho, mas serve. Acho também que o código poderia ser grandemente melhorado, até pq não sei se isso funcionaria corretamente com herança e polimorfismo, mas não quis perder mais tempo brincando nisso :) Moral da história: adoro classes abertas.