Ruby para desenvolvedores .NET–parte 2

Esta é uma série de artigos sobre Ruby para desenvolvedores .NET, confira os outros em:

Ruby para desenvolvedores .NET – parte 1

Ruby, é uma linguagem orientada a objetos. É  possível reconhecer, apenas com pequenas diferenças na sintaxe, algumas similaridades e diferenças de funcionamento, se comparado com o C#.

Podemos ver no código abaixo, a definição de uma classe(Usuario), a definição de um construtor (initialize), a definição de um método (autorizar_acesso) e a criação de 2 atributos, nome e email.

class Usuario
  attr_accessor :nome, :email

  def initialize(nome)
    @nome = nome
  end

  def autorizar_acesso
    false
  end
end

O que podemos ver de diferente aqui, é que quando chamamos o método attr_accessor para criar as propriedades nome e email, internamente o Ruby cria duas variáveis de instância chamadas @nome e @email e essas variáveis podem, obviamente, ser acessadas por qualquer método daquele objeto.’

A propósito, instanciar a class Usuario é tão simples quanto:

usuario = Usuario.new

Retorno de valores

Uma outra coisa importante de lembrar no Ruby, é que a última instrução de um método sempre é retornada. Portanto dentro do método autorizar_acesso, estamos retornando o valor false. Colocar false como última instrução (e nesse caso, a única) é o mesmo que dizer return false.

Por exemplo, os dois métodos abaixo fazem a mesma coisa:

def soma(x, y)
  # faz um monte de coisa desnecessaria aqui
  x + y
end

def soma(x, y)
  # faz um monte de coisa desnecessaria aqui
  resultado_soma = x + y
  return resultado_soma
end

Nos dois casos, x é somado a y e o resultado da soma é retornado.

Herança

Assim como em C#, Ruby também tem herança como podemos ver no exemplo abaixo:

class Usuario
  attr_accessor :nome, :email

  def initialize(nome)
    @nome = nome
  end

  def autorizar_acesso
    false
  end
end

class UsuarioEspecial < Usuario
  def autorizar_acesso
    true
  end
end

No código acima a classe UsuarioEspecial herda da classe Usuario e sobrescreve o método autorizar_acesso. Assim já podemos ver que é possível usar também o polimorfismo.

Métodos Estáticos

Ruby não tem métodos estáticos realmente, mas ele tem, o que é conhecido como métodos de classe e funcionam de forma similar aos métodos estáticos do C#. Para  usar métodos de classe basta que na declaração do método seja colocada a palavra chave self, como podemos ver:

class UsuarioEspecial < Usuario

  def self.salvar
    enviar_email("texto do email")
    #salvar os dados do usuario
  end

  def autorizar_acesso
    true
  end

private

  def enviar_email(txt)
    # envia email
  end
end

O método salvar pode ser chamado diretamente na classe UsuarioEspecial, não é necessário criar uma instância.

UsuarioEspecial.salvar

Ainda no código acima podemos ver que para declarar um método privado pasta adicionar a palavra chave private e qualquer método declarado abaixo dela será considerado privado.

Interfaces

Interfaces são um artifício  das linguagens estáticas para dizer ao compilador que uma classe tem um ou mais métodos.

No Ruby não existe um compilador e portanto não existe essa checagem prévia. Também existe a questão de que podemos alterar uma classe Ruby mesmo depois que ela já foi declarada, mas vamos falar disso depois. Portanto não existe a necessidade de interfaces.

Digamos que exista a seguinte situação feita em C#:

interface IControlePagamento
{
    void Pagar();
}

class Pagamento : IControlePagamento
{
    public void Pagar()
    {
        // logica de pagamento
    }
}

O que esse código bem simples faz, é dizer ao compilador que a classe Pagamento implementa os métodos da Interface IControlePagamento. Em Ruby a única coisa que temos que fazer é efetivamente implementar o método Pagar()

class ControlePagamento
  def pagar
  end
end

Isso tem vantagens e desvantagens.

A vantagem é que o código em Ruby é muito mais sucinto e objetivo, não é preciso escrever código para satisfazer o compilador. Existe apenas código para resolver o problema do negócio.

A desvantagem é que você não tem o aviso imediato do compilador caso o método não seja implementado.

Ainda assim, se você é adepto de técnicas como TDD, esse é um problema fácil de resolver, já que seus testes ficariam responsáveis por isso.

Outro recurso disponível no Ruby é que, toda classe automaticamente herda da classe Class, na classe Class existe um método chamado respond_to?. Esse método verifica se um objeto responde/contém a um determinado método.

respond_to_false

No exemplo acima a classe ControlePagamento foi definida sem o método pagar, veja que quando foi chamado o método respond_to? o retorno foi false.

Já abaixo o método foi definido e a resposta foi true.

respond_to_true

Enfim, existem opções para controlar isso e há gente que faça, mas vale dizer que pelo que tenho visto, o mais comum é simplesmente seguir uma convenção.

Conclusão

Nesse artigo já vimos mais algumas diferenças mais marcantes do Ruby, no próximo vou falar um pouco do Object Model do Ruby.

Duvidas, criticas ou sugestões? Deixe um comentário.

Ruby para desenvolvedores .NET–parte 1

Eu tenho usado Ruby já há algum tempo, principalmente em alguns desenvolvimentos pessoais usando o Rails. Mas eu trabalho com C# já há mais de 8 anos e vivi fechado nesse mundo .NET por muito tempo, muito mais do que eu gostaria. De qualquer forma, ruby já tem feito parte do meu dia a dia, então eu gostaria de compartilhar algumas coisas que já aprendi sobre ruby, para aqueles, que como eu, vivem no mundo .NET.

Motivação

Ruby é e deve ser considerada uma linguagem de primeira classe, é possível hoje realizar aplicativos de diversos fins com Ruby e não somente aplicações web usando Rails. Mas, muitas vezes as empresas preferem ficar com linguagens mais conhecidas no mercado como Java ou C# para suas aplicações.

Ok, se você não pode usar Ruby para construir suas aplicações é bem provável que possa usar Ruby como uma linguagem de scripting (que ela é), para ajudar em trabalhos marginais porém importantes que muitas vezes não são feitos, ou são feitos usando outras coisas como XML, como por exemplo realizar Builds e Deploys, fazer testes de aplicativos, entre outros.

Se você pode escolher qual a linguagem quer usar, melhor pra você, Ruby pode ser uma ótima escolha, como veremos.

Interpretador

A primeira coisa que precisamos para usar Ruby é um interpretador de Ruby. Existem vários interpretadores por ai, o que eu vou usar aqui é o IronRuby. O IronRuby é um interpretador do Ruby que permite usar Ruby sobre a plataforma .NET, ou seja, vai permitir que você use os assemblies que já está costumado. É Ruby, segue a especificação de Ruby, com o adicional do .NET. Ótimo não é?

Eu recomento instalar a versão 1.0 que é compatível com o Ruby 1.8.7, andei fazendo uns testes com a versão 1.1 do IronRuby e ainda dá vários paus (pelo menos na data atual). A vantagem dessa versão 1.1 é que ela já vem com ferramentas para o Visual Studio 2010.

O Console

Uma vez com o IronRuby instalado, você deve ter o IronRuby Console no seu menu iniciar, ou então pode executar o console a partir de um prompt padrão com o comando iirb.

O console permite que você execute qualquer instrução ruby, vá e faça um teste simples:

console

Uma outra vantagem do Ruby é a “falta de cerimônia” no código como os {}, ;, () e afins. Aliando isso ao fato de ser uma linguagem interpretada, veja a diferença de um Hello World feito em C# para uma aplicação console e uma em Ruby.

using System;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(string.Format("Hello World, {0}", args[0]));
        }
    }
}

E agora em Ruby:

puts "Hello World, #{ARGV[0]}"

Considere, que além da diferença da linguagem, para rodar o aplicativo no .NET é preciso compilar, gerar um executável e então rodá-lo. E para rodar o script Ruby, considerando que ele foi salvo num arquivo chamado hello_world.rb basta executar o comando:

comando_ruby

Fortemente, Estaticamente e Dinamicamente tipado

Falando da linguagem realmente, Ruby é uma linguagem fortemente e dinamicamente tipada. O que isso quer dizer?

Quer dizer as variáveis tem um tipo bem definido, por exemplo uma variável do tipo String não pode ser somada a uma variável do tipo Fixnum veja:

tipos

Veja que apenas por atribuir um valor às variáveis os tipos foram definidos como Fixnum e String, isso é definir uma tipagem dinamicamente, ou seja, no seu primeiro uso. Nos casos acima as variáveis texto e numero são instâncias das classes String e Fixnum respectivamente e por isso tem acessos aos seus métodos, então se você quiser concatenar as duas variáveis em uma string pode fazer o seguinte:

concat

Veja que chamei o método to_s que converte para string e então foi gerado o texto “VinTem12”

Linguagens, estaticamente tipadas, como o C#, tem seu tipo definido em tempo de compilação, ou seja, antes da execução.

Usando o .NET

Como um exemplo simples de como é possível usar as classes do .NET a partir do IronRuby, vou mostrar um código básico de um MessageBox do Windows Forms.

clr

O princípio é o mesmo para qualquer classe do .NET Framework. Alegre

Concluindo

Essa foi apenas uma apresentação inicial de como instalar um ambiente Ruby no Windows, do console do Ruby e da diferença mais básica entre Ruby e C# que é a tipagem.

Nos próximos vou falar um pouco mais a fundo das características do Ruby e quais as diferenças para o C#.