Lab4 Misael Alexandre

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

Introdução

O objetivo deste laboratório foi introduzir a linguagem orientada a objetos Ruby. O procedimento adotado para tal foi converter o código do segundo laboratório (feito em Java) para Ruby, a fim de que se pudesse comparar as vantagens e desvantagens do uso de Ruby (tipagem dinâmica) ao invés de Java (tipagem estática).

Desenvolvimento

Diferentemente do segunto laboratório, foram criados somente 3 arquivos: um de classes, um simulador e um de testes.

Arquivo classes.rb

Este arquivo foi responsável por armazenar os códigos das classes (transformadas de Java para Ruby) Aluno, AlunoITA, AlunoUSP, AlunoUnicamp, Comportamento, SafoPreguicoso, Burro, Pemba, Imprevisivel, Esforcado, Summa, RelaQueue, Professor e Relatorio.

O código de classes.rb pode ser visto abaixo:

class Aluno
 
  def initialize(name,queue)
    @nome=name
    @queue=queue
    @conhecimento=0
    @comportamento=Esforcado.new(self)
  end
 
  attr_accessor :conhecimento;
  attr_accessor :nome;
 
  def inteligencia
    return @comportamento.inteligencia
  end
 
  def dedicacao
    return @comportamento.dedicacao
  end
 
  attr_writer :comportamento
 
  def fazEEntregaRelatorio
    qualidade=(2 * dedicacao + 1 * inteligencia) / 3
    originalidade=(1 * dedicacao + 2 * inteligencia) / 3
    rela=Relatorio.new(qualidade, originalidade, self)
    @queue.queue(rela)
    @conhecimento=@conhecimento+1
  end
 
end
 
class AlunoITA < Aluno
 
  def initialize(nome, queue)
    super(nome, queue)
  end
 
  def comportamento=(comportamento)
    if(comportamento.class==Burro) 
      raise(Exception.new)
    end
    @comportamento=comportamento
  end
 
end
 
class AlunoUSP < Aluno
 
  def initialize(nome, queue)
    super(nome, queue)
  end
 
  def comportamento=(comportamento)
    if((comportamento.class==Summa)||(comportamento.class==SafoPreguicoso)) 
      raise(Exception.new)
    end
    @comportamento=comportamento
  end
 
end
 
class AlunoUnicamp < Aluno
 
  def initialize(nome, queue)
    super(nome, queue)
  end
 
  def comportamento=(comportamento)
    if((comportamento.class==Summa)||(comportamento.class==SafoPreguicoso)) 
      raise(Exception.new)
    end
    @comportamento=comportamento
  end
 
end
 
class Comportamento
 
  def initialize(aluno)
    @aluno=aluno
  end
 
end
 
class Esforcado < Comportamento
 
  def initialize(aluno)
    super(aluno)
    @inteligencia=0.5
    @dedicacao=1
  end
 
  attr_accessor :inteligencia
  attr_accessor :dedicacao
 
end
 
class Burro < Comportamento
  def initialize(aluno)
    super(aluno)
    @inteligencia=0
    @dedicacao=0
  end
 
  attr_accessor :inteligencia
  attr_accessor :dedicacao
end
 
class Imprevisivel < Comportamento
 
  def initialize(aluno)
    super(aluno)
  end
 
  def inteligencia
    return rand
  end
 
  def dedicacao
    return rand
  end
 
end
 
class Summa < Comportamento
  def initialize(aluno)
    super(aluno)
    @inteligencia=1
    @dedicacao=1
  end
 
  attr_accessor :inteligencia
  attr_accessor :dedicacao
end
 
class SafoPreguicoso < Comportamento
  def initialize(aluno)
    super(aluno)
    @inteligencia=1
  end
 
  attr_accessor :inteligencia
  def dedicacao
    return rand*0.5
  end
 
end
 
class Pemba < Comportamento
 
  def initialize(aluno)
    super(aluno)
  end
 
  def inteligencia
    return rand*0.5
  end
 
  def dedicacao
    return rand*0.5
  end
 
end
 
class RelaQueue
 
  def initialize
    @array = []
    @fim = 0
    @inicio = 0
  end
 
  def queue(elem)
    @array[@fim] = elem
    @fim = @fim+1
  end
 
  def dequeue
    @valor = @array[@inicio]
    if(@fim==@inicio)
      @valor = nil
    end
    @inicio = @inicio+1
    return @valor
  end
 
end
 
class Professor
 
  @queue=RelaQueue.new
 
  def initialize(queue)
    @queue=queue
  end
 
  def corrigirRelatorio(rela)
    nota=( rela.qualidade + rela.originalidade + rand )/3 * 10
    return nota
  end
 
  def corrigirRelatorios
    rela=@queue.dequeue
    while(rela.nil?)
      nota=corrigirRelatorio(rela)
      puts(rela.aluno.nome+": "+nota)
      rela=this.queue.dequeue
    end
  end
 
end
 
class Relatorio
 
  def initialize(qualidade, originalidade, aluno)
    @qualidade=qualidade
    @originalidade=originalidade
    @aluno=aluno
  end
 
  attr_accessor :qualidade
  attr_accessor :originalidade
  attr_accessor :aluno
 
end

Os principais mudanças na transformação do código das classes (de Java para Ruby) que compoem classes.rb foram:

  • Devido a tipagem dinâmica, não foi mais preciso inicializar os objetos necessários na classe. Eles podiam ser criados quando fosse preciso. Isto ajudou a diminuir o código.
  • O uso de attr_accessor para getters e setters mais simples também ajudou a diminuir o código.
  • O modo de lançar uma Exception. Em Java se "atirava" (throw) uma Exception. Em Ruby usou-se o método raise(Exception obj).
  • Comportamento não mais foi uma classe abstrata, e sim uma classe normal. Assim, não houve mais necessidade da especificacão dos métodos abstratos que deveriam ser sobrescritos nas classes que herdassem de Comportamento.
  • O uso do método rand (que por si só já retornava um float randomico entre 0 e 1) também ajudou a diminuir o código.][
  • **GRANDE MUDANÇA: **Devido a tipagem dinâmica, não foi mais preciso usar genericos para criar-se uma Queue genérica. A classe RelaQueue pode ser uma Queue não só de relatorios, mas de qualquer objeto! Além disso, a Queue não é mais limitada a 10 elementos, mas sim a uma quantidade indefinida (só depende da memória…).

Arquivo simulator.rb

Este arquivo correnspondeu somente a transformação do antigo Simulator.java para a linguagem Ruby.

O código de simulator.rb pode ser visto abaixo:

require "classes.rb"
 
class Simulator
  vetor_aluno=[]
  queue=RelaQueue.new
 
  puts "Entre com o numero de alunos:"
  numero=gets()
  numero=numero.to_i
 
  arr=(0..(numero-1)).to_a
 
  arr.each do |elem|
 
    puts "Entre com o nome do aluno #{elem+1}: "
    nome=gets()
 
    universidade=nil
    while((universidade!="ITA\n")&&(universidade!="USP\n")&&(universidade!="Unicamp\n"))
      puts "Entre com a universidade do aluno #{elem+1}: "
      universidade=gets()
    end
 
    if(universidade=="ITA\n")
      vetor_aluno[elem]=AlunoITA.new(nome,queue)
    elsif(universidade=="USP\n")
      vetor_aluno[elem]=AlunoUSP.new(nome,queue)
    elsif(universidade=="Unicamp\n")
      vetor_aluno[elem]=AlunoUnicamp.new(nome,queue)
    end
 
    comportamento=nil
    while((comportamento!="SafoPreguicoso\n")&&(comportamento!="Burro\n")&&(comportamento!="Pemba\n")&&(comportamento!="Imprevisivel\n")&&(comportamento!="Summa\n")&&(comportamento!="Esforcado\n"))
      puts "Entre com o comportamento do aluno #{elem+1}: "
      comportamento=gets()
    end
 
    if(comportamento=="SafoPreguicoso\n")
      comp=SafoPreguicoso.new(vetor_aluno[elem])
      begin
        vetor_aluno[elem].comportamento=(comp)
      rescue Exception => e
        puts "Voce tentou fazer algo impossivel"
      end
    elsif(comportamento=="Burro\n")
      comp=Burro.new(vetor_aluno[elem])
      begin
        vetor_aluno[elem].comportamento=(comp)
      rescue Exception => e
        puts "Voce tentou fazer algo impossivel"
      end
    elsif(comportamento=="Pemba\n")
      comp=Pemba.new(vetor_aluno[elem])
      begin
        vetor_aluno[elem].comportamento=(comp)
      rescue Exception => e
        puts "Voce tentou fazer algo impossivel"
      end
    elsif(comportamento=="Imprevisivel\n")
      comp=Imprevisivel.new(vetor_aluno[elem])
      begin
        vetor_aluno[elem].comportamento=(comp)
      rescue Exception => e
        puts "Voce tentou fazer algo impossivel"
      end
    elsif(comportamento=="Summa\n")
      comp=Summa.new(vetor_aluno[elem])
      begin
        vetor_aluno[elem].comportamento=(comp)
      rescue Exception => e
        puts "Voce tentou fazer algo impossivel"
      end
    elsif(comportamento=="Esforcado\n")
      comp=Esforcado.new(vetor_aluno[elem])
      begin
        vetor_aluno[elem].comportamento = comp
      rescue Exception => e
        puts "Voce tentou fazer algo impossivel"
      end
    end
 
  end
 
  arr.each do |elem|
    vetor_aluno[elem].fazEEntregaRelatorio;
  end
 
end

Os pontos que vale destacar na mudança são:

  • Vemos a utilidade de se colocar todas as classes em um único arquivo, já que para que se consiga "mexer" com as classes já criadas (como instanciá-las) é necessário fazer um require. Se todas as classes estivessem em arquivos diferentes, imagine…
  • Para se ler do teclado, usou-se o método gets(). Por sua simplicidade de uso, economizou muitas linhas de código.
  • O loop usado foi bem diferente do "usual" (o velho for usado em Java, C++, etc). A partir da variável numero, foi criado um array que variava entre 0 e numero-1. O loop foi somente uma iteração neste array.
  • Substituição de try-catch por begin-rescue

No restante, não houveram grandes mudanças, só pequenas adaptações.

Arquivo testes.rb

Este arquivo correnspondeu somente a transformação do antigo Teste.java para a linguagem Ruby.

O código de testes.rb pode ser visto abaixo:

require 'classes' #carregue o código da sua aplicação aqui
require 'test/unit'
 
class Teste < Test::Unit::TestCase
  def testFuncionaComoOLab1
    queue=RelaQueue.new
    prof=Professor.new(queue)
 
    aluno1=Aluno.new("John Smith", queue)
    aluno2=Aluno.new("Mike 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
 
    assert_equal(0.5, aluno1.inteligencia, 0.01)
    assert_equal(1, aluno1.dedicacao, 0.01)
 
    assert_equal(1.0, aluno3.inteligencia, 0.01)
    assert(aluno3.dedicacao != aluno3.dedicacao)
    assert(aluno3.dedicacao < 0.5)
 
    aluno1.fazEEntregaRelatorio
 
    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)
 
    aluno2.fazEEntregaRelatorio
    aluno3.fazEEntregaRelatorio
    aluno4.fazEEntregaRelatorio
 
    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)
 
    assert_equal(0.5, esforcado.inteligencia, 0.01)
    assert_equal(1, esforcado.dedicacao, 0.01)
 
    assert_equal(0.0, burro.inteligencia, 0.01)
    assert_equal(0.0, burro.dedicacao, 0.01)
 
    assert_equal(1.0, summa.inteligencia, 0.01)
    assert_equal(1.0, summa.dedicacao, 0.01)
 
    assert_equal(1.0, safo.inteligencia, 0.01)
    assert(safo.dedicacao != safo.dedicacao)
    assert(safo.dedicacao < 0.5)
 
    assert(imprevisivel.inteligencia != imprevisivel.inteligencia)
    assert(imprevisivel.inteligencia < 1.0)
    assert(imprevisivel.dedicacao != imprevisivel.dedicacao)
    assert(imprevisivel.dedicacao < 1.0)
 
    assert(pemba.inteligencia != pemba.inteligencia)
    assert(pemba.inteligencia < 0.5)
    assert(pemba.dedicacao != pemba.dedicacao)
    assert(pemba.dedicacao < 0.5)
  end
 
  def testAsSubClassesDeAlunoTemRestricoes
    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)
    rescue Exception => e
      puts "Iteano naum eh burro!"
    end  
 
    begin
      alunoUSP.comportamento = SafoPreguicoso.new(alunoUSP)
    rescue Exception => e
      puts "USPeano naum eh safopreguicoso!"
    end 
 
    begin
      alunoUnicamp.comportamento = Summa.new(alunoUnicamp)
    rescue Exception => e
      puts "Unicampeano naum eh summa!"
    end     
 
  end
 
  def testRelaQueueEhSubclasseDoGenericoQueue
 
  end
 
end

Para os testes, não houveram grandes mudanças. Houve somente pequenas adaptações. A única coisa que convém salientar foi que o teste testRelaQueueEhSubclasseDoGenericoQueue se tornou obsoleto, já que a Queue é totalmente genérica (aceita qualquer objeto).

Screenshots da execução de simulator.rb e testes.rb.

O resultado da excecução de simulator.rb pode ser visto na figura abaixo:

simulator.bmp

O resultado da excecução de testes.rb pode ser visto na figura abaixo:

testesssss.bmp

Como esperado, os resultados foram satisfatórios.

O código fonte do projeto do NetBeans criado foi:

Laboratório 4

Conclusão

Conclui-se que o objetivo do laboratório foi alcançado: houve um contato dos alunos com a linguagem Ruby. Comparando com o mesmo projeto feito em Java, a principal conclusão que se pode extrair é que foi bem mais fácil programar em Ruby do que em Java, ficando assim o código ficou bem menor. Esta foi a principal vantagem.
Para um projeto pequeno como este, Ruby se mostrou uma linguagem melhor. Entretanto, sendo necessário robustez e velocidade, creio que Java seria mais adequado, já que a forma interpretada de Ruby perde em velocidade de execução comparado a JVM de Java (a qual compila o código).

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