Lab1: Introdução a OO e Java

aluno: José Gerardo Arruda Junior
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 28/08/2008 (5)

Introdução

Nesta primeira aplicação, foi desenvolvido um programa em Java com o objetivo principal de sedimentar os conceitos de OO vistos em aula e a sintaxe da linguagem.

Com esse intuito, criou-se uma aplicação que simula as atividades de entrega e correção de relatórios por alunos e professores, respectivamente. A correção é coordenada por uma fila, onde são inseridos os relatórios a medida que são entregues.

Neste contexto, criaram-se 4 classes principais, que representam os elementos dessa dinâmica: Aluno, Professor, Relatório e RelaQueue. Da classe aluno, abstrata, herdou-se duas subclasses, AlunoEsforcado e AlunoSafoPreguicoso, com comportamentos ligeiramente diferentes.

A aplicação como um todo e o modo como as classes interagem entre si na troca de informações podem ser vistos no diagrama de classes abaixo, proposto no enunciado:

diagrama_de_classes.bmp

Desenvolvimento

Percebeu-se que é bastante importante o entendimento do diagrama de classes antes do início do desenvolvimento do código, para perfeita compreensão de como ocorrerá a troca de informações entre as distintas classes. Tal diagrama dá a noção da "natureza" dos processos, e sua importância só pôde ser percebida depois de dificuldades encontradas ao escrever cada classe isoladamente, sem um entendimento prévio da dinâmica geral.

A observação do diagrama permite concluir, por exemplo, que objetos das classes Aluno e Professor só podem ser criados depois da criação de um objeto da classe RelaQueue, visto que este é passado como parâmetro na construção das classes Aluno e Professor. Esta é a idéia de dependência, representada no diagrama por uma seta em linha contínua. Tal tipo de dependência tem reflexo no código do programa, já que exige que atributos da classe RelaQueue sejam instanciados nas classes dependentes (Aluno e Professor) para que a informação passada na mensagem do construtor seja armazenada.

Só após um entendimento geral, portanto, deve-se entender cada classe internamente. Nos próximos itens serão detalhadas cada uma delas, com os comentários pertinentes.

Classe RelaQueue

Na criação dessa classe houve apenas uma confusão, pois no diagrama de classes não há atributos mostrados, apenas os métodos. No entanto, sabe-se que devem ser declarados os atributos "inicio" e "fim" usados nos métodos queue() e dequeue(), e instanciado um objeto da classe Relatorio, conforme o trecho de código abaixo:

// Variáveis de instância
    private Relatorio[] relaQueue = new Relatorio[10]; 
    private int inicio = 0;
    private int fim = 0;

Penso ainda que a dependência desta classe à classe Relatorio deveria ser tracejada e não contínua, visto que podemos instanciar um RelaQueue antes de instanciar um Relatorio.

No método dequeue(), foi feita uma modificação no algoritmo proposto a fim de garantir que o professor saiba que não existem mais relatórios para corrigir. Neste caso, que ocorre quanto inicio =fim, uma chamada a dequeue() retorna null:

public Relatorio dequeue(){
        Relatorio valor;  

        if (this.inicio == this.fim) valor = null;
        else { 
            valor = relaQueue[inicio];
            inicio = (inicio +1) % 10;
        }
        return valor;
    }

Classe Aluno

A criação dessa classe foi a que apresentou a maior dificuldade de implementação, associada principalmente à aplicação dos conceitos de herança e de classe abstrata na sintaxe do programa.

No que diz respeito à abstração da classe, houve dúvida no seguinte aspecto: sendo a classe abstrata e não havendo, portanto, objetos instanciados, faz sentido adicionar um construtor em seu código, conforme foi sugerido no diagrama de classes? Na resolução deste problema, optou-se por criar dois construtores, um para cada subclasse, ao invés de um para a classe abstrata, conforme pode ser visto no trecho abaixo:

//Construtor da subclasse AlunoEsforçado
    public AlunoEsforcado(String nome, RelaQueue queue){
        this.nome = nome;
        this.queue = queue;        
    }
 
//Construtor da subclasse AlunoSafoPreguicoso
    public AlunoSafoPreguicoso(String nome, RelaQueue queue){
        this.nome = nome;
        this.queue = queue;        
    }

Uma fato observado, agora relacionado à herança da classe, é que o atributo "nome" deve ser declarado como protected, afim de que possa ser acessado no construtor das subclasses. Uma alternativa caso quiséssemos deixá-lo privado, seria criar um métodos público na classe Aluno que atribuisse a mensagem ao nome, e chamar este método no construtor das subclasses. Optamos por deixá-lo como protegido.

Observando o diagrama de classes fornecido, penso que deve ser adicionada uma dependência Aluno —> Relatório (tracejada), visto que é criado um objeto Relatorio no método fazEEntregaRelatorio().

Na página de instruções do lab1 há uma contradição com a do diagrama UML dos métodos getDedicacao() e Inteligencia(). Adotei na implementação a descrição do diagrama UML.

Classe Relatorio

Esta classe foi a de implementação mais fácil e dispensa muitos comentários. Atento apenas para o fato de seu construtor, no diagrama UML, estar retornando um objeto do tipo Relatorio, o que vai ao encontro da definição de construtor, pois devem retornar "void".

Classe Professor

Esta classe também foi de fácil implementação. Nela observamos pela primeira vez um método privado(corrigirRelatorio()), assim declarado pois só é chamado de dentro da classe. Isso ilustra o conceito de encapsulamento e garante a transparência do método corrigirRelatorios().

Resultados

Primeiramente, executou-se a aplicação criando instâncias manualmente. Criou-se os mesmos 4 alunos do teste da "unit test" e chamou-se o método corrigir relatorios do objeto "prof". Vemos abaixo que as notas dos 4 alunos foram impressas, pois, aqui, não "roubamos" o relatório do aluno1 com a chamada co método dequeue().

teste_manual.bmp

Em seguida, criou-se uma classe do tipo "Unit Test" e executou-se o teste fornecido. Os resultados condizem com o esperado (impressão da nota de 3 alunos), como visto abaixo:

testAluno.bmp

Conclusão

A aplicação foi ótima para a consolidação do aprendizado de aula. No início, houve alguma dificuldade com a sintaxe da linguagem e principalmente com a forma de como "conectar" uma classe à outra por meio de seus métodos, envio de mensagens, etc.

Alguns dos conceitos utilizados não estavam presentes nos slides de aula (até porque não dá pra colocar tudo) e, no meu caso, isso dificultou um pouco o trabalho no início. Procurei algumas bibliografias e encontrei algumas das informações que precisava bem esparsas.

A noção de OO pôde ser bem embasada com a aplicação proposta.

Desculpas pelo atraso na entrega do relatório. Quando percebi que não daria para entregá-lo no prazo, optei fazê-lo com calma a fim de assimilar os conceitos da melhor forma. Peço adote o critério que achar apropriado na atribuição da nota.

Bernardo de PaduaBernardo de Padua 1220716845|%e %b %Y, %H:%M %Z|agohover

O diagrama de RelaQueue não especificou nada além dos métodos queue() e dequeue() para deixar a implementação da queue livre (podia ser feita como o aluno preferisse).

O contrutor não retorna void (ele não retorna nada, na verdade). Mas o keyword new retorna um Relatório. Em Ruby, por exemplo, new nada mais é que um método de classe que retorna o objeto construído. Pode-se pensar no construtor como uma das partes do processo de inicialização do objeto (new), na qual vc pode adicionar código a ser executado em cada inicialização.

Não precisa colar a imagen da descrição do rela. O relatório está bom.

POR FAVOR, NÃO USE O FORMATO BMP PARA OS SCREEN SHOTS. Suas imagens ocuparam mais de 3MB, nosso espaço é limitado no Wiki (use o jpg ou png, ficariam 10X menores).

unfold by Bernardo de PaduaBernardo de Padua, 1220716845|%e %b %Y, %H:%M %Z|agohover
Add a new comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License