Lab4 Anderson Aiziro

aluno: Nome do Aluno
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 08/11/2008 (6)

Introdução

O objetivo deste laboratório foi a aplicação da linguagem Ruby. Utilizando o código desenvolvido para o lab2, realizamos as alterações para aplicar a linguagem Ruby. Com isto, foi possível perceber como se relacionam Java e Ruby, quais suas diferenças em diversos casos e suas semelhanças.

Desenvolvimento

O código foi separado em 3 classes. A classe simulador, a classe classes e a classe de teste.

A classe classes contém todas as classes desenvolvidas para o funcionamento da aplicação: Aluno, AlunoITA, AlunoUSP, AlunoUnicamp, Professor, RelaQueue, Relatorio e os comportamentos SafoPreguicoso, Esforcado, Summa, Pemba, Burro. Ao contrário da aplicação em Java, em ruby, podemos colocar várias classes em um mesmo aquivo de classe. E para relacionar dois arquivos, basta colocarmos o comando "require 'classe_necessaria' " no início da classe Ruby que utilizará a classe_necessária. Em Java, arquivos do mesmo pacote já estão relacionados.

O código da classe classes é:

Alunos:

class Aluno 
    attr_accessor :comportamento
    attr_reader :conhecimento, :nome
 
    def initialize(nome,queue) 
        @nome=nome
        @queue=queue
        @comportamento= Esforcado.new(self)
        @conhecimento = 0
    end
 
    def fazeentregarelatorio
        rela = Relatorio.new(self.qualidade ,self.originalidade,self)
        @queue.queue(rela)
        @conhecimento+=1
    end
 
    def qualidade
        @qualidade=(2*@comportamento.dedicacao+ @comportamento.inteligencia )/3
    end
 
    def originalidade
        @originalidade= (@comportamento.dedicacao+ 2*@comportamento.inteligencia)/3
    end
 
    def inteligencia 
      @comportamento.inteligencia
    end
 
    def dedicacao 
      @comportamento.dedicacao
    end
 
end
 
class AlunoITA < Aluno
 
    def initialize(nome,queue)
        super(nome,queue)
    end
 
    def comportamento= (comportamento) 
        raise "Iteanos nao sao burros!" if comportamento.class == Burro
        super
 
    end
 
end
 
class AlunoUSP < Aluno
 
  def initialize(nome,queue)
        super(nome,queue)
  end
 
  def comportamento= (comportamento)
    raise "Alunos da USP não são Summa." if comportamento.class == Summa
    raise "Alunos da USP não são Safos Preguiçosos." if comportamento.class ==SafoPreguicoso
    super
  end
 
end
 
class AlunoUnicamp < Aluno
 
    def initialize(nome,queue)
        super(nome,queue)
    end
 
    def comportamento= (comportamento)
        raise "Alunos da UNICAMP não são Summa." if comportamento.class == Summa
        raise "Alunos da UNICAMP não são Safos Preguiçosos." if comportamento.class == SafoPreguicoso
        super
    end
 
end

Comportamentos:

class Esforcado 
    attr_reader :inteligencia , :dedicacao
 
    def initialize(aluno)
        @inteligencia=0.5
        @dedicacao=1
        @aluno=aluno
    end
 
end
 
class Burro
   attr_reader :inteligencia, :dedicacao
 
    def initialize(aluno)
        @inteligencia = 0
        @dedicacao = 0
        @aluno = aluno
    end
 
end    
 
class Imprevisivel 
 
    def initialize(aluno)
        @aluno = aluno
 
    end
    def inteligencia
      return random0a1
    end
 
    def dedicacao
      return random0a1
    end
 
    def random0a1
        rand
    end
end
 
class Pemba
 
    def initialize(aluno)
        @aluno = aluno
        @inteligencia = self.random0ameio
    end
 
    def inteligencia
      return random0ameio
    end
 
    def dedicacao
      return random0ameio
    end
 
    def random0ameio
        rand*0.5
    end
 
end
 
class SafoPreguicoso
    attr_reader :inteligencia
 
    def initialize(aluno)
        @aluno = aluno
        @inteligencia = 1
    end
 
    def dedicacao
      return random0ameio
    end
 
    def random0ameio
        rand*0.5
    end
 
end
 
class Summa
    attr_reader :inteligencia, :dedicacao
 
    def initialize(aluno)
        @aluno = aluno
        @inteligencia = 1
        @dedicacao = 1
    end
 
end

Rela:

class Relatorio 
    attr_reader :aluno, :originalidade, :qualidade
 
    def initialize(qualidade,originalidade,aluno)
        @originalidade=originalidade;
        @qualidade=qualidade;
        @aluno=aluno;
    end
 
end
 
class RelaQueue
 
    def initialize
      @array =[] 
      @inicio = 0
      @fim = 0
    end
    def queue(rela) 
        @array[@fim] = rela
        @fim = (@fim + 1) % 10;
    end
    def dequeue
      @valor = @array[@inicio]
 
      if(@inicio==@fim)
          valor=nil
      end
 
      @inicio = (@inicio + 1) % 10
      @valor
 
    end
 
end

Professor:

class Professor 
    def initialize(queue)
        @queue=queue;
    end
 
    def corrigirrelatorios
        while(true)
            rela=@queue.dequeue
            if(rela==nil) 
              break
            end
            puts("#{rela.aluno.nome.to_s}"+ ": ");
            puts("#{corrigirrelatorio(rela)}");
 
        end
    end
 
    private
 
    def corrigirrelatorio(rela)
      nota = (rela.qualidade + rela.originalidade + fatoraleatoriode0a1)/3 
      nota *=10
      return nota
    end
 
    def fatoraleatoriode0a1
        rand
    end
end

A classe simulador é equivalente à classe simulador desenvolvida em Java, sendo utilizada para a interação entre a aplicação e o usuário. Aqui, uma diferença é que em Java, temos a classe Simulador com o método main dentro dela para a execução do arquivo. Em ruby, não precisamos declarar nenhuma classe ou método. Apenas desenvolvemos a forma como o usuário deve interagir com a aplicação.

A implementação da classe simulador segue abaixo:

require 'classes' 
 
  puts("Deseja adicionar um aluno (s/n): ")
  string = gets()
  while(string!="n")
 
    queue = RelaQueue.new
    professor = Professor.new(queue)
 
    puts "Digite o nome do aluno - "
    nome = gets().strip
    puts "Escolha a faculdade do aluno: (ITA, USP, UNICAMP) - "
    facul = gets().strip
 
    if(facul=="ITA")
      alunos=AlunoITA.new(nome,queue)
 
    elsif(facul=="USP")
      alunos=AlunoUSP.new(nome,queue)
    else
      alunos=AlunoUnicamp.new(nome,queue)
    end
    puts alunos.class
    puts"Escolha o tipo do aluno: (summa, safo, esforcado, pemba, imprevisivel, burro) - "
    tipo = gets().strip
 
    if(tipo=="summa")
      alunos.comportamento = Summa.new(alunos)
 
    elsif(tipo=="safo")
      alunos.comportamento = SafoPreguicoso.new(alunos)
 
    elsif(tipo=="esforcado")
      alunos.comportamento = Esforcado.new(alunos)
 
    elsif(tipo=="pemba")
      alunos.comportamento = Pemba.new(alunos)
 
    elsif(tipo=="imprevisivel")
      alunos.comportamento = Imprevisivel.new(alunos)
    else
      alunos.comportamento = Burro.new(alunos)
    end
    puts alunos.comportamento.class
    alunos.fazeentregarelatorio
    professor.corrigirrelatorios
    puts "Deseja adicionar outro aluno (s/n): "    
    string=gets().strip
  end

Com a classe de simulação acima, obtivemos os seguintes resultados:
simulacao.JPG

simulacao2.JPG

A classe de testes é a mesma que a desenvolvida em Java, apenas alterando a sintaxe de seus comandos para que a aplicação rodasse em Ruby. A classe de testes portada para Ruby é:

require 'classes'
require 'test/unit'
 
class TestInteressante < Test::Unit::TestCase
  def test_meu_teste
    queue = RelaQueue.new
    aluno = AlunoITA.new("John Smith", queue)
    aluno.comportamento = SafoPreguicoso.new(aluno)
    assert_equal(1.0, aluno.inteligencia(), 0.01)
    assert(aluno.dedicacao() < 0.5)
    assert_raise(RuntimeError) { aluno.comportamento = Burro.new(aluno) } 
  end
end
 
class Teste < Test::Unit::TestCase
  def test_funciona_como_o_lab1
    queue = RelaQueue.new
    prof = Professor.new(queue)
 
    aluno1 = Aluno.new("John Smith", queue)
    aluno2 = Aluno.new("Mark Smith", queue)
    aluno3 = Aluno.new("Joseph Smith", queue)
    aluno4 = Aluno.new("Robert Smith", queue)
 
    begin
      aluno3.comportamento = (SafoPreguicoso.new(aluno3))
      aluno4.comportamento = (SafoPreguicoso.new(aluno4))
    rescue Exception=> e
      puts "Não deveria lançar erro!"
    end
 
    #teste de aluno_esforçado
    assert_equal(0.5, aluno1.inteligencia , 0.01)
    assert_equal(1, aluno1.dedicacao, 0.01)
 
    #teste de aluno_safo
    assert_equal(1.0, aluno3.inteligencia, 0.01)
    assert(aluno3.dedicacao != aluno3.dedicacao)
    assert(aluno3.dedicacao < 0.5)
 
    #alunos começam a fazer os relas
    aluno1.fazeentregarelatorio
 
    #roubamos o relatório do primeiro aluno para investigá-lo
    rela1 = queue.dequeue
    assert_equal(aluno1, rela1.aluno)
    assert(rela1.aluno.nome == "John Smith")
    assert(rela1.qualidade < 0.9)
    assert(rela1.qualidade > 0.8)
    assert(rela1.originalidade < 0.7)
    assert(rela1.originalidade > 0.6)
 
    #os outros continuam a fazer os relas
    aluno2.fazeentregarelatorio
    aluno3.fazeentregarelatorio
    aluno4.fazeentregarelatorio
 
    #deve exibir a correção dos relas dos alunos aluno2, aluno3 e aluno4, nesta ordem
    #pois "roubamos" o relatório do aluno1
    prof.corrigirrelatorios
  end
 
  def testoscomportamentosfuncionamcomoespecificado
    queue = RelaQueue.new
    aluno1 = Aluno.new("John", queue)
    summa = Summa.new(aluno1)
    pemba = Pemba.new(aluno1)
    imprevisivel = Imprevisivel.new(aluno1)
    safo = SafoPreguicoso.new(aluno1)
    esforcado = Esforcado.new(aluno1)
    burro = Burro.new(aluno1)
 
    #teste de esforçado
    assert_equal(0.5, esforcado.inteligencia, 0.01)
    assert_equal(1, esforcado.dedicacao, 0.01)
 
    #teste de burro
    assert_equal(0.0, burro.inteligencia, 0.01)
    assert_equal(0.0, burro.dedicacao, 0.01)
 
    #teste de summa
    assert_equal(1.0, summa.inteligencia, 0.01)
    assert_equal(1.0, summa.dedicacao, 0.01)
 
    #teste de safo
    assert_equal(1.0, safo.inteligencia, 0.01)
    assert(safo.dedicacao != safo.dedicacao)
    assert(safo.dedicacao() < 0.5)
 
    #teste de imprevisivel
    assert(imprevisivel.inteligencia != imprevisivel.inteligencia)
    assert(imprevisivel.inteligencia < 1.0)
    assert(imprevisivel.dedicacao != imprevisivel.dedicacao);
    assert(imprevisivel.dedicacao() < 1.0)
 
    #teste de pemba
    assert(pemba.inteligencia != pemba.inteligencia)
    assert(pemba.inteligencia < 0.5)
    assert(pemba.dedicacao != pemba.dedicacao) 
    assert(pemba.dedicacao < 0.5)
  end
 
  def test_as_subclasses_de_aluno_tem_restricoes
    queue = RelaQueue.new
    alunoita = AlunoITA.new("John Smith", queue)
    alunousp = AlunoUSP.new("Mark Smith", queue)
    alunounicamp = AlunoUnicamp.new("Joseph Smith", queue)
 
    begin
      alunoita.comportamento = SafoPreguicoso.new(alunoita)
      alunoita.comportamento = Summa.new(alunoita)
      alunousp.comportamento = Burro.new(alunousp)
      alunounicamp.comportamento = Burro.new(alunounicamp)
    rescue Exception => e
      puts "Não deveria lançar erro!"
    end
 
    begin
      alunoita.comportamento = Burro.new(alunoita)
      puts "Deveria lançar erro!"
    rescue Exception => e    
    end
 
    begin
      alunousp.comportamento = SafoPreguicoso.new(alunousp)
      puts "Deveria lançar erro!"
    rescue Exception => e    
    end
 
    begin
      alunounicamp.comportamento = Summa.new(alunounicamp)
      puts "Deveria lançar erro!"
    rescue Exception => e    
    end
  end
end

Com a classe de testes acima, obtivemos os seguintes resultados:

teste.JPG

Conclusão

Utilizando como base um projeto em Java, foi possível perceber as diferenças entre Java e Ruby em cada parte do projeto. Por exemplo, em Java utilizamos uma classe abstrata Comportamento e subclasses que definiam cada tipo de comportamento. Em Ruby não é necessário o desenvolvimento da classe Comportamento. Contudo, poderíamos desenvolver a classe Comportamento, do mesmo modo como feito no lab2. Teríamos uma classe Comportamento e os métodos seriam sobrescritos em suas subclasses, que extenderiam a classe comportamento (ex: class Burro < Comportamento).
Além disso, foi possível perceber que a linguagem Ruby simplifica muito o código, ou seja, a quantidade de linhas necessárias para realizar a mesma operação é muito menor em diversas situações, sem prejudicar a legibilidade do código.
Outra diferença é que em Ruby, pelo fato de termos uma tipagem dinâmica, temos uma liberdade maior para implementação. Alem de ser possível testar todas as idéias antes de realmente implementar-las no projeto. Utilizando o irb, podemos criar a classe ou o método que estamos pensando e podemos ver se funciona antes de colocar-las no projeto. Isto facilita e otimiza muito o desenvolvimento do projeto, pois reduz a quantidade de erros.
A principal dificuldade encontrada foi que, por estarmos desenvolvendo a primeira aplicação em Ruby, cometemos muitos erros pequenos e simples de se corrigir, mas que pela falta de prática com a linguagem, tornam-se motivos para ficarmos travados no mesmo lugar por muito tempo.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License