Lab4 Leonardo Bruno

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

Introdução

Neste laboratório iremos ter o primeiro contato prático com a linguagem Ruby, que também se caracteriza pela OO. A principalmente diferença de Ruby está em seu caráter dinâmico, o que diferencia sensivelmente de java, que tem um carater estático. Devido a esse carater dinãmico a linguagem já se torna bem mais simples, uma vez que previsões do tipo da variáveis são postergadas para o tempo de execução. Ruby também se caracteriza pelos aspectos mais naturais de seu código, se aproximando muito de uma linguagem natural. Assim, iremos portar para Ruby o código em java feito no segundo laboratório.

Desenvolvimento

Criamos três arquivos. O primeiro contém todas as classes do programa. Podemos perceber que a classe abstrata que englobova todos os tipos de comportamento perdeu sua finalidade, uma vez que a tipagem agora é dinâmica. Também devido a esse caráter dinânico, podemos perceber a grande simplificação que o código sofreu, uma vez que declarações de tipos de variáveis não são mais necessárias. Vale também ressaltar as várias facilidades que o Ruby possui,como a ausencia de chaves, como o carater optativo do uso de parentesis ,ou de ponto e vírgula , o que torna a leitura do código bem mais intuitiva. A seguir, podemos observar o arquivo com as classes:

class Aluno
    # variaveis de instancia
    @conhecimento
    @nome
    @queue
    @comportamento
 
   def initialize (n,q)
        @nome = n
        @queue = q
        @comportamento = Esforcado.new(self)
        @conhecimento=0
 
   end
 
    attr_accessor :nome #Configurador que seta o nome de um aluno
    attr_accessor :comportamento
    attr_reader :conhecimento
 
    def dedicacao
    @comportamento.dedicacao
    end
 
    def inteligencia
    @comportamento.inteligencia
    end
 
    def fazeentregarelatorio #Metodo que manda o Aluno fazer e entregar um realtorio
        qualidade = ((2*@comportamento.dedicacao() + @comportamento.inteligencia()) / 3 )
        originalidade = ((@comportamento.dedicacao() + 2*@comportamento.inteligencia()) / 3)     
        rela = Relatorio.new(qualidade,originalidade, self)  
        @queue.queue(rela)
        @conhecimento=@conhecimento+1
    end
end
 
class AlunoITA < Aluno
 
    def initialize(n,q)
       super   
     end
 
    def comportamento=(comp) 
       # @comportamento= comp
       if (comp.class == Burro)  then raise(Exception.new) end #"iteanos não são burros!"
       @comportamento= comp
      #super.setComportamento(comportamento); //faz o que a superclasse Aluno faz.       
    end
end
 
class AlunoUSP < Aluno
 
    def comportamento=(comp)
       if((comp.class==Summa)||(comp.class== SafoPreguicoso))then raise(Exception.new)end #"apenas iteanos sao safos!"
       @comportamento=comp
    end
end

Acima, podemos observar a facilidade com que o getters e setters são feitos. A nomenclatura e os atalhos(attr) facilitam muito a programação. O uso de uma @ nas variáveis de instancia torna-as bem mais visíveis.

Agora, olhemos como ficou o arquivo referente ao simulador:

require 'classes'     
 
      #//inicia o Array de alunos
      alunos = Array.new
 
      puts("Deseja inserir novo aluno?(s/n): ")
      op2 = gets()
 
         #String op;
      #String nome;
 
      q = RelaQueue.new #//cria a queue
      p = Professor.new(q) # //cria o professor
      #Aluno temp;
 
      #os alunos serao criados até q o operador nao deseje mais
      while(op2=="sim\n")
 
          #//inicialmente sera perguntado a Escola e o Nome do aluno
          puts("Qual a escola do aluno?: ")
      op=gets() 
 
          case op
          when "ITA\n"          
             puts("O nome do aluno: ")
             nome = gets
             temp = AlunoITA.new(nome,q)
             alunos << temp          
          when "USP\n"           
             puts("O nome do aluno: ")
             nome = gets
             temp = AlunoUSP.new(nome,q)
             alunos << temp
          when "Unicamp\n"           
                puts("O nome do aluno: ")
                nome = gets
                temp = AlunoUnicamp.new(nome,q)
                alunos << temp
          else 
            puts("tipo de aluno invalido! Tente denovo!")
            next
          end                          
 
    #  //sera atribuido o comportamento do aluno
      puts("Qual o comportamento do aluno?: ");
      op=gets()
      if(op=="SafoPreguicoso\n") 
         begin 
             temp.comportamento= SafoPreguicoso.new(temp)
             rescue Exception => e 
               puts("Apenas iteanos sao Safos!") 
         end     
      elsif(op=="Esforcado\n") 
      begin
         temp.comportamento= Esforcado.new(temp)
         rescue Exception => e
 
      end  
      elsif(op=="Summa\n")
      begin                     
        temp.comportamento= Summa.new(temp)
         rescue 
           puts("Apenas os iteanos são Summa")
      end 
      elsif(op=="Pemba\n")
      begin                      
         temp.comportamento= Pemba.new(temp)
         rescue Exception => e  
 
      end
      elsif(op=="Imprevisivel\n")
      begin                      
         temp.comportamento= Imprevisivel.new(temp)
         rescue Exception => e                               
      end
      elsif(op=="Burro\n")
      begin                             
         temp.comportamento= Burro.new(temp)
         rescue Exception => e
           puts("Iteanos nao sao burros")
      end
      else puts("tipo de aluno invalido! Ele sera considerado Esforcado!")
      end         
 
      puts()
      puts("Deseja inserir novo aluno?(s/n): ")
      op2=gets()
      puts()
  end
    #faz todos os alunos criados fazerem e entregarem o relatorio
    for a in alunos 
     a.fazeentregarelatorio        
    end            
    p.corrigirrelatorios()

Podemos Observar a facilidade do for em Ruby e de como trabalhar com o array. O case e os if-elsif também funcionam de forma harmônica, sendo a principal vantagem a simplicidade da sintaxe. Aqui fica bem clara a simplificação pela ausencia das declarações dos tipos das variáveis.
Realizamos uma série de testes com o simulador, conforme segue abaixo:

fig1.JPG

fig1

fig2.JPG

fig2

Por último, portamos o código dos testes, conforme segue a seguir:

require 'classes' #carregue o código da sua aplicação aqui
require 'test/unit'
#este é só um exemplo, não é toda a classe de testes!
class TestInteressante < Test::Unit::TestCase
 
def testFuncionaComoOLab1()
  #criando os objetos
  queue = RelaQueue.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 
    fail("Não 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.fazeentregarelatorio();
 
 #roubamos o relatório do primeiro aluno para investigá-lo
  rela1 = queue.dequeue();
  assert_equal(aluno1, rela1.autor());
  assert(rela1.autor().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.fazeentregarelatorio();
  aluno3.fazeentregarelatorio();
  aluno4.fazeentregarelatorio();
 
  #deve exibir a coreção dos relas dos 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 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 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
    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 
end

Assim, executamos na linha de comando conforme fizemos com o simuldor:

fig3.JPG

fig3

Assim, podemos perceber que todos os teste foram aceitos.

O arquivo fonte está anexado no relatório.

Conclusão

Assim, podemos perceber bem após este laboratório as diferenças entre java e Ruby. Notamos que Ruby é uma linguagem bem mais prática e rápida, o que decorre do fato de ser carater dinâmico e de sua alta simplicidade na sintaxe. Ao longo de todo o laboraório, podemos ver como o código foi se simplificando e tomando uma forma mais natural de se ler. Só pelo fato de não temos que nos preucupar amplamente com os tipos das variáveis, evitando todas as declarações necessárias em java, Ruby já ganha uma imensa vantagem no que diz repesito a simplicidade. Fora isso, ainda podemos notar diferenças na sintaxe que a tornam mais prática e intuitiva. Obviamente, que pode ser o primeiro contato com Ruby demandei uma quantidade de tempo muito grande para realização deste laboratório, pois os detalhes da linguagem no primeiro contato podem ser grandes barreiras, mas apesar disto, foi uma experiência muito positiva.

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