Lab4 Cicero David

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

Introdução

Essa prática de laboratório objetivou familiarizar-se com a linguagem de programação Ruby, atentando para as pricipais diferenças em relação à Java. A prática consistiu na "tradução" do código gerado no lab2 para Ruby.

Desenvolvimento

Diferentemente de Java, podemos declarar todas as classes em um mesmo arquivo. Assim, resolveu-se dividir o código em três arquivos:
"classes.rb": contém a criação das classes das entidades
"teste.rb": contém a classe de teste Unit
"simulador.rb": contém o código que simula a interface com o usuário

Os principais pontos observado na criação das classes das entidades foi a questão da herança (não existem classes abstratas em Ruby, mas mesmo assim manteve-se a classe Comportamento, só para manter-se semelhante ao lab2), a criação mais prática de getters e setters (por meio do uso de attr_writer, attr_reader), a tipagem dinâmica e o tratamento de exceções.

Abaixo segue como exemplo a classe Aluno a algumas de suas subclasses

class Aluno
  attr_reader :nome, :conhecimento
  attr_writer :comportamento
 
  def initialize (nome, rela_queue)
    @nome = nome
    @queue = rela_queue
    @conhecimento = 0
    @comportamento = Esforcado.new(self)
  end
 
  def faz_e_entrega_relatorio
    qualidade = (2*@comportamento.dedicacao + 1*@comportamento.inteligencia)/ 3
    originalidade = (1*@comportamento.dedicacao+2*@comportamento.inteligencia)/3
    rela = Relatorio.new(qualidade, originalidade, self)
 
    @queue.queue(rela)
    @conhecimento = @conhecimento + 1
 
  end
 
  def inteligencia
    return @comportamento.inteligencia
  end
 
  def dedicacao 
    return @comportamento.dedicacao
  end
 
  def conhecimento
    return @conhecimento
  end
 
end
 
class AlunoITA < Aluno
  def initialize (nome, rela_queue)
    super
  end
 
  def comportamento=(comportamento)
     raise "nao eh possivel" if (comportamento.instance_of?(Burro))
     @comportamento = comportamento
  end
end
 
class AlunoUSP < Aluno
  def initialize (nome, rela_queue)
    super
  end
 
  def comportamento=(comportamento)
     raise "nao eh possivel" if ((comportamento.instance_of?(Summa))||(comportamento.instance_of?(SafoPreguicoso)))
     @comportamento = comportamento
  end
end
 
class AlunoUnicamp < Aluno
  def initialize (nome, rela_queue)
    super
  end
 
  def comportamento=(comportamento)
     raise "nao eh possivel" if ((comportamento.instance_of?(Summa))||(comportamento.instance_of?(SafoPreguicoso)))
     @comportamento = comportamento
  end
end

O classe de teste mostrou-se ser bastante parecida com o os testes JUnit em Java, sendo necessário basicamente mudar somente os nomes dos métodos, a forma de intanciação e o tratamento de exceções
Na codificação do simulador foi que pôde-se notar a utilidade da propriedade de meta-programação da linguagem Ruby. É dado ao usuário a possibiliade de escolher a faculdade e o comportamento dos objetos alunos. A princípio é necessário então definir um controle de fluxo (com a utilização de ifelse ou switch… case) para decidir que tipo de subclasse seria instanciada a partir da escolha do usuário. Com a ulização da meta-pogramação foi possível criar o código a ser executado em tempo de execução através de um string e do comando eval() do ruby. Assim, bastou construir uma string composta a parter da decisão so usuário e então executá-la. O código onde isso pode ser observado é msotrado abaixo:

require 'classes'
 
tipo_aluno = {1=> "ITA",2 => "Unicamp", 3=>"USP"}
tipo_comportamento = {1=> "Burro",2 => "Esforcado", 3=>"Imprevisivel", 
 4=>"Pemba", 5=>"SafoPreguicoso", 6=>"Summa"}
 
rela_queue = RelaQueue.new
alunos = []
professor = Professor.new(rela_queue)
 
while (true)
 
  puts "Escolha a faculdade:"
  while (true)
    tipo_aluno.each { |key,value| puts "#{key} : #{value}"}
    puts "Escolha:"
    resposta_fac = gets 
    break if tipo_aluno.has_key?(resposta_fac.to_i)   
  end
  puts "Escolha o comportamento:"
  while (true)
    tipo_comportamento.each { |key,value| puts "#{key} : #{value}"}
    puts "Escolha:"
    resposta_comp = gets 
    break if tipo_comportamento.has_key?(resposta_comp.to_i)   
  end
 
  puts "Nome: "
  nome = gets
  aluno = eval("Aluno#{tipo_aluno[resposta_fac.to_i]}.new(\"#{nome}\", rela_queue)")
 
  begin
  eval("aluno.comportamento=#{tipo_comportamento[resposta_comp.to_i]}.new(aluno)")
  alunos.unshift(aluno)
  rescue Exception =>e
  puts e 
  end
 
  puts "Criar mais algum aluno?"
  break if (gets.eql?("n\n"))
end
 
alunos.each { |item| item.faz_e_entrega_relatorio}
professor.corrigir_relatorios

Também observou-se que não é necessária a criação de um classe com o método estático main para gerar um código executavel.

Após realizada a codificação, executou-se o arquivo de teste obtendo o resultado satisfatório mostrado na figura abaixo:

tetseUnit.JPG

Por último, realizamos alguns testes com o simulador. Abaixo segue um desses testes:
testeSimulador.JPG

Conclusão

Com essa prática, pôde-se familiarizar-se com a linguagem ruby. Percebeu-se que ela possui algumas vantagens que reduzem a quantidade de código necessário drasticamente, como a tipagem dinâmica a utilização de attr_acessor e a meta-porgramação, abindo mais espaço para o porgramador. Entretanto o desenvolvimento mostrou-se bem mais complicado, visto que a maior parte dos erros só podem ser vizualizados em tempo de excução, a utilidade de ambientes de desenvolvimento, como o NetBeans, reduz bastante já que em virtude da tipagem dinamica se limita-se a criação automática de código e verificação automática de erros.

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