O que é Eingenclass, afinal?

Bom, eu acredito que algumas pessoas que começaram com a linguagem Ruby possam ter essa pergunta. O que, exatamente, são Eingenclass (ou, na nomenclatura mais comum, Singleton Classes)? O que, exatamente, retorna o método “metaclass”, do ActiveSupport? Bom, em primeiro lugar, é bom entender algumas coisas: o código a seguir:

class Exemplo
end

e1 = Exemplo.new
e2 = Exemplo.new
def e1.imprimir
  puts "Algo"
end

e1.imprimir #Imprime Algo
e2.imprimir #NoMethodError

Por que a primeira instância ganhou um método chamado “imprimir”, e a outra não? Para onde foi a definição deste método? Para dar a resposta, é necessário primeiro entender alguns conceitos importantes. Em primeiro lugar, sempre que um método é definido, ele é definido em uma classe, e a partir deste momento ele está disponível para ser chamado por uma instância. Este é um conceito interessante: embora, quando façamos códigos como:

class Exemplo2
  def self.somar(a, b)
    a + b
  end

def um_metodo
    "um método"
  end
end

a tendência é chamar o método “somar” de “class method” ou “metodo da classe”, na verdade não é isso que acontece. Este método, na verdade, não foi definido na classe Exemplo2, e sim em outra classe da qual a classe Exemplo2 é apenas uma instância. Para os que conhecem melhor a estrutura de classes do Ruby, sabe que toda classe é uma instância da classe Class, e sabe também que definir um método como o “somar”, acima, não automaticamente adiciona esse método a todas as outras classes. É aí que entram as Eigenclasses
(more…)

Dá para criar classes abstratas em Ruby?

Ok, aqui vamos nós para mais estudos de como fazer coisas bizarras em Ruby… outro dia, estava olhando para um livro, “Design Patterns in Ruby”, que falava de classes abstratas (tipo Java) e a inexistência delas em Ruby, aonde “Duck Typing” resolve. Mas aí pensei: será que não dá para simular o comportamento de classes abstratas tipo Java, em Ruby?

Para os que não conhecem Java: se você, em Java, declarar uma classe como abstrata, e definir, digamos, dois métodos abstratos, quando esta classe for herdada, você é obrigado a definir estes dois métodos, senão o código sequer compila. Bom, parece então simples, em Ruby: basta criar uma classe, informar, de alguma que ela é abstrata, e então quando ela for herdada, se a classe herdada não definir todos os métodos, lançar uma exceção (digamos, um NoMethodError). Ok, Ruby permite traçar quando uma classe foi herdada com o método “callback” inherited, portanto é relativamente simples saber se a classe foi herdada e se ela implementa os métodos da abstrata, certo?

Bom, na prática… não.
(more…)

O Usuário SEMPRE Sabe o que Quer

Não, não é uma pergunta. O título deste post, embora pareça contraditório com o que a maioria das pessoas desenvolvedoras de sistema dizem, quer dizer exatamente o que ele quer dizer. Depois de muito tempo trabalhando com desenvolvimento de sistemas, e um ano trabalhando direto com métodos ágeis (no qual um usuário é livre para fazer mudanças) a frase que mais me perturba é quando alguém diz: “o usuário nunca sabe o que quer”, seguida de perto pelas “o usuário é folgado” ou “o usuário não usa o sistema que desenvolvemos pra ele”.

Primeiro ponto a ser feito, é que ninguém se pergunta “POR QUE o usuário não usa o sistema”, ou “POR QUE ele é folgado”. O que faria uma pessoa usar uma planilha de excel, com todas as dificuldades e inseguranças que ela oferece, ao invés de um sistema? Preguiça de clicar em trocentos botões? O sistema é lento? O sistema é “muito chato”, tipo, milhares de validações, etc? Tudo isso, é o usuário lhe dizendo que o sistema não é do jeito que ele quer – e se o sistema foi desenvolvido PARA ele, por que um programador culpa o usuário, se a falha foi de si mesmo ao ter desenvolvido algo que o usuário não queria?
(more…)

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…)

Ensaio Sobre a Violência

Este será um post totalmente off-topic*, mas tudo bem.

Quando eu era mais novo, lá para a minha pré-adolescencia, lembro de ter assistido ao filme “Ghost – do outro lado da vida”. Muitos já devem tê-lo assistido também. Lembro que na época, meu pai estava começando a seguir o espiritismo, e não lembro mas acho que foi por este exato motivo que estávamos assistindo ao filme. Lembro também de ter comentado que os vilões meio que se matavam sozinhos, e meu pai concordou comigo, mas por algum motivo aquilo não me pareceu certo… parecia que tinha algo muito errado com o filme, com a forma como o personagem principal enfrentava os vilões, mas antes de explicar direito o que eu pensei, vamos para outro filme: “Jogos mortais”. Numa primeira comparação, parece que o vilão de Jogos mortais é bem mais cruel e perverso do que o mocinho de Ghost, porém fazendo uma comparação mais completa, isso não é verdade.

Vendo pelo seguinte lado: em Ghost, o personagem principal morre, e como fantasma caça seus assassinos. Quando os encontra, os assombra até que eles, assustados como nunca, acabam se matando “sozinhos”. Soa familiar? O estranho é que, para a maioria das pessoas, Sam (de Ghost) não é um “vilão” como o de Jogos mortais, por exemplo, embora a atitude de ambos os personagens é exatamente a mesma. Talvez possam vir papos do tipo “mas os personagens que Sam mata são assassinos, e ele faz isso sem intenção, blá blá”, mas a verdade é que isso não importa a mínima – a reação que parecemos ter quando uma pessoa é morta difere demasiadamente dependendo se a pessoa era “boa” ou “má”.
(more…)

Ascenção e Queda de Scrum

Bom, para os que não sabem ainda, eu trabalho como Analista de TI na Universidade Federal do ABC. Ano passado (2009), tive a difícil missão de criar uma divisão de desenvolvimento de sistemas, de forma que ela atendesse um monte de demandas. Além disso, o TI já tinha 3 anos de existência e nunca tinha-se sequer rascunhado uma divisão de desenvolvimento, porque as primeiras chefias do Núcleo de TI tinham a idéia de que não haveria desenvolvimento de software dentro da UFABC. Enfim, problemas à parte…

Estudos foram feitos. Já havia uma série de scripts escritos todos em Ruby para facilitar um número de tarefas, e também já existiam dois projetos de Rails publicados, então parecia no mínimo estranho usar uma linguagem ágil, com um framework ágil (que inclusive possui geradores de código) e adotar uma metodologia tradicional. Artigos também com o do professor Xexéo, da UFRJ, auxiliaram a mostrar que existe uma frente acadêmica que abraça mudanças (já escrevi em posts anteriores que o Brasil é um país que valoriza mais do que deveria os diplomas e títulos). Anyway, aos fatos:

(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…)