Lab4 Marcus Edson

aluno: Marcus Edson Barreto Brito
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 06/08/2008 (2)

Introdução

Neste laboratório tivemos um primeiro contato com a linguagem Ruby ao passarmos para essa linguagem o 2o. laboratório, que havia sido feito em JAVA. Com isso pudemos perceber algumas semelhanças e diferenças entre as duas linguagens, que são ambas orientadas a objeto.

Desenvolvimento

Os códigos das classes(professor, aluno, relaQueue, etc), do Simulador e de teste são mostradas abaixo.
Fizemos algumas modificações em relação às classes já feitas em JAVA para que elas se adequassem ao Ruby.
As principais modificações são comentadas abaixo.

Classes Principais

Foram criadas várias classes distintas para os diferentes tipos de comportamento. Diferente do que fizemos em JAVA, em que tínhamos uma classe abstrata "Comportamento" e os vários tipos de comportamento eram subclasses dela. E a classe aluno tinha uma variável comportamento, que podia ser modificada para qualquer uma das subclasses de "Comportamento". Já em Ruby, na classe "Aluno" temos uma variável "comportamento" que pode ser modificada para qualquer uma das classes criadas, já que as variáveis em Ruby não têm um tipo definido.
Outra modificação importante foi na classe RelaQueue. Os métodos "queue" e "dequeue" foram bastante simplificados (e veja que usamos "array" da mesma forma que em JAVA) e não foi necessário a criação de um array de genéricos, visto que em Ruby, em um array podemos colocar variáveis de qualquer tipo.
As classes AlunoUSP, AlunoITA e AlunoUnicamp são subclasses de aluno, da mesma forma que em JAVA, e implementam as mesmas exceções. Só foi necessário modificar a forma como é lançada a exceção,através do comando "raise".
Outra modificação importante está nos métodos "getters" e "setters". Seu uso é bem facilitado em Ruby, bastando utilizar attr_reader/attr_writer: e as variáveis que se deseja ler/escrever.

class Aluno 
  attr_reader :nome, :conhecimento, :comportamento 
  attr_writer :comportamento
 
  def initialize(nome, queue)  
    @nome=nome
    @queue=queue
    @conhecimento=0
    @comportamento=Esforcado.new(self)    
  end
 
  def faz_e_entrega_relatorio
        qualidade = (2 * @comportamento.dedicacao + @comportamento.inteligencia ) / 3
        originalidade = (@comportamento.dedicacao + 2 * @comportamento.inteligencia ) / 3
        rela = Relatorio.new(qualidade, originalidade, self)
        @queue.queue(rela)
        @conhecimento+=1
  end
 
  def inteligencia
      @comportamento.inteligencia
  end
 
  def dedicacao
      @comportamento.dedicacao    
  end
 
end
 
class AlunoUSP < Aluno
  def initialize(nome, queue)
    super(nome, queue)
  end
 
  def comportamento=(comp)
    if(comp.is_a?(Summa) || comp.is_a?(SafoPreguicoso) )
     raise("Voce tentou fazer algo impossivel\n")
    end
    super comportamento=comp
  end
end
 
class AlunoITA < Aluno
  def initialize(nome, queue)
    super(nome, queue)
  end
 
  def comportamento=(comp)
    if(comp.is_a?(Burro))
       raise("Voce tentou fazer algo impossivel\n")
     end
    super comportamento=comp
  end
 
end
 
class AlunoUnicamp < Aluno
  def initialize(nome, queue)
    super(nome, queue)
  end
 
  def comportamento=(comp)
    if(comp.is_a?(Summa) || comp.is_a?(SafoPreguicoso) )
     raise("Voce tentou fazer algo impossivel\n")
    end
    super comportamento=comp
  end
end
 
class Esforcado
  attr_reader :inteligencia, :dedicacao  
  def initialize(aluno)
    @aluno=aluno
    @inteligencia=0.5
    @dedicacao=1.0
  end
 
  def to_s
    "Esforcado"
  end
end
 
class Summa
  attr_reader :inteligencia, :dedicacao  
  def initialize(aluno)
    @aluno=aluno
    @inteligencia=1.0
    @dedicacao=1.0
  end
 
  def to_s
    "Summa"
  end
end
 
class SafoPreguicoso
  attr_reader :inteligencia  
  def initialize(aluno)
    @aluno=aluno
    @inteligencia=1.0
  end
 
  def dedicacao
    rand*0.5
  end
 
  def to_s
    "SafoPreguicoso"
  end
 
end
 
class Pemba
  def initialize(aluno)
    @aluno=aluno
  end
 
  def dedicacao
    rand*0.5
  end
 
  def inteligencia
    rand*0.5
  end  
 
  def to_s
    "Pemba"
  end
end
 
class Burro
  attr_reader :inteligencia, :dedicacao  
  def initialize(aluno)
    @aluno=aluno
    @inteligencia=0.0
    @dedicacao=0.0
  end
 
  def to_s
    "Burro"
  end
end
 
class Imprevisivel
  def initialize(aluno)
    @aluno=aluno
  end
 
  def dedicacao
    rand
  end
 
  def inteligencia
    rand
  end
 
  def to_s
    "Imprevisivel"
  end
end
 
class Relatorio
  attr_reader :qualidade, :originalidade, :aluno 
 
  def initialize(qualid, origin, aluno)
    @qualidade=qualid
    @originalidade=origin
    @aluno=aluno
  end
 
end
 
class RelaQueue
  def initialize
    @array = []
  end
 
  def queue(obj)
        @array.push(obj)
  end
 
  def dequeue
        @array.shift
  end
end
 
class Professor
  def initialize(queue)
    @queue=queue
  end
 
  def corrigir_relatorio(rela)
    ((rela.qualidade + rela.originalidade + rand ) / 3 )* 10
  end
 
  def corrigir_relatorios
    while(aux=@queue.dequeue)
      puts "#{aux.aluno.nome}"+ " - " + "#{aux.aluno.comportamento.to_s}" + ":" + "#{corrigir_relatorio(aux)}"
    end
  end           
end

Classe Simulador

Na classe Simulador as principais diferenças encontradas foram:
-> A facilidade, em relação à JAVA, para se escrever algo na tela e para se receber uma entrada do usuário .
-> No lugar do método ".equal", utilizamos o ".eql?" de ruby. Observe que o método termina com uma interrogação, o que significa que ele retorna um booleano.
-> Foi substituído os blocos de try/catch por um begin/rescue

require 'class'   
 
   queue =RelaQueue.new
   alunos=[]
   prof=Professor.new(queue)
 
   puts("Inserir novo aluno?(s/n): ")
   inserir=gets
   inserir.chomp!
   while(!inserir.eql?("s") && !inserir.eql?("n"))
      puts("Inserir novo aluno?(s/n): ")
      inserir=gets
      inserir.chomp!
   end        
 
while(inserir.eql?("s"))
      puts("Digite o nome do aluno: ")
      nome = gets
      nome.chomp! 
      puts("Diga o número correspondente a universidade a qual o aluno pertence: ")
      puts("1-ITA | 2-USP | 3-Unicamp")
      inst = gets
      inst.chomp!
      while(!inst.eql?("1") && !inst.eql?("2") && !inst.eql?("3"))
          puts("Tipo inválido. Diga o número correspondente a universidade do aluno: ");
          inst = gets
          inst.chomp!
      end
 
      puts("Diga o número correspondente ao comportmaneto do aluno: ")
      puts("1-Esforcado | 2-Safo | 3-Summa | 4-Pemba | 5-Burro | 6-Imprevisivel")
      tipo = gets
      tipo.chomp!
      while(!tipo.eql?("1") && !tipo.eql?("2") && !tipo.eql?("3") && !tipo.eql?("4") && !tipo.eql?("5") && !tipo.eql?("6"))
          puts("Tipo inválido. Diga o número correspondente ao comportmaneto do aluno: ");
          tipo = gets
          tipo.chomp! 
      end
 
      if(inst.eql?("1"))
          alunos.push(AlunoITA.new(nome, queue))
      elsif(inst.eql?("2"))
          alunos.push(AlunoUSP.new(nome, queue))
      elsif(inst.eql?("3"))
          alunos.push(AlunoUnicamp.new(nome, queue))
      end
 
    begin
 
      if(tipo.eql?("1"))
          alunos.last.comportamento=Esforcado.new(alunos.last)
      elsif(tipo.eql?("2"))
          alunos.last.comportamento=SafoPreguicoso.new(alunos.last)
      elsif(tipo.eql?("3"))
          alunos.last.comportamento=Summa.new(alunos.last)
      elsif(tipo.eql?("4"))
          alunos.last.comportamento=Pemba.new(alunos.last)
      elsif(tipo.eql?("5"))
          alunos.last.comportamento=Burro.new(alunos.last)      
      elsif(tipo.eql?("6"))
          alunos.last.comportamento=Imprevisivel.new(alunos.last)
      end
 
      rescue
        puts"#{$!}"
      end
 
      puts("Inserir novo aluno?(s/n): ")
      inserir = gets
      inserir.chomp!
      while(!inserir.eql?("s") && !inserir.eql?("n"))
          puts("Inserir novo aluno?(s/n): ");
          inserir = gets
          inserir.chomp!
      end
end
 
    alunos.each{|aluno| aluno.faz_e_entrega_relatorio}
 
    prof.corrigir_relatorios

Classe de Teste

Na classe de teste basicamente substituímos os assertEquals/assertTrue por assert_equal/assert, os blocos try/catch por begin/rescue e modificamos as formas de instanciar objetos e de mudar a variável comportamento.

require 'class'
require 'test/unit'
require 'teste'
 
class Teste < Test::Unit::TestCase
 
  def teste_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
    fail("Nao deveria lancar erro")
 end
 
  assert_equal(0.5, aluno1.inteligencia, 0.01);
  assert_equal(1, aluno1.dedicacao, 0.01);
 
  #teste de alunosafo
  assert_equal(1.0, aluno3.inteligencia, 0.01)
  assert(aluno3.dedicacao != aluno3.dedicacao) #deve ser randomica
  assert(aluno3.dedicacao < 0.5)
 
  #alunos comecam a fazer os relas
  aluno1.faz_e_entrega_relatorio
 
 #roubamos o relatório do primeiro aluno para investigá-lo
  rela1 = queue.dequeue
  assert_equal(aluno1, rela1.aluno)
  assert(rela1.aluno.nome.eql?("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.faz_e_entrega_relatorio
  aluno3.faz_e_entrega_relatorio
  aluno4.faz_e_entrega_relatorio
 
  #deve exibir a correção dos relas dos aluno2, aluno3, e aluno4, nesta ordem
  #pois "roubamos" o relatório do aluno1
  prof.corrigir_relatorios
  end
 
def teste_os_comportamentos_funcionam_como_especificado
  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 esforcado
  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()) #deve ser randomica
  assert(safo.dedicacao < 0.5);
 
  #teste de imprevisivel
  assert(imprevisivel.inteligencia != imprevisivel.inteligencia) #deve ser randomica
  assert(imprevisivel.inteligencia < 1.0)
  assert(imprevisivel.dedicacao != imprevisivel.dedicacao) #deve ser randomica
  assert(imprevisivel.dedicacao < 1.0)
 
  #teste de pemba
  assert(pemba.inteligencia != pemba.inteligencia) #deve ser randomica
  assert(pemba.inteligencia < 0.5)
  assert(pemba.dedicacao != pemba.dedicacao) #deve ser randomica
  assert(pemba.dedicacao < 0.5)
 
end
 
def teste_as_sub_classes_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
    fail("Não deveria lançar erro!")
  end
 
  begin
    alunoITA.comportamento= Burro.new(alunoITA)
    fail("Deveria lançar erro!");
  rescue
  end
 
  begin
    alunoUSP.comportamento=SafoPreguicoso.new(alunoUSP)
    fail("Deveria lançar erro!");
  rescue
  end
 
  begin
    alunoUnicamp.comportamento=Summa.new(alunoUnicamp)
    fail("Deveria lançar erro!")
  rescue
  end
 
end 
 
end

Testes Realizados

Testes realizados pela classe teste
lab4_fig1.JPG
Testes realizados manualmente pelo simulador
lab4_fig2.JPG

Código fonte:
Ces-22_Lab4

Conclusão

Nesse laboratório pudemos ter um contato com a linguagem Ruby. Foi bem interessante, pois foi a primeira linguagem dinâmica com a qual tive contato. Pude perceber uma maior facilidade do uso da linguagem em relação a JAVA, o que é muito bom para o programador, no entanto exige uma maior atenção, pois isso aumenta a chance de fazermos algo errado e mesmo assim o programa ser executado.
Outro ponto interessante a ser notado foi o fato de termos usado uma nova linguagem orientada a objeto para fazer um programa que já havia sido feito em JAVA. O que fortaleceu a noção de que os conceitos de orientação a objeto podem ser empregados independentemente da linguagem que está sendo utilizada.

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