Lab2 Ricardo Tominaga

aluno: Ricardo Itiro Sabota Tominaga
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 02/09/2008 (6)

Introdução

Nesse laboratório foi feito uma espécie de "update" do laboratório anterior. Foi criada uma classe que contém um método "main", possibilitando a realização de IO de dados pelo próprio console. Foram aplicados outros conceitos de OO como delegação e desacoplamento. Além disso, foi implementada uma solução de tratamento de exceções com "throw-try-catch exception". E também, criou-se uma classe para fila de tipo genérico, para, dessa forma, ser herdada por RelaQueue, que apenas especifica o tipo de objeto na fila.

Desenvolvimento

Interface para IO

Para a realização da interface com o usuário foi criada uma classe chamada de Simulador, a qual possui o método "main", responsável por realizar a execução principal do código. Dentro desse método foram instanciados os objetos necessários para a execução de um procedimento completo como no laboratório 1, no entanto sem a necessidade de faze-lo manualmente.

Console c;
        char flag=0;
        RelaQueue queue = new RelaQueue();
        Professor prof = new Professor(queue);
        Vector<Aluno> Alunos = new Vector<Aluno>(); 
        String s = new String();

Utilizando-se o objeto do tipo Console pôde-se realizar a aquisição de dados, bem como sua impressão no console.

...
     c = System.console();
 
        do{
            printMenu1(c);
            s = c.readLine("\nOpcao: ");
    ...
        c.printf("\n\nABSURDO! O aluno sera, por definicao, esforcado!");
    ...

Um exemplo da utilização da interface IO com o usuario através do console (no caso do próprio DOS, pois não foi possível pelo BlueJ).

lab2img3.jpg

Img.1 Exemplo da interface IO com o usuário

Desacoplamento, delegação e coesão

Inicialmente, no lab1, especificou-se apenas comportamentos de Aluno. Quando se desejou adicionar mais uma classificação, como a instituição que um determinado aluno estuda, o número de subclasses de Aluno aumentou, resultando em excesso de classes e repetição de código. Esse código seria, em princípio, muito acoplado, ou seja, praticamente tudo é feito e definido por Aluno. Por esse mesmo motivo, o código não tinha muita coesão, uma vez que o código restringia o seu reuso. Uma solução para desacoplar o código é a delegação. Percebeu-se que era possível separar o comportamento da instituição, ou seja, a criação de uma classe responsável apenas pelo comportamento.

public abstract class Comportamento
{   
    Aluno aluno;
 
    public Comportamento(Aluno aluno){
        this.aluno=aluno;
    }
 
    public abstract float getInteligencia();
    public abstract float getDedicacao();
}

Sendo abstrata, pode-se utilizar a herança para definir os comportamentos. Por exemplo:

public class Summa extends Comportamento
{
    private float inteligencia=1;
    private float dedicacao=1;
 
    public Summa(Aluno aluno){
        super(aluno);
    }
 
    public float getInteligencia(){
        return this.inteligencia;
    }
 
    public float getDedicacao(){
        return this.dedicacao;
    }
}
lab2img2.jpg

Img.2 Imagem que mostra instanciação manual e o diagrama de classes

Pela imagem 2 é possível perceber quão complexo é o código, no entanto se mostra organizado e bem desacoplado (desconsiderando as linhas de uso). Considerando-se que sem a delegação teríamos 6 (comportamentos) X 3 (instituições) = 18 subclasses (aproximadamente, pois há instituições que não admitem certos comportamentos), reduziu-se a necessidade de subclasses pela metade, bem como a repetição de código.

Os problemas de desacoplamento e coesão poderiam ser resolvidos, também, com a criação de uma classe abstrata Instituição, a qual definiria, por composição, a instituição do aluno, considerando até uma mudança de instituição (da mesma forma como foi feito o comportamento). Outra forma de resolver esses problemas é a utilização de interface, pois, cada comportamento diferente é obrigado a implementar todos os métodos da classe abstrata Comportamento, ou seja, é praticamente o mesmo trabalho.

Tratamento de exceções

A solução para tratamento de erros utilizada foi a definida pelas palavras reservadas throw-try-catch. Ela funciona da seguinte maneira: No método que se deseja aplicar uma exceção utiliza-se a palavra reservada "throw", que "lança" uma exceção no momento da chamada do método. Quando o método é chamado, deve-se utilizar o método "try" que tentará executar o pedido, caso haja uma exceção para a chamada daquele método a diretiva "catch" fará o tratamento da exceção.

Exemplo de código:

public void setComportamento(Comportamento comportamento) throws Exception{
        if(comportamento instanceof Burro) throw new Exception();
        super.setComportamento(comportamento);
    }

"Lançamento" da exceção

try {
        Alunos.lastElement().setComportamento(new Burro(Alunos.lastElement()))
    } catch (Exception e){
                 c.printf("\n\nABSURDO! O aluno sera, por definicao, esforcado!");
    };

"Tentativa" de chamar o método e tratamento da exceção (caso ocorra)

Fila de tipo genérico

No primeiro lab, foi criada uma classe RelaQueue, que era uma fila do tipo Relatório. Isso é muito restritivo, uma vez que só aceita objetos do tipo Relatório. Desejava-se realizar uma fila que pudesse comportar qualquer tipo de objeto. Para isso foi criada uma classe Queue<T>, onde T especifica o tipo da fila no momento da sua utilização no código. Para a construção da classe Queue genérica foi utilizado um objeto do tipo Vector, o qual já aceita tipos genéricos.

Código de Queue<T>:

public class Queue<T>
{
    private Vector<T> Q = new Vector<T>();
    private int inicio=0;
    private int fim=0;
 
    public void queue(T t){
        Q.add(fim,t);
        fim=(fim+1)%10;
    }
 
    public T dequeue(){
        T aux;
        if(inicio!=fim){
            aux=Q.elementAt(inicio);
            inicio=(inicio+1)%10;
            return aux;
        }
        else return null;
    }
}

Classe teste

Aqui está a "prova" do funcionamento do código:

lab2img1.jpg

Imagem da passagem no teste

Conclusão

Os conceitos de OO servem para o ser humano escrever menos código, sendo esse mais reutilizável e legível. Essa foi a maior conclusão com relação a esse lab. No entanto, na opinião do autor, a solução para a construção de uma fila de genéricos foi um tanto "acochambrada", pois foi utilizado o tipo Vector que já é uma espécie de fila, o que foi feito simplesmente limitou o tamanho da fila e a tornou cíclica. O tratamento de exceções permite a criação de um código robusto, uma vez que pode-se adicionar exceções e tratamento sem a utilização, por exemplo, de flags, ou de valores de retorno.

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