Efeitos Colaterais e Códigos

Esse assunto é bem complexo, e envolve certas situações interessantes. Mas antes, precisamos de uma definição do que é um efeito colateral em código: quando se escreve um código em uma linguagem, cada procedimento/função/método deveria fazer uma, e apenas uma tarefa. Mais do que isso, e estamos inserindo um efeito colateral no código. Quando programamos em linguagens puramente funcionais, como por exemplo Haskell, fica evidente que estamos mexendo com uma função com efeitos colaterais porque ela fica, de certa forma, “marcada”.

Ok, e em Ruby, por exemplo? Como saber? A idéia é simples (e talvez isso possa até ser uma definição formal): “Uma função não tem efeitos colaterais quando não importa quantas vezes ela é chamada, ela sempre traz os mesmos resultados”. Embora simples, na teoria, identificar uma função assim nem sempre é fácil. Por exemplo, imaginemos um caso bem interessante: a função “save” do ActiveRecord. Ela parece, em teoria, não ter efeitos colaterais, mas ela possui um: vamos para um código na prática:

class Person < ActiveRecord::Base
  validates_uniqueness_of :name
end

me = Person.new :name => "Maurício"
myself = Person.new :name => "Maurício"
me.save #true.
me.save #false. FALSE?

Tecnicamente falando, as duas funções deveriam retornar true: eu passei dois objetos exatamente iguais para elas. O segredo, se é que há algum, é que o método “save” na verdade faz duas coisas: valida os objetos e salva-os no banco. O principal problema é o “salvar no banco”, na verdade: estamos definindo um estado “global”, digamos assim. Todos os nossos novos objetos “Person” vão, automaticamente, ter que consultar o banco (nosso “estado global”) e verificar se a propriedade “name” já existe. Como se, por causa desse “estado” todos os saves automaticamente ganham um “if” a mais. Outra coisa também que o “save” faz que indica um efeito colateral é mudar o “id” do objeto:

me = Person.new :name => "Maurício"
p me.id #retorna nil
me.save
p me.id #retorna um número qualquer

(more…)

O Método “Extend” e Seus Usos

Provavelmente muita gente conhece o método “extend”, usado principalmente em classes para adicionar métodos, tais como:

module Nameable
  def set_name(name)
    @name = name
  end
end

class MyClass
  extend Nameable
  set_name "Foo Bar"
end

Claro que há pessoas que fazem verdadeiras aberrações, tipo um “module” que define o callback “included” que chama um “extend”, tipo essa situação:

module Nameable
  def self.included(klass)
    klass.extend Nameable::ClassMethods
  end

  module ClassMethods
    def set_name(name)
      @name = name
    end
  end
end

class MyClass
  include Nameable
  set_name "Foo Bar"
end

Mas vamos ignorar esse tipo de coisa e pensar em outras formas de usar o “extend”. Digamos que temos uma classe como a seguir:

class Authenticator
  def login(username, password)
    if User.find_by_username_and_password(username, password)
      return true
    else
      return false
    end
  end

Ok, temos uma regra para autenticar (aviso: não use isso em produção, o código prevê que os usuários tem suas senhas gravadas no banco sem criptografia nenhuma). Digamos, agora, que em um determinado cliente, esse código só não é o suficiente: o cliente quer que, antes de autenticar no banco, se autentique no sistema

Uma solução é usar monkey-patch. Nesse caso, teríamos um código em outro lugar que redefiniria a classe e adicionaria novos métodos, tipo:
(more…)

Métodos privados semelhantes a Java/C++ em Ruby

Fazia um tempo que eu não postava uma das bizarrices em Ruby, então vamos lá: esses dias, no grupo de usuários de Ruby, surgiu uma discussão muito boa sobre métodos privados e alto acoplamento. A idéia é mais ou menos assim: em Java (ou C++), ao definir um método público que chama um método privado, se você reimplementar aquele método privado, os métodos públicos herdados não são afetados. Um exemplo vale mais que mil palavras, então:

#include <stdio.h>

class Example {
    public:
    void imprimir() {
        hello();
    }

    private:
    void hello() {
        printf("Hello, world!\n");
    }
};

class Ex2: public Example {
    private:
    void hello() {
        printf("Hello, from Ex2\n");
    }
};

int main(void) {
    Ex2 e;
    e.imprimir(); //Essa linha imprime "Hello, world!"
}

Já no código Ruby equivalente:

class Example 
  def imprimir()
    hello
  end

  private
  def hello
    puts "Hello, world!"
  end
end

class Ex2 < Example 
  private
  def hello
    puts "Hello, from Ex2"
  end
end

Ex2.new.imprimir #Imprime "Hello, from Ex2"

Ou seja, reimplementar métodos privados numa subclasse pode quebrar métodos da superclasse. Embora eu considere isso uma peculiaridade da linguagem e não como um problema de acoplamento, implementação falha, ou qualquer coisa (e até, mais pra frente, pretendo escrever um post sobre o assunto de diferenças entre linguagens de programação além da sintaxe), a discussão inteira me deu uma idéia: como implementar esse comportamento em Ruby?
(more…)

Closures, Functions e Programação Funcional em Javascript

Estes dias, tive que fazer um código que achei que seria muito complicado, e que deveria rodar num browser. A idéia é que, dependendo do que foi digitado em uma determinada caixa de texto, um pedaço de uma página deveria mudar. Até aí, tudo bem, o problema é que o pedaço que deveria mudar deveria agrupar informações de outras caixas de texto, e outras regras confusas. Achei uma solução muito simples e prática, e gostaria de dividí-la. Mas antes, vamos simplificar o escopo:

Imagine que há uma página, no qual há um botão “adicionar”. Ao clicar nele, ele adiciona um “select” (sexo) e uma caixa de texto com observações ou qualquer outra coisa. Podem ser adicionados tantos elementos como se achar necessário. Para cada elemento alterado, deve ser exibido um sumário na tela de baixo (observações), digamos, concatenando o sexo e as observações. A parte difícil é: quando qualquer elemento for mudado, APENAS o sumário relativo àquele conjunto de elementos (sexo e observação) deve ser alterado, e também, quando eu estiver editando as observações (ou o sexo), o sumário deve ficar em negrito. Para simplificar (e rodar em vários browser) usarei a biblioteca Javascript chamada Prototype (não usarei o JQuery porque seria jogar uma bomba numa mosca), e a idéia é escrever apenas o código relativo às edições (porque é isso que pega). Portanto, para quem quiser, basta pegar o gist do Github http://gist.github.com/658668 para ter um esqueleto do programa (basta abrir o .html em qualquer browser).
(more…)

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

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

Programação Procedural em Java

Ok, o título parece estranho, mas é algo que me preocupa: Afinal, POR QUE as pessoas confundem tanto desenvolvimento orientado a objeto com procedural? Recentemente eu fiz uma integração do Jasper com Ruby (projeto Jasper on Rails, no meu github) e me vi tendo que usar a API do Jasper. É mais ou menos assim (em JRuby):

  modelo = "#{DIR}/arquivo.jasper"
  dados = File.read("#{DIR}/dados.xml")
  str_reader = java.io.StringReader.new(dados)
  input_source = org.xml.sax.InputSource.new(str_reader)
  documento = JRXmlUtils.parse(input_source)

  params = {
    JRXPathQueryExecuterFactory::PARAMETER_XML_DATA_DOCUMENT => documento
  }
  fill = JasperFillManager.fill_report(modelo, params)
  pdf = JasperExportManager.export_report_to_pdf(fill)
  return String.from_java_bytes(pdf)

(more…)