Modelagem e Implementação de Aquário de Peixes- por Jorge Fernandes - Página 1 Modelagem e Implementação (Incremental de um Software para Controle) de Aquário de Peixes Jorge Fernandes Natal, Agosto de 2002 1. Objetivos O objetivo deste texto é apresentar uma seqüência de decisões de projeto e implementação com o objetivo de criar um programa em Java que manterá informações sobre um aquário de peixes ornamentais. Basicamente um cadastro dos peixes presentes no aquário será criado para facilitar a manutenção do aquário. Este texto é composto por mais 4 seções. A Seção 2 apresenta o modelo inicial do nossos sistema. 2. Modelagem do Sistema Obedecendo ao "Princípio da Abstração", criaremos uma série de representações de informação sobre os elementos que fazem parte do sistema (aquário e peixes), limitando as informações coletadas sobre estes elementos ao mínimo necessário. Isto é, o nosso modelo e implementação de software tratará apenas a quantidade de informações necessárias e suficientes para suportar as operações de manutenção do aquário. Mesmo que possamos armazenar uma grande informações diversas sobre o aquário, como formato do aquário, data de fabricação, fabricante, tipo de material usado na construção, etc, nos limitaremos a armazenar apenas os dados que são necessários a realização das operações de manutenção. A principal informação necessária para manutenção do aquário é seu volume de água em litros. Adicionalmente, como podemos controlar vários aquários com o software, precisamos dar um nome para cada aquário. Adicionalmente, o aquário contém um conjunto de peixes. Para cada peixe será armazenado sua espécie, sexo, nome ou apelido, e ano e mês de nascimento. 3. Regras para Manutenção de um Aquário Para facilitar a manutenção do aquário será necessário armazenar a data da última manutenção efetuada no mesmo (mês e ano). A manutenção compreende a limpeza do aquário e a retirada ou inserção de alguns peixes, conforme regras abaixo: 1. O somatório das idades dos peixes, em mêses, deve ser igual ou inferior, ao volume do aquário em litros de água; 2. Cada um dos peixes não deve viver em um aquário cujo volume, em litros, seja menor do que a quadrado da sua idade medida em bimestres. A periodicidade de manutenção dependerá do volume do aquário e da quantidade de peixes no mesmo. URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 2 4. Funcionalidades Básicas do Programa A nossa primeira versão do programa só manipula as informações de um único aquário por vez, e deste modo deve oferecer suporte às seguintes opções: 1. 2. 3. 4. 5. Criação de um Aquário; Inclusão de um Peixe no Aquário; Remoção de um Peixe do Aquário; Listagem de todos os peixes contidos no aquário; Consulta sobre a data estimada da próxima manutenção do aquário, com listagem dos peixes que devem ser removidos na data estimada; 6. Registro de manutenção efetuada no aquário, com indicação da data na qual a mesma foi efetuada. A retirada dos peixes efetuada durante a manutenção deve ser informada através da opção de menu "Remoção de um Peixe do Aquário". 5. Funcionalidades para Gerenciamento de Dados Dado que todas as informações manipuladas pelo programa estão contidas em memória RAM, estas podem ser perdidas se não forem armazenadas em meio permanente. Por isto se faz necessário suportar mais duas operações no programa, chamadas operações de gerenciamento de dados: 1. Exportação - copia as informações sobre o aquário que estão em memória RAM, armazenando-as em um meio permanente (diskette ou no HD); 2. Importação - recupera as informações sobre o aquário que estão em meio permanente, e reconstrói na memória RAM as informações sobre o aquário. 6. Modelagem das Informações do Programa O diagrama de classes abaixo modela as informações necessárias para a manutenção do aquário. Modelo de dados do sistema de informações de um aquário Mais adiante faremos a modelagem das operações suportadas pelo programa. 7. Prototipagem do Sistema Obedecendo ao princípio de Construção de Software "Bottom-Up", faremos inicialmente a prototipagem dos objetos mais simples do sistema, no caso os peixes, para depois prosseguirmos com a prototipagem do aquário. 7.1 Definindo a classe Peixe Precisamos fornecer suporte à criação e manipulação de peixes. A classe Peixe_V1 modela os dados de um Peixe. Chamaremos de Peixe_V1 para indicar que é a versão 1 de nosso protótipo. class Peixe_V1 { URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 3 String especie; String sexo; String nome; int anoNascimento; int mesNascimento; } 7.2 Criando um Peixe "Japones" chamado de "Grandao" Com a declaração de classe acima já é possível criar um objeto que armazene informações sobre um peixe. Colocaremos instruções para criação de peixes na classe aquário. O programa abaixo, por exemplo, cria um objeto peixe e associa algumas informações a eles. class Aquario_V1 { public static void main(String[] args) { Peixe_V1 peixe = new Peixe_V1(); peixe.especie = "Japones"; peixe.nome = "Grandao"; peixe.anoNascimento = 2000; peixe.mesNascimento = 1; peixe.sexo = "Macho"; } } 7.4 Criando um Peixe Qualquer O programa da classe Aquario_V1 (mais propriamente chamado de método main() da classe Aquario_V1, ou Aquario_V1.main) cria um objeto peixe, mas os dados do peixe são fixos (isto é, definidos dentro do próprio programa), o que o torna inflexível se quisermos usar este programa para criar peixes diferentes de um "Japones" chamado de "Grandao". A versão abaixo faz com que os dados do peixe, como espécie, nome, sexo, etc, sejam informados pelo usuário. Sobre os trechos de código "IO.readStr()" e "IO.readInt()", por enquanto é suficiente saber que readStr() e readInt() são métodos da classe IO.java. Eles são responsáveis por capturar a entrada de dados do usuário, via teclado, e retornar os dados digitados no formato de objetos Strings (cadeias de caracteres) e números inteiros, respectivamente. class Aquario_V2 { public static void main(String[] args) { Peixe_V1 peixe = new Peixe_V1(); peixe.especie = IO.readStr(); peixe.nome = IO.readStr(); peixe.anoNascimento = IO.readInt(); peixe.mesNascimento = IO.readInt(); peixe.sexo = IO.readStr(); } } 7.5 O Método criaPeixe() O programa Aquario_V2.main cria um único peixe, cujos dados são informados pelo usuário. No entanto, o objeto (da classe Peixe_V1) é destruído quando o programa é encerrado. Adicionalmente o URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 4 método main, por definição, está exigindo a passagem de um array de strings como parâmetro, o que não é necessário para criação de peixes. A solução para resolver os problemas acima é criar um método novo (o chamaremos de criaPeixe()), cujas responsabilidades são: (1) receber entrada de dados do usuário, (2) criar um objeto peixe, e (3) retornar, ao método chamador, o peixe criado. O código fica agora como abaixo. Manteremos o método main() de forma a indicar como se pode chamar o método Aquario_V3.criaPeixe() para criar um ou mais peixes. class Aquario_V3 { public static Peixe criaPeixe() { Peixe_V1 peixe = new Peixe_V1(); peixe.especie = IO.readStr(); peixe.nome = IO.readStr(); peixe.anoNascimento = IO.readInt(); peixe.mesNascimento = IO.readInt(); peixe.sexo = IO.readStr(); return peixe; } public static void main(String[] args) { Peixe p1 = Aquario_V3.criaPeixe(); Peixe p2 = Aquario_V3.criaPeixe(); Peixe p3 = Aquario_V3.criaPeixe(); } } 7.6. Aumentando Compreensibilidade na Interface com o Usuário Perceba que as as solicitações de entrada de dados feitas ao usuário no método Aquario_V3.criaPeixe () são "silenciosas", o que dificulta ao usuário do programa saber o que deve deve ser digitado. O programa abaixo indica ao usuário, de forma mais clara, qual a informação que deve ser fornecida pelo usuário. Adicionalmente, como os métodos main() e criaPeixe() estão declarados na mesma classe, não é necessário que o método main() informe explicitamente em qual classe está o método criaPeixe(), o que reduz a quantidade de texto no código e aumenta a legibilidade do programa. A classe Aquario_V4 contém as melhorias de usabilidade (para o usuário) e legibilidade (para o programador). class Aquario_V4 { public static Peixe criaPeixe() { IO.println("Criando um peixe."); Peixe_V1 peixe = new Peixe_V1(); IO.println(" Informe a espécie do peixe e tecle <enter>:"); peixe.especie = IO.readStr(); IO.println(" Informe o nome do peixe (se tiver):"); peixe.nome = IO.readStr(); IO.println(" Informe o ano de nascimento do peixe (1999, 2000, 2001, etc.):"); peixe.anoNascimento = IO.readInt(); IO.println(" Informe o mês de nascimento do peixe (1 - Janeiro, 2 - Fevereiro, etc.):"); peixe.mesNascimento = IO.readInt(); IO.println(" Informe o sexo do peixe, digite a letra "M" (Macho) ou "F" (Fêmea):"); peixe.sexo = IO.readStr(); IO.println("Peixe Criado!"); return peixe; } public static void main(String[] args) { URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 5 Peixe p1 = criaPeixe(); Peixe p2 = criaPeixe(); Peixe p3 = criaPeixe(); } } 7.7. Armazenando os Peixes em um Array Os peixes criados pelo programa Aquario_V4.main estão armazenados (referenciados) em variáveis individuais, o que inviabiliza a criação de uma quantidade arbitrária de peixes, visto que seria necessário a declaração de uma variável para cada objeto criado. O programa Aquario_V5.main utiliza uma estrutura de array para guardar uma quantidade qualquer de peixes. Para facilitar a visualização do código doravante omitiremos o código do método criaPeixe(), que já está completo, e o moveremos para o final do código da classe. class Aquario_V5 { public static void main(String[] args) { Peixe_V1[] peixes = new Peixe_V1[1000]; peixes[0] = criaPeixe(); peixes[1] = criaPeixe(); peixes[2] = criaPeixe(); } public static Peixe criaPeixe() { ... } } Perceba que apenas uma variável (peixes) é declarada no programa, mas esta referencia um array capaz de armazenar até mil peixes. Por outro lado, o programa ainda está limitado, pois efetivamente só cria uma quantidade fixa de peixes (três), armazenadas nas posições indicadas pelas constantes "0", "1" e "2". O programa deve delegar ao usuário a decisão de criar a quantidade de peixes que ele achar necessário, o que fazemos a seguir. 7.8. O Usuário no Controle Pleno da Criação de Peixes No programa Aquario_V6.main usamos uma estrutura de repetição (do { ... } while()) e um índice (qtdPeixes) para indicar a posição na qual o peixe será armazenado. Como o índice não é mais uma constante, e sim uma variável, podemos iniciar armazenando os peixes na posição 0 (veja que a variável posição começa com o valor 0) e prosseguir incrementando qtdPeixes de um em um, o que armazena os outros peixes criados em posições subsequentes, até que o usuário desista de criar peixes. class Aquario_V6 { public static void main(String[] args) { Peixe_V1[] peixes = new Peixe_V1[1000]; int qtdPeixes = 0; do { IO.println("Quer Criar um Peixe? (S/N)"); String opcao = IO.ReadStr(); if (opcao.equals("S")) { peixes[qtdPeixes] = criaPeixe(); qtdPeixes++; } } while (! opcao.equals("N")); URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 6 } public static Peixe criaPeixe() { ... } } 7.9. Aperfeiçoando a Interface com o Usuário Uma série de melhorias podem ser feitas na interface com o usuário. Uma delas é a criação de uma estrutura de menu de opções, que permita ao usuário escolher qual, dentra as várias operações disponíveis, o usuário deseja executar. Por enquanto podemos oferecer ao usuário duas opções: (1) Inserir um peixe no aquário; e (2) Sair do Programa. A seleção da operação a ser realizada será baseada em números inteiros. Além do mais, poderiamos mostrar mensagens de erro no caso de uma falha de operação, oferecer um pouco mais de informações sobre a origem do programa, além de melhorar a aparência visual do mesmo. A classe Aquario_V7 mostra como estas melhorias podem ser efetuadas. class Aquario_V7 { public static void main(String[] args) { Peixe_V1[] peixes = new Peixe_V1[1000]; int qtdPeixes = 0; do { IO.println("----- Programa Aquario - Menu de Opcoes -----"); IO.println(" 1 - Incluir um Peixe no Aquario -"); IO.println(" 2 - Sair do Programa -"); IO.println("---------------------------------------------"); IO.println("Qual a sua Opção?"); int opcao = IO.ReadInt(); switch (opcao) { case 1 : peixes[qtdPeixes] = criaPeixe(); qtdPeixes++; break; case 2: // opcao de saída do programa break; default: IO.println("Opcao invalida"); } } while (opcao != 2); } public static Peixe criaPeixe() { ... } } 7.10. Informações sobre o Aquário e Outras Operações O programa ainda não manipula informações sobre o aquário. No início deste documento soubemos que é necessário armazenar o nome e o volume em litros de água que o aquário contém. Podemos criar uma nova opção de menu, para armazenar estas informações nas variáveis nome e volume. Outras melhorias que poderiamos fazer neste momento são: implementar a listagem de todos os peixes que estão no aquário; URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 7 implementar a remoção de peixes do aquário. A operação solicita o nome do peixe a ser removido e o retira do aquário. Adicionalmente, todos os peixes que estavam armazenados em qtdPeixes após a qtdPeixes do peixe removido serão armazenados em uma qtdPeixes imediatamente inferior. Por exemplo, se os peixes P1, P2, P3 e P4 estavam respectivamente armazenados nas posicoes 0, 1, 2 e 3 do array de peixes, então após a remoção do peixe P2, os peixes P1, P3 e P4 estarão respectivamente armazenados na qtdPeixes 0, 1 e 2. A posição 3 estará vazia. Por fim, como mais adiante estaremos inserindo vários novas opções no programa vamos mover a opção de saída do programa para a posição 99, e incluir uma mensagem indicando que o programa encerrou. A classe abaixo implementa todas as melhorias discutidas acima. class Aquario_V8 { public static void main(String[] args) { Peixe_V1[] peixes = new Peixe_V1[1000]; int qtdPeixes = 0; String nome; int volume; do { IO.println("----- Programa Aquario - Menu de Opcoes -----"); IO.println(" 1 - Incluir Informações Sobre o Aquario -"); IO.println(" 2 - Incluir um Peixe no Aquario -"); IO.println(" 3 - Listar os Peixes no Aquario -"); IO.println(" 4 - Excluir um Peixe no Aquario -"); IO.println(" 99 - Sair do Programa -"); IO.println("---------------------------------------------"); IO.println("Qual a sua Opção?"); int opcao = IO.ReadInt(); switch (opcao) { case 1 : // 1 - Incluir Informações Sobre o Aquario IO.println("Informe o nome do aquário"); nome = IO.readStr(); IO.println("Informe o volume em litros do aquário"); volume = IO.readStr(); break; case 2 : // 2 - Incluir um Peixe no Aquario peixes[qtdPeixes] = criaPeixe(); qtdPeixes++; break; case 3: // 3 - Listar os Peixes no Aquario IO.println("Aquario: " + nome + " - Volume de Agua: " + volume + " litros "+ " - Quantidade de Peixes: " + qtdPeixes); IO.println("INICIO Listagem de Peixes *********************"); IO.println("#-ESPECIE, NOME, ANO NASC, MES NASC, SEXO"); for (int i = 0; i < qtdPeixes; i++) { Peixe_V1 peixeAtual = peixes[i]; IO.println("#"+i+"-"+ peixe.especie+","+ peixe.nome+","+ peixe.anoNascimento+","+ peixe.mesNascimento+","+ peixe.sexo); } IO.println("FIM Listagem de Peixes *********************"); break; URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 8 case 4 : // 4 - Excluir um Peixe no Aquario IO.println("Informe o nome do peixe a remover"); String nomePeixeProcurado = IO.readStr(); for (int i = 0; i < qtdPeixes; i++) { Peixe_V1 peixeAtual = peixes[i]; String nomePeixeAtual = peixeAtual.nome; if (nomePeixeAtual.equals(nomePeixeProcurado)) { // o peixe a ser removido foi encontrado peixes[i] = null; // remover o peixe procurado // deslocar de uma posição a menos, // todos os peixes que estavam armazenados // nas posicoes acima do peixe removido for (int j = i + 1; j < qtdPeixes; j++) { peixes[j-1] = peixes[j]; } // esvaziar a posição do último peixe deslocado peixes[qtdPeixes-1] = null; // subtrair de um a quantidade de peixes no aquario qtdPeixes = qtdPeixes - 1; break; // sair do laco for } } break; case 99: // opcao de saída do programa break; default: IO.println("Opcao invalida"); } } while (opcao != 99); IO.println("----- Programa Aquario - FIM -----"); IO.println("Obrigado por usar este software!"); } public static Peixe criaPeixe() { ... } } 8. Modularidade Perceba que o programa já começa a ficar muito extenso, o que dificulta a sua legibilidade. Além do mais, a medida em que o programa fica maior e mais complexo, torna-se cada vez mais difícil identificar onde possíveis erros estão localizados. A implementação do software já necessita do uso de técnicas de domínio de complexidade, das quais a mais importante é chamada modularidade. Aplicaremos duas classes técnicas de modularização no programa acima para melhorar sua organização, sem que seja modificada sua funcionalidade: modularização de código e modularização de dados. 8.1 Modularização de Código - 1 Consiste em delimitar dentro de um método muito extenso os trechos de código que fazem tarefas bem definidas, em seguida é criado um método que realiza tal tarefa, e são substituidas as linhas de código no método original por uma chamada ao método criado. Na classe Aquario_V9 é feita a modularização da URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 9 apresentação de menus e saudações. Perceba que na modularização da apresentação de menus, criamos um método que já retorna um inteiro com a opção selecionada. Perceba também que os trechos de código que realizam as operações permanecem intactos, por enquanto. class Aquario_V9 { public static void main(String[] args) { Peixe_V1[] peixes = new Peixe_V1[1000]; int qtdPeixes = 0; String nome; int volume; do { int opcao = mostraMenu(); switch (opcao) { case 1 : // 1 - Incluir Informações Sobre o Aquario IO.println("Informe o nome do aquário"); nome = IO.readStr(); IO.println("Informe o volume em litros do aquário"); volume = IO.readStr(); break; case 2 : // 2 - Incluir um Peixe no Aquario peixes[qtdPeixes] = criaPeixe(); qtdPeixes++; break; case 3: // 3 - Listar os Peixes no Aquario IO.println("Aquario: " + nome + " - Volume de Agua: " + volume + " litros "+ " - Quantidade de Peixes: " + qtdPeixes); IO.println("INICIO Listagem de Peixes *********************"); IO.println("#-ESPECIE, NOME, ANO NASC, MES NASC, SEXO"); for (int i = 0; i < qtdPeixes; i++) { Peixe_V1 peixeAtual = peixes[i]; IO.println("#"+i+"-"+ peixe.especie+","+ peixe.nome+","+ peixe.anoNascimento+","+ peixe.mesNascimento+","+ peixe.sexo); } IO.println("FIM Listagem de Peixes *********************"); break; case 4 : // 4 - Excluir um Peixe no Aquario IO.println("Informe o nome do peixe a remover"); String nomePeixeProcurado = IO.readStr(); for (int i = 0; i < qtdPeixes; i++) { Peixe_V1 peixeAtual = peixes[i]; String nomePeixeAtual = peixeAtual.nome; if (nomePeixeAtual.equals(nomePeixeProcurado)) { // o peixe a ser removido foi encontrado peixes[i] = null; // remover o peixe procurado // deslocar de uma posição a menos, // todos os peixes que estavam armazenados // nas posicoes acima do peixe removido URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 10 for (int j = i + 1; j < qtdPeixes; j++) { peixes[j-1] = peixes[j]; } // esvaziar a posição do último peixe deslocado peixes[qtdPeixes-1] = null; // subtrair de um a quantidade de peixes no aquario qtdPeixes = qtdPeixes - 1; break; // sair do laco for } } break; case 99: // opcao de saída do programa break; default: IO.println("Opcao invalida"); } } while (opcao != 99); mostraSaudacaoFinal(); } private static int mostraMenu() { IO.println("----- Programa Aquario - Menu de Opcoes -----"); IO.println(" 1 - Incluir Informações Sobre o Aquario -"); IO.println(" 2 - Incluir um Peixe no Aquario -"); IO.println(" 3 - Listar os Peixes no Aquario -"); IO.println(" 4 - Excluir um Peixe no Aquario -"); IO.println(" 99 - Sair do Programa -"); IO.println("---------------------------------------------"); IO.println("Qual a sua Opção?"); int opcao = IO.ReadInt(); return opcao; } private static void mostraSaudacaoFinal() { IO.println("----- Programa Aquario - FIM -----"); IO.println("Obrigado por usar este software!"); } public static Peixe criaPeixe() { ... } } 8.2 Modularização de Código - 2 A implementação das operações de menus está bem delimitada dentro da cláusula switch, mas se movessemos de cada um destes trechos de código para dentro de métodos específicos isto tornaria o programa bem mais legível e modular, como mostrado na classe Aquario_V10_com_erro_de_compilacao. O programa abaixo, em vez de contém um método com dezenas de linhas de código, contém vários métodos menores e modulares. Embora tenhamos melhorado a modularidade do mesmo, este apresenta um erro, explicado adiante. O erro decorre do fato de que cada um dos quatro métodos: incluirInfoAquario(), incluirPeixe(), URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 11 e excluirPeixes(), utiliza as variáveis peixes, qtdPeixes, nome e/ou volume, as quais são declaradas dentro do método main, e portanto estão fora do escopo dos outros quatro métodos. Uma solução é proposta na classe Aquario_V11. listarPeixes() class Aquario_V10_com_erro_de_compilacao { public static void main(String[] args) { Peixe_V1[] peixes = new Peixe_V1[1000]; int qtdPeixes = 0; String nome; int volume; do { int opcao = mostraMenu(); switch (opcao) { case 1: incluirInfoAquario(); break; case 2: incluirPeixe(); break; case 3: listarPeixes(); break; case 4: excluirPeixe(); break; case 99: // opcao de saída do programa break; default: IO.println("Opcao invalida"); } } while (opcao != 99); mostraSaudacaoFinal(); } } static void incluirInformacoesAquario() { // 1 - Incluir Informações Sobre o Aquario IO.println("Informe o nome do aquário"); nome = IO.readStr(); IO.println("Informe o volume em litros do aquário"); volume = IO.readStr(); } static void incluirPeixeNoAquario() { peixes[qtdPeixes] = criaPeixe(); qtdPeixes++; } static void listarPeixes() { IO.println("Aquario: " + nome + " - Volume de Agua: " + volume + " litros "+ " - Quantidade de Peixes: " + qtdPeixes); IO.println("INICIO Listagem de Peixes *********************"); IO.println("#-ESPECIE, NOME, ANO NASC, MES NASC, SEXO"); for (int i = 0; i < qtdPeixes; i++) { Peixe_V1 peixeAtual = peixes[i]; IO.println("#"+i+"-"+ URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 12 peixe.especie+","+ peixe.nome+","+ peixe.anoNascimento+","+ peixe.mesNascimento+","+ peixe.sexo); } IO.println("FIM Listagem de Peixes *********************"); } static void excluirPeixe() { IO.println("Informe o nome do peixe a remover"); String nomePeixeProcurado = IO.readStr(); for (int i = 0; i < qtdPeixes; i++) { Peixe_V1 peixeAtual = peixes[i]; String nomePeixeAtual = peixeAtual.nome; if (nomePeixeAtual.equals(nomePeixeProcurado)) { // o peixe a ser removido foi encontrado peixes[i] = null; // remover o peixe procurado // deslocar de uma posição a menos, // todos os peixes que estavam armazenados // nas posicoes acima do peixe removido for (int j = i + 1; j < qtdPeixes; j++) { peixes[j-1] = peixes[j]; } // esvaziar a posição do último peixe deslocado peixes[qtdPeixes-1] = null; // subtrair de um a quantidade de peixes no aquario qtdPeixes = qtdPeixes - 1; break; // sair do laco for } } } private static int mostraMenu() { ... } private static void mostraSaudacaoFinal() { ... } public static Peixe criaPeixe() { ... } } O código da classe Aquario_V11 mostra uma possível solução para corrigir o erro da classe Aquario_V10_com_erro_de_compilacao. A única mudança no código, com relação à versão anterior, foi a re-declaração das variáveis peixes, qtdPeixes, nome e/ou volume, as quais foram retiradas de dentro do método main e movidas para o escopo da classe. O conteúdo dos outros métodos permanece o mesmo, mas é omitido por questões de espaço. class Aquario_V11 { static Peixe_V1[] peixes = new Peixe_V1[1000]; static int qtdPeixes = 0; static String nome; static int volume; URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected]) Modelagem e Implementação de Aquário de Peixes - por Jorge Fernandes - Página 13 public static void main(String[] args) { do { int opcao = mostraMenu(); switch (opcao) { case 1: incluirInfoAquario(); break; case 2: incluirPeixe(); break; case 3: listarPeixes(); break; case 4: excluirPeixe(); break; case 99: // opcao de saída do programa break; default: IO.println("Opcao invalida"); } } while (opcao != 99); mostraSaudacaoFinal(); } static void incluirInformacoesAquario() { ... } static void incluirPeixeNoAquario() { ... } static void listarPeixes() { ... } static void excluirPeixe() { ... } public static Peixe criaPeixe() { ... } } 9. Conclusões Este tutorial introduziu os seguintes conceitos a serem discutidos e amadurecidos: Criação de objetos e entrada de dados via teclado. Armazenamento de objetos em uma estrutura de coleção (array) Uso de menus textuais Modularização de programas através de métodos Última alteração em 20 de agosto de 2002, por Jorge Fernandes URL: http://www.dimap.ufrn.br/~jorge. Copyright (c) 2002, Jorge Fernandes ([email protected])