Traçando a Execução em Bibliotecas de Terceiros (em Ruby)

Ontem, acredito que esbarrei feio num bug do Ruby 1.8 (não sei se outras versões estão com o mesmo problema). Para encurtar a longa história, estava mexendo num código usando TheRubyRacer semelhante ao seguinte (nota: se você não entender o código a seguir, vale a pena dar uma olhada em meu post anterior):

class UmaClasse
  def method_missing(method, *args, &b)
    puts "Método #{method} chamado!"
    ...
  end
end

require 'v8'
context = V8::Context.new
context['classe'] = UmaClasse.new
p context.eval('classe.um_metodo')
p context.eval('classe.um_metodo = 10')

O que eu esperava, é que na linha 11, fosse impressa a mensagem “Método um_metodo chamado!”, porém o que aconteceu não foi bem isso. Quando olhei para a documentação da biblioteca, descobri que ela expõe apenas os métodos públicos por padrão, agora COMO ela fazia isso… isso já é outro problema. Então, num primeiro momento, resolvi remover todos os métodos da classe UmaClasse, e ver o que acontecia:
(more…)

Conectando Javascript e Ruby

Bom, a algum tempo vi uma biblioteca chamada Harmony, para Ruby, que tenta fazer esse processo. Porém, eu achei alguns problemas na biblioteca que meio que me impediam de usá-la do jeito que eu queria, então acabei encontrando uma outra alternativa: The Ruby Racer.

Esta biblioteca usa o interpretador V8, o mesmo usado no Google Chrome, para interpretar Javascript. Possui uma API bem simples, e consegue incorporar objetos Ruby no Javascript de uma forma bem transparente. Como exemplo, digamos que queremos expor uma classe Ruby para o Javascript. Basta usar o código a seguir:

require 'v8'

class UmaClasse
  def initialize(nome)
    @nome = nome
  end

  def imprimir_nome
    puts @nome
  end
end

js = V8::Context.new
js['uma_classe'] = UmaClasse.new
js.eval('uma_classe.imprimir_nome()')

Este código conectará, no Javascript, um objeto chamado uma_classe. Para instalar a biblioteca, um simples “gem install therubyracer” basta, na maioria das vezes. Quando isso não funciona (que nem o meu caso)…
(more…)

Dá para fazer tipagem estática em Ruby?

Bom, resolvi começar uma série – coisas que você NUNCA quis fazer com Ruby, e tinha medo de perguntar. Basicamente, pensei em montar códigos absurdos de coisas que são completamente contra a filosofia da linguagem, ou que pelo menos são muito esquisitas, e publicar aqui os resultados. As regras são simples: os resultados devem ser testáveis (com RSpec, de preferência) e devem ser escritas puramente em Ruby, de preferência sem nenhuma biblioteca auxiliar (e, se for necessário usar, é obrigatório que a biblioteca tenha sido escrita puramente em Ruby também).

Como primeiro da série, vamos simular uma tipagem estática em Ruby. Como é impossível sobrescrever o operador “=” em Ruby, resolvi usar uma função – static – para simular o mesmo comportamento. Para simplificar, vamos meio que definir uma “variável global” com “static.”, e definir que esta terá tipagem estática. Começamos definindo uma função chamada “static”

def static
  Static.instance
end

(more…)

Porque o Rubinius é importante.

Muita gente já falou sobre o assunto, e eu percebi, até agora, que não dei minha opinião então…

Para as pessoas que estão interadas, Rubinius é uma implementação de Ruby sobre Ruby. Parece estranho, e é um pouco mesmo, então vale a pena mostrar mais como isso funciona. Nos outros interpretadores, uma boa parte das classes padrão da linguagem são implementadas em C (ou Java, no caso do JRuby). Em Rubinius, estas classes são implementadas em Ruby sempre que possível, e a máquina virtual (VM, atualmente estão usando o LLVM) é extremamente simples e otimizada. Com isso, além de Ruby ficar muito mais flexível (mais? sim, é sempre possível) ainda se ganham alguns conceitos interessantes. Para fazer esta “mágica”, é necessário um compilador que traduz código Ruby para bytecodes que serão executados na LLVM – e Rubinius escreveu este compilador totalmente em Ruby. Pode parecer um conceito absurdo, mas não é – o próprio compilador C da Gnu, o GCC, é escrito em C.
(more…)

A importância do código-fonte

Talvez o nome deste post seja estranho, em um blog tão focado à programação. Porém, vale um pouco de história.

De duas semanas para cá, estou escrevendo um artigo para tentar apresentar no Workshop Brasileiro de Métodos Ágeis. Inclusive, eu recomendo a todos que trabalham a um certo tempo com uma linguagem, tecnologia, etc, que escrevam um artigo sobre o assunto, mesmo que não seja em formato científico, só para organizar as idéias. Ajuda bastante a focalizar seus próximos passos. Porém, esse não é o assunto. O assunto é bem simples, na verdade:

Design de Software.

Tentei traçar as origens da tal “metodologia em cascata”, e não consegui. O artigo mais antigo que eu cheguei foi de Winston Royce, em 1970 (sim, 1970 – é difícil de acreditar que a maioria das metodologias de desenvolvimento de software de hoje se baseiam numa idéia que surgiu a 40 anos atrás), e Royce sequer nomeia a metodologia. Na verdade, ele apresenta o desenho típico de uma metodologia em cascata e comenta: “a implementação acima é arriscada e convida à falhas”. Seria possível que, na informática, alguém em 1970 apresenta o modelo que mais tarde seria chamado de “cascata”, diz para as pessoas não usarem, e as pessoas começam a usá-lo? Bom, sendo informática, eu não duvido de nada (nem de doutores em engenharia de software citando que até uma metodologia em cascata é melhor do que as metodologias ágeis – sim, eu ouvi isso). Enfim…

Mas, voltando ao tópico – a metodologia que Royce propôe enfatiza a documentação. Mais tarde, essa documentação seria unificada pela UML, e uma série de estudiosos iriam “contribuir” para a tal UML, criando mais e mais diagramas… além daquelas coisas obsoletas, tipo fluxograma, “teste de mesa”, etc etc. Aqui, vale a pena citar Jack Reeves, que pergunta em seu artigo (de 1992): “O que é design de software?”. O artigo é extenso, mas transcrevo umas partes aqui:

O objetivo final de qualquer atividade de engenharia é algum tipo de documentação. Quando um trabalho de design foi completado, a documentação é entregue à manufatura. Eles são um grupo completamente diferente, com habilidades completamente diferentes do time do design. Se a documentação realmente representa um design completo, o time da manufatura pode proceder para construir o produto. De fato, eles podem proceder para construir uma grande parte do produto, sem qualquer intervenção dos designers. Depois de revisar o ciclo de desenvolvimento de software, da forma que eu entendo, eu concluo que a única documentação de um software que, na verdade, satisfaz o critério de uma documentação de design é o código-fonte.
(more…)

Smalltalk, e a noção de objetos

Em outro artigo meu, citei como uma linguagem como Java pode ser usada para programação procedural, mesmo sendo “orientada a objeto”. Esses dias, brincando um pouco com Smalltalk, acabei achando um e-mail do Alan Kay sobre o que ele considera “programação orientada a objeto”, e o que isso difere do que conhecemos.

Primeiro ponto: na programação orientada a objetos que a maioria de nós conhecemos, a abstração é mais ou menos assim: um objeto é uma “coisa”, e essa coisa possui métodos. Na hora em que você roda o programa, a “classe” é definida, um ou mais objetos são instanciados, e a partir daí você pode chamar os métodos dos objetos.

Em Smalltalk, as coisas são um pouco diferentes
(more…)

A saga da busca em bancos de dados

Num mundo perfeito, todos os sistemas de armazenamento se conversariam, a nível do servidor e não do cliente, e jamais precisaríamos manualmente definir por “joins”, ou seja lá qual a forma que seu banco de dados faz.

Claro, o mundo não é perfeito.

Nesse caso, precisamos no mínimo padronizar uma forma de buscar dados. A maioria dos sistemas relacionais entende SQL, embora isso também não seja padronizado. Pior ainda, se for necessário buscar uma informação que está em uma tabela da base de dados X, e uní-la (join) com uma da base de dados Y, temos que fazer a busca manualmente.

Entra, aí, uma idéia.
(more…)

Curiosidades sobre Procs em Ruby

Esses dias, estava montando um código para Ruby usando Procs (blocos de código), salvando esses procs em variáveis e depois rodando-os sobre “bindings” diferentes. Talvez tenha ficado um pouco complicado de entender, mas na prática é algo mais ou menos assim:

class UmaClasse
  def self.callback_qualquer
    ...#alguns códigos aqui....
    @@bloco = proc do
      break if condicao_qualquer
      ...#códigos do meu callback
    end
    ...#mais algumas coisas
  end

  def salvar
    instance_eval(&@@bloco)
    puts "Rodei"
  end
end

Ou seja, eu posso criar um bloco definindo um callbackqualquer, e depois rodar esse bloco no contexto da “instância”, não da classe (o código que eu fiz, na verdade, é bem mais complexo). Mas, surpreeendentemente, esse código não funciona – ele lança um LocalJumpError se a condição do Proc for satisfeita. Por quê?

(more…)

Lazy Evaluation

Existe um conceito, muito utilizado por programadores de linguagens funcionais e pouco utilizado em outras linguagens, chamado Lazy Evaluation. Para não extender muito a definição, basta dizer que no caso do Lazy Evaluation, um resultado só é computado quando ele é necessário ao programa. Exemplos explicam melhor o conceito, então segue um:

100.times do |iterador| #Equivalente ao "for" de outras linguagens
  n = fatorial(iterador)  #Calcula o fatorial
  if(iterador.even?)       #Se for um número PAR
    print "Resultado da operação: #{n}" #Imprime o resultado do fatorial
  end
end

Lembrando que Ruby não trabalha com Lazy Evaluation, portanto o código acima não seria adequado. Mas, digamos que a linguagem acima suporte Lazy Evaluation: o resultado de n só seria calculado se o iterador for par. Ou seja, embora estejamos sempre definindo que n = fatorial(iterador), o programa não calcula o resultado do fatorial até que precisemos dele – neste caso, até que ele seja impresso na tela. Ou seja, em linguagens como Haskell, que suportam Lazy Evaluation por padrão, o código acima seria perfeitamente válido e não seria ineficiente. Normalmente, quando você usa Lazy Evaluation o código que só rodará depois é chamado de “promisse”, pois ele é uma promessa que o valor será calculado.

Mas porque isso é tão interessante?

(more…)

Paradigmas do MongoDB

Esses dias trabalhei firme no meu mapeador para MongoDB, o MongoParadigm. O código dele, como sempre, está disponível no GitHub. Atualmente estou me esforçando para integrar ele com Rails, e depois disso tudo pretendo finalmente implementar o “has :many” e o “belongs_to”. Pensei como seriam essas associações, e percebi que elas era a parte menos importante do MongoDB.

Isso porque eu acho que estou entendendo o que exatamente é uma base de dados orientada a “documentos”, finalmente – trabalhando na UFABC, é fácil de ver esse tipo de coisa: O registro de um aluno é um documento (no caso, de uma pessoa). O histórico do aluno é outro documento – e essa é a parte interessante, o histórico é um documento que pertence a um aluno, e não o contrário. Isso deve ficar bem documentado no MongoDB, porque apesar de não parecer, as bases de dados relacionais levam a gente a pensar de forma não-natural. Por exemplo, quando você vai armazenar um histórico de notas de um aluno em uma base relacional, normalmente você não armazena UM histórico, e sim um monte de registros que estão ligadas a um aluno por uma chave. Agora, é perfeitamente simples de entender porque o MongoDB não implementa trasações – afinal, no caso dele, se fosse necessária uma alteração se está mexendo em UM documento, e não em 20 registros, por exemplo.

(more…)