Lab4 Francisco Germano

aluno: Francisco Germano Batista da Silva Júnior
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 20/11/2008 (16)

Introdução

O laboratório consistiu na conversão do laboratório 02 feito em Java para Ruby. Todas as classes utilizadas na aplicação, classe main e classe de testes foram traduzidas para a linguagem Ruby. O principal objetivo do laboratório era propiciar uma comparação entre as linguagens, ressaltando as diferenças entre uma linguagem dinâmica/interpretada e uma estática/compilada.

Desenvolvimento

As diferenças de Ruby com relação a Java começam já na estruturação do projeto. Em ruby foram utilizados somente 3 arquivos (um para as classes da aplicação, um arquivo de simulação com comandos para serem executados e um arquivo com os testes), enquanto em Java temos nescessariamente um arquivo para cada uma das classes e um método main para poder rodar o simulador.

Foram criadas 16 classes para a aplicação (sendo uma delas de testes) e o código de simulação.

Aluno


Classe que representa os alunos na aplicação.

class Aluno
 
  def initialize (nome, queue)
    @nome = nome
    @queue = queue
    @comportamento = Esforcado.new(self)
    @conhecimento = 0  
  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)
    @conhecimento += 1
    @queue.queue(rela)
  end
 
  attr_reader :conhecimento
 
  attr_reader :nome
 
  def dedicacao
    @comportamento.dedicacao
  end
 
  def inteligencia
    @comportamento.inteligencia
  end
 
end

AlunoITA


Classe que representa os alunos do ITA.

class AlunoITA < Aluno
 
  def comportamento=(comportamento) 
    if(comportamento.instance_of?(Burro)) 
      raise "Comportamento de burro nao permitido para aluno do ITA"
    end
    @comportamento=comportamento
  end 
end

AlunoUSP


Classe que representa os alunos da USP.

class AlunoUSP < Aluno 
 
  def comportamento=(comportamento)
    if(comportamento.instance_of?(Summa))
      raise "Comportamento de Summa nao permitido para aluno da USP"
    elsif(comportamento.instance_of?(SafoPreguicoso))
      raise "Comportamento de Safo nao permitido para aluno da USP"
    end
    @comportamento=comportamento
  end
end

AlunoUnicamp


Classe que representa os alunos da Unicamp.

class AlunoUnicamp < Aluno
  def comportamento=(comportamento)
    if(comportamento.instance_of?(Summa))
      raise "Comportamento de Summa nao permitido para aluno da Unicamp"
    elsif(comportamento.instance_of?(SafoPreguicoso))
      raise "Comportamento de Safo nao permitido para aluno da Unicamp"
    end
    @comportamento=comportamento
  end
end

Comportamento


Classe que representa o comportamento dos alunos.

class Comportamento
 
  def initialize (al)
    @aluno=al
  end
 
  attr_reader :dedicacao
 
  attr_reader :inteligencia
 
end

Esforcado


Classe que representa o comportamento esforçado.

class Esforcado < Comportamento 
 
  def initialize(al)
    @dedicacao = 1
    @inteligencia = 0.5
    @aluno = al
  end
end

Burro


Classe que representa o comportamento burro.

class Burro < Comportamento
 
  def initialize (al)
    @dedicacao=0
    @inteligencia=0
    @aluno=al
  end
end

Imprevisivel


Classe que representa um comportamento imprevisível.

class Imprevisivel < Comportamento
 
  def dedicacao
    @dedicacao=rand
    @dedicacao
  end
 
  def inteligencia
    @inteligencia=rand
    @inteligencia
  end
end

Pemba


Classe que representa o comportamento de um pemba.

class Pemba < Comportamento
 
  def dedicacao
    @dedicacao = rand/2;
    @dedicacao
  end
 
  def inteligencia
    @inteligencia=rand/2;
    @inteligencia
  end
end

SafoPreguicoso


Classe que representa o comportamento de um aluno safo e preguicoso.

class SafoPreguicoso < Comportamento
 
  def initialize(al)
    @inteligencia=1
    @aluno=al
  end
 
  def dedicacao
    @dedicacao=rand/2;
    @dedicacao
  end
 
end

Summa


Classe que representa o comportamento de um aluno que será Summa cum Laude.

class Summa < Comportamento
 
  def initialize (al)
    @inteligencia=1;
    @dedicacao=1;
    @aluno=al;
  end
end

Professor


Classe que representa um professor.

class Professor
 
  def initialize(fila)
    @queue = fila
  end
 
  def corrigir_relatorio(rela)
    @nota = ( rela.qualidade + rela.originalidade + rand) / 3 * 10
  end
 
  def corrigir_relatorios
    temp=@queue.dequeue
    while temp!=nil
      puts(temp.aluno.nome+ ": " +self.corrigir_relatorio(temp).to_s)
      temp=@queue.dequeue
    end
  end
end

Queue


Classe que representa uma fila genérica de objetos.

class Queue
 
  def queue(obj)
    @array ||= []
    @array << obj
  end
 
  def dequeue
    obj = @array.pop
    return obj;
  end
end

Rela_queue


Sub-classe de Queue que representa uma fila de relatórios.

class Rela_queue < Queue
  ;
end

Relatorio


Classe que representa os relatórios feitos pelos alunos.

class Relatorio
 
  def initialize (qld, ori, al)
    @qualidade=qld
    @originalidade=ori
    @aluno=al
  end
 
  attr_reader :qualidade
 
  attr_reader :originalidade
 
  attr_reader :aluno
end

Simulador


Em um arquivo separado das classes foi criado um código para testar e simular a utilização do programa desenvolvido.

require "classes.rb"
 
c = 0
erro = 0
vet_aluno = []
fila = Rela_queue.new()
professor = Professor.new(fila)
 
while c != 4
  puts "1 - Adicionar aluno"
  puts "2 - Fazer relatorio"
  puts "3 - Corrigir relatorios"
  puts "4 - Sair"
 
  begin
    c=gets()
    c=c.to_i
  end while (c < 1 || c > 4)
 
  case c
 
  when 1
    puts "\nDigite o numero de alunos que serao inseridos"
    n = gets()
    n=n.to_i
    range = 1..n
    n.times do |i|
      puts "Digite o nome do aluno #{i+1}"
      str = gets()
      puts "Digite a instituicao do aluno\n1 - ITA\n2 - USP\n3 - Unicamp\n"
 
      begin
        j=gets()
        j=j.to_i
      end while (j < 1 || j > 3)
 
      case j
      when 1
        al = AlunoITA.new(str, fila)
      when 2
        al = AlunoUSP.new(str, fila)
      else
        al = AlunoUnicamp.new(str, fila)
      end
 
      begin
        puts "Digite o comportamento do aluno\n1 - Esforcado\n2 - Safo Preguicoso"
        puts "3 - Pemba\n4 - Suma\n5 - Burro\n6 - Imprevisivel\n"
 
        begin
          j=gets()
          j=j.to_i
        end while (j < 1 || j > 6)
 
        case j
        when 1
          comp = Esforcado.new(al)
          begin
            al.comportamento=(comp)
            erro = 0
          rescue Exception => ex
            erro = 1
          end
 
        when 2
          comp = SafoPreguicoso.new(al)
          begin
            al.comportamento=(comp)
            erro = 0
          rescue Exception => ex
            puts "Somente alunos do ITA podem ser safos preguicosos\n"
            erro = 1
          end
 
        when 3
          comp = Pemba.new(al)
          begin
            al.comportamento=(comp)
            erro = 0
          rescue Exception => ex
            erro = 1
          end
 
        when 4
          comp = Summa.new(al)
          begin
            al.comportamento=(comp)
            erro = 0
          rescue Exception =>ex
            puts "Somente alunos do ITA podem ser Summa\n"
            erro = 1;
          end
 
        when 5
          comp = Burro.new(al)
          begin
            al.comportamento=(comp)
            erro = 0
          rescue Exception => ex
            puts "Alunos do ITA nao podem ser burros\n"
            erro = 1
          end
 
        when 6
          comp = Imprevisivel.new(al);
          begin
            al.comportamento=(comp)
            erro = 0
          rescue Exception => ex
            erro = 1
          end
        end
      end while (erro == 1)
 
      vet_aluno << al
    end
 
  when 2
    puts "Qual aluno deve fazer o relatorio?"
    vet_aluno.length.times do |i|
      al = vet_aluno[i]
      puts "#{i+1} - " + al.nome
    end
    n = gets()
    n = n.to_i
    al = vet_aluno[n - 1]
    al.faz_e_entrega_relatorio
 
  when 3
    professor.corrigir_relatorios
  end
  puts "\n"
end

Abaixo segue o resultado dos testes manuais do programa.

Simulador_Ruby_01.jpg
Simulador_Ruby_02.jpg
Simulador_Ruby_03.jpg
Simulador_Ruby_04.jpg
Simulador_Ruby_05.jpg
Simulador_Ruby_06.jpg
Simulador_Ruby_07.jpg

Testes


Para finalizar o laboratório a classe de testes utilizada no laboratório 02 foi convertida para Ruby.

require 'classes' #carregue o código da sua aplicação aqui
require 'test/unit'
 
class LabTest < Test::Unit::TestCase
 
  def test_funciona_como_o_lab1
    #criando os objetos
    queue = Rela_queue.new
    prof = Professor.new(queue)
 
    # O que muda em termos de interface externa neste lab,
    # é a criação dos alunos. O que mostra que o nosso código
    # está bem desacoplado e a nossa refatoração não alterou
    # o funcionamento dos outros objetos (Professor, Relatório, etc).
    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
      fail("Nao deveria lançar erro!")
    end
 
    #teste de alunoesforcado
    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 coreção dos relas dos aluno2, aluno3, e aluno4, nesta ordem
    #pois "roubamos" o relatório do aluno1
    prof.corrigir_relatorios
  end
 
  def test_os_comportamentos_funcionam_como_especificado
    queue = Rela_queue.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 test_as_sub_classes_de_aluno_tem_restricoes
    queue = Rela_queue.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
      fail("Não deveria lançar erro!");
    end
    begin
      alunoITA.comportamento=(Burro.new(alunoITA))
      fail("Deveria lançar erro!");
    rescue Exception => e
    end
    begin
      alunoUSP.comportamento=(SafoPreguicoso.new(alunoUSP))
      fail("Deveria lançar erro!");
    rescue Exception => e
    end
    begin
      alunoUnicamp.comportamento=(Summa.new(alunoUnicamp))
      fail("Deveria lançar erro!")
    rescue Exception => e
    end
  end
 
  def test_rela_queue_eh_subclasse_do_generico_queue
    q = Rela_queue.new #propriedade básica do polimorfismo
 
  end
 
end

Todos os testes foram concluidos com sucesso, comprovando o bom funcionamento do código desenvolvido.

Teste_Ruby.jpg

Conclusão

Através desse laboratório foi possível aplicar algumas das diversas diferenças entre Ruby e Java. Ruby sendo uma linguagem dinâmica abre um grande número de possibilidades (devendo o programador possuir especial cuidado com respeito ao polimorfismo de seus objetos), causando até uma estranheza inicial para quem é acostumado a programar em linguagens estáticas. O encapsulamento é uma característica mais presente do que em Java, sendo os comandos de atalho para a criação de acessores a uma variável de instância uma grande vantagem.

Por fim pode-se dizer em linhas gerais que Ruby é uma linguagem mais concisa e legível que Java. O fato da linguagem ser interpretada pode causar complicações para programadores iniciantes pois muitos erros simples que poderiam ser detectados em tempo de compilação só serão detectados no tempo e execução (interpretação da linguagem).

O trabalho desenvolvido não necessitou de um conhecimento profundo de Ruby e não constituiu uma dificuldade na implementação de algoritmos ou padrões de projetos (tudo foi aproveitadod o laborat´roio número 02), entretanto a idéia de comparar o trabalho nas duas linguagens foi extremamente válida para a solidificação dos novos conceitos introduzidos com as linguagens dinâmicas e interpretadas.

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