10 de agosto de 2010

Collections: Estruturas de dados

São tipos de dados compostos, diferentemente dos tipos: int, double, float, entre outros que são tipos de dados primitivos. As estruturas de dados são formas de armazenamento de dados ou objetos.
Por exemplo, os arrays são estruturas de dados lineares e estáticas para armazenar dados, porém com capacidade limitada, ou seja deve-se inicializá-lo com um tamanho. Para aumentar essa capacidade durante a execução da aplicação teria que haver um algoritmo que aumente a capacidade de informações do array.


Código-fonte:
System.out.println("-------------------Arrays-------------------");
 //inicializando array com 3 posições
 String[] array = new String[3];

 //inserindo elementos
 array[0] = "A";
 array[1] = "B";
 array[2] = "C";

 //ou
 // inicializando array com 3 elementos
 String[] array2 = { "A", "B", "C" };

 //percorrendo o array para fazer a listagem dos dados
 for (int i = 0; i < array2.length; i++){
     System.out.println(array2[i]);
 }
Resultado:
-------------------Arrays-------------------
A
B
C

Estruturas de dados Java
As estruturas de dados Java se encontram no pacote java.util. As operações básicas dessas estruturas são: adição, remoção, acesso e pesquisa. Podemos tratar uma estrutura de dados como uma coleção, pois este permite armazenar vários objetos. Os tipos de coleções estudados serão: Listas, Conjuntos e Mapas.
Listas As listas são estruturas de dados dinâmicas. Os elementos são arrumados numa ordem linear, ou seja, os elementos possuem sucessor (com exceção do ultimo elemento) e antecessor (com exceção do primeiro elemento). Alguns tipos de listas são: LIFO  e FIFO Exemplo de lista: java.util.List Pilhas (LIFO): Last in, First out [Ultimo que entra, primeiro que sai] Os elementos de uma pilha são adicionados ao topo e removidos do topo também. Exemplo: java.util.Stack
Código Fonte:
System.out.println("-------------------Pilhas-------------------");
        //criando a pilha
        Stack pilha = new Stack();
        //inserindo valores na pilha
        pilha.push("A");
        pilha.push("B");
        pilha.push("C");
        pilha.push(12.6);
        //pegando o topo da pilha
        System.out.println("Topo: " + pilha.peek());
        //percorrendo a pilha
        for (int i = 0; i < pilha.size(); i++){
            System.out.println(pilha.get(i));
        }
        //removendo um elemento, e por ser uma pilha
        //ele removerá o elemento que foi inserido por ultimo
        pilha.pop();
        System.out.println("Depois de remover um elemento:");
        //percorrendo a pilha novamente
        for (int i = 0; i < pilha.size(); i++){
            System.out.println(pilha.get(i));
        }
Resultado:
-------------------Pilhas-------------------
Topo: 12.6
A
B
C
12.6
Depois de remover um elemento:
A
B
C

Filas (FIFO): First in, First out [Primeiro que entra, primeiro que sai] Os elementos de uma pilha são adicionados ao final da fila e removidos do topo da mesma. Exemplo: java.util.Queue
Código Fonte:
System.out.println("-------------------Filas-------------------");
        //criando a fila, Queue é apenas uma interface,
        //então utilizaremos a implentação LinkedList
        Queue fila = new LinkedList();
        //inserindo elementos na fila
        fila.add("A");
        fila.add("B");
        fila.add("C");
        fila.add(12.6);
        //pegando o topo da fila
        System.out.println("Topo: " + fila.peek());
        //percorrendo a fila, este é outra forma de percorrer uma lista
        //o Object é o tipo do elemento, o obj é o elemento e a fila é nossa lista
        // o obj corresponderia ao get(i) da pilha
        for (Object obj : fila){
            System.out.println(obj);
        }
        //removendo um elemento, e por ser uma fila
        //ele removerá o elemento que foi inserido por primeiro
        fila.remove();
        System.out.println("Depois de remover um elemento:");
        //percorrendo a fila novamente
        for (Object obj : fila) {
            System.out.println(obj);
        }
Resultado:
-------------------Filas-------------------
Topo: A
A
B
C
12.6
Depois de remover um elemento:
B
C
12.6

Para entender melhor o funcionamento de pilha e fila, compare o resultado dos exemplos, pois os dois códigos fazem a mesma coisa, porém de formas diferentes.
Conjuntos
Os conjuntos não permitem que seja inseridos elementos duplicados num mesmo conjunto, e também não tem uma ordem dos elementos como nas listas, assim como os conjuntos matemáticos.
Exemplo: java.util.Set Mapas
Um mapa armazena pares (chave, valor), essa chaves e valores podem ser de qualquer tipo. A chave é utilizada para achar um elemento rapidamente. Um mapa normalmente implementada como “Tabela Hash”. Exemplo: java.util.Map
Tabela Hash
Também chamada de: Tabela de dispersão ou tabela de espalhamento ou tabela hashing. É uma estrutura de dados especial, que associa chaves de pesquisa a valores. O objetivo é, a partir de uma chave simples, fazer uma busca rápida e obter o valor desejado.
Java Collection Framework 
"Desde a versão 1.2 do JDK (depois que o renomearam para Java 2 SDK), a plataforma J2SE inclui um framework de coleções (a Collections Framework). Uma coleção é um objeto que representa um grupo de objetos. Um framework de coleções é uma arquitetura unificada para representação e manipulação de coleções, permitindo que elas sejam manipuladas independentemente dos detalhes de sua implementação."
Mais informações sobre o framework: http://javafree.uol.com.br/artigo/847654/
Estrutura do framework:



Collection: Interface base para todos os tipos de coleções.
Set: Contém apenas os métodos herdados de Collection e adiciona a restrição de que elementos duplicados não são permitidos.
Exemplo:java.util.Set
Codigo-fonte:
System.out.println("---------------Collection----------------");
       System.out.println("-------------------Set-------------------");
       //criando um set, como Set é interface, vamos utilizar a implementação HashSet
       Set< String > set = new HashSet< String >();
       //inserindo elementos
       set.add("A");
       set.add("B");
       set.add("C");
       set.add("A");
       //removendo elemento "C"
       set.remove("C");
       //percorrendo a coleção
       for (String obj : set){
           System.out.println(obj);
       }
Resultado:
---------------Collection----------------
-------------------Set-------------------
A
B

SortedSet:Usaremos implementações de SortedSet para situações onde desejarmos ordenar os elementos.
Exemplo: java.util.SortedSet
Codigo-fonte:
System.out.println("-------------------SortedSet-------------------");
       //criando um set ordenado, como SortedSet é interface, vamos utilizar a implementação TreeSet
       SortedSet< String > setOrdenado = new TreeSet< String >();
       //inserindo elementos
       setOrdenado.add("B");
       setOrdenado.add("A");
       setOrdenado.add("C");
       setOrdenado.add("A");
       //percorrendo o conjunto
       for (String obj : setOrdenado){
           System.out.println(obj);
       }
Resultado:
-------------------SortedSet-------------------
A
B
C


List: É uma coleção ordenada que pode conter valores duplicados. Além disso, temos controle total sobre a posição onde se encontra cada elemento de nossa coleção, podendo acessar cada um deles pelo índice.
Exemplo:java.util.List Codigo-fonte:
System.out.println("-------------------List-------------------");
       //criando um list, como List é interface, vamos utilizar a implementação ArrayList
       List< String > list = new ArrayList< String >();
       //inserindo elementos na lista
       list.add("A");
       list.add("C");
       list.add("E");
       //perconrrendo a lista
       System.out.println("Lista Atual");
       for (String obj: list){
           System.out.println(obj);
       }
       //inserindo um elemento numa determinada posição da lista
       list.add(1, "B");
       //perconrrendo a lista
       System.out.println("Lista com novo elemento");
       for (String obj: list){
           System.out.println(obj);
       }
       //substituindo o elemendo de uma determinada posição
       list.set(3, "D");
       //perconrrendo a lista
       System.out.println("Lista com elemento substituido");
       for (String obj: list){
           System.out.println(obj);
       }
Resultado:
-------------------List-------------------
Lista Atual
A
C
E
Lista com novo elemento
A
B
C
E
Lista com elemento substituido
A
B
C
D


Queue: Normalmente utilizamos esta interface quando queremos uma coleção do tipo fila (FIFO).
Exemplo: java.util.Queue Codigo-fonte e resultado já apresentado em Filas.


Map: Map não é uma Collection pois uma Collection não trabalha com chaves. Utilizada em relações de chave-valor entre os elementos. Cada chave pode conter apenas um único valor associado.
Exemplo: java.util.Map
Codigo-fonte:
System.out.println("-------------------Map-------------------");
       //criando um mapa, Map é interface, HashMap é a implementação
       Map< String, String > mapa = new HashMap< String, String >();
       //inserindo elementos no mapa: ex: a -> chave ; Letra A -> valor
       mapa.put("a", "Letra A");
       mapa.put("b", "Letra B");
       mapa.put("c", "Letra C");
       //removendo pela chave
       mapa.remove("a");
       //listando os elementos do mapa
       System.out.println("Listagem: " + mapa);
       //pegando um valor a partir do mapa
       System.out.println("Pegar a partir chave b: " + mapa.get("b"));
Resultado:
-------------------Map-------------------
Listagem: {b=Letra B, c=Letra C}
Pegar a partir chave b: Letra B


SortedMap: Usaremos SortedMap para situações onde desejarmos ordenar os elementos, esses elementos são ordenados pela chave e não pelo valor.
Exemplo: java.util.SortedMap
Codigo-fonte:
System.out.println("-------------------SortedMap-------------------");
       //criando um mapa ordenado
       SortedMap< String, String > mapaOrdenado = new TreeMap< String, String >();
       //inserindo elementos no mapa
       mapaOrdenado.put ("um", "11111");
       mapaOrdenado.put ("dois", "222222");
       mapaOrdenado.put ("tres", "33333");
       //listando os elementos do mapa
       System.out.println ("Listando: " + mapaOrdenado);
       //como a chave é uma String, a ordenação da mesma será por ordem alfabética
Resultado:
-------------------SortedMap-------------------
Listando: {dois=222222, tres=33333, um=11111}


Obs: para executar os exemplos, crie uma classe com um método main e para executar no Netbeans utilize : Shift + F6
Exemplo:
public class Collections {

    public static void main(String[] args) {
        //Código-fonte aqui.!
    }
}
Referências: http://www.dsc.ufcg.edu.br/~jacques/cursos/p2/html/ed/colecoes.htm http://download.oracle.com/javase/tutorial/collections/index.html

5 de agosto de 2010

UML: Trabalhando com a diagramação

Dado o seguinte cenário:
"Um grande hotel dispõe de apartamentos para os seus hóspedes. Cada aposento tem seu valor e um numero para identificação. Ao ser feito a hospedagem, caso o hóspede não esteja cadastrado, o mesmo deve ser realizado. Na hospedagem devem constar dados como: data de entrada e data de saída, além de que a hospedagem pode ter mais de um aposento. Uma hospedagem tem uma conta, é nela que deve constar o valor. O hóspede também pode solicitar serviço de quarto (refeições entregues em seu aposento) ou consumir alimentos e bebidas no restaurante do hotel. Em ambos os casos, o registro é feito pelo funcionário diretamente na conta da hospedagem, sendo assim em uma conta pode haver mais de um registro de consumo. Na ocasião da saída do hóspede, é feito o fechamento da conta, no fechamento deve apresentar todos os gastos de consumo do hóspede. Não será necessário a implementação do pagamento. "

A partir do cenário dado geramos o seguinte diagrama de casos de uso:


E também o seguinte diagrama de classes:


No NetBeans vamos criar um novo projeto do tipo Aplicativo Java com o nome de Hotel.
Dentro do projeto encontramos os Pacotes de código-fonte, dentro deste iremos criar um novo pacote chamado model, onde ficarão nossas classes de modelo. Essa classes devem ser implementadas apenas com os atributos, getters e setters, de acordo com o diagrama de classes.

A estrutura final do projeto será a seguinte:


1 de agosto de 2010

Análise: Conceitos de documentação de sistemas

Análise de Requisitos
“a análise de requisitos está associada ao processo de descobrir quais são as operações que o sistema deve realizar e quais são as restrições que existem sobre elas”. (WAZLAWICK, 2004)
Esta é a fase em que o analista senta com o cliente para fazer o levantamento das funcionalidades do sistema e as restrições que existe sobre elas.
Exemplos:
Requisito funcional: “O sistema deve permitir a inserção, alteração e a remoção de produtos”
Requisito não funcional: “a base de dados deve ser protegida para acesso apenas de usuários autorizados” ou “o tempo de resposta do sistema não deve ultrapassar 30 segundos”.

Casos de uso
“os grandes processos de negócios da empresa são também chamados de casos de uso. Eles devem cobrir as principais atividades da empresa ligadas ao sistema que será implementado”. (WAZLAWICK, 2004)
Os casos de uso são definidos a partir do levantamento dos requisitos funcionais, por exemplo, seguindo o exemplo de requisito funciona, podemos dizer que o caso de uso para aquele requisito seria “manter produtos”, quando se diz “manter” refere-se as funções de inserir, alterar e remover, este caso de uso poderia ser separado em três outros casos de uso: “inserir produtos”, “alterar produtos” e “remover produtos”, assim o caso de uso “manter produtos” não existiria, isso depende do ponto de vista de quem vai fazer esse levantamento.

Orientação a Objetos
Trata-se de um paradigma de análise, projeto e programação de softwares baseados na composição e interação entre objetos.
Alguns conceitos da orientação a objetos:
Classe: exemplo usado para criar um objeto
Objeto: instância de uma classe
Atributos: características de um objeto
Métodos: definem as habilidades do objeto

Análise Orientada a Objetos
Esta trata-se de definir classes(objetos) a partir da análise de requisitos e identificar os atributos e operações para cada objeto.

UML
A UML trata-se de uma Linguagem Unificada de Modelagem, uma linguagem gráfica para: visualizar, especificar, construir e documentar o desenvolvimento completo de um sistema. A UML não é uma metodologia de desenvolvimento, isso significa que ela não diz para você o que fazer primeiro e em seguida ou como projetar seu sistema, mas ela a auxilia na visualização do sistema como um todo.

Alguns diagramas da UML

Diagrama de casos de uso
É a forma de representar visualmente os casos de uso com seus respectivos atores - podemos identificá-los como os usuários do sistema - levantados na análise de requisitos.

Diagrama de classes
Consideraremos a imagem acima como um sistema de venda qualquer.
Este diagrama representa visualmente as classes definidas na análise orientada a objetos.

Diagramas de atividades


Considere que o caso de uso utilizado seja “inserir funcionário”, a imagem representa as atividades de inserção de um funcionário, porém de forma bem simples, poderia ter validações de campos obrigatórios antes de inserir, isso depende do que o sistema realmente terá que fazer. Este diagrama trata a representação das atividades consideradas num determinado caso de uso, seria praticamente um passo a passo de como o caso de uso deve funcionar.

Observações: essas são formas básicas de documentação de sistemas, o que foi apresentado são apenas introduções, por exemplo: existem mais diagramas de UML, a análise de requisitos pode ser expandida, entre outras formas.


Lembrando... que toda essa fase de análise não é completamente finalizada para iniciar o sistema, praticamente ela finalizará juntamente com o sistema, pois todos os dados levantados acima serão sempre atualizados de acordo com o que o cliente deseja. Não se consegue capturar tudo o que o cliente quer logo nas primeiras conversas, novas funcionalidades poderão surgir no andamento do projeto.


Ok... mas porque fazer tudo isso antes de começar um sistema, porque não começar o sistema de uma vez?
Bom... essa é uma forma de facilitar a comunicação entre uma equipe, entender melhor o problema, dividir a complexidade do mesmo além de ajudar a redimensionar recursos e prazos adequadamente.

Mas, toda essa parte de projeto deve facilitar o entendimento de uma determinada situação, se o mesmo for tão complexo quanto ao que está sendo projetado, o seu uso perde o sentido. Então, não há porque seguir exatamente os diagramas da UML, simplificar os estes de forma que você possa entender, ajuda no projeto.


Além de toda essa documentação de projeto, há também a documentação de código-fonte. No caso de documentar a API dos programas em Java, a Sun Microsystem criou um gerador de documentação que gera o mesmo a partir do código-fonte, o resultado é expresso em HTML.

Exemplo:

Comentário durante a geração do código-fonte:


Resultado do método em HTML:


Observações: existem outras tags do JavaDoc para documentação, no caso do exemplo só apresentamos @param e @return.

Outra forma de documentação bem interessante é a prototipação, que trata de criar as telas do sistema, antes de começar o desenvolvimento do mesmo. Assim é possível apresentar ao cliente como ficaria as telas do sistema, de forma rápida e sem implementação de códigos-fonte. O Pencil é um software que permite que essas telas sejam criadas, segue o link: http://pencil.evolus.vn/en-US/Downloads/Application.aspx


Quanto a criação de diagramas tem um site que é gratuito e que permite a criação destes: https://creately.com/


Referência sobre análise de sistemas orientados a objetos


WAZLAWICK, Raul Sidnei. Análise e projeto de sistemas de informação orientados a objetos. Rio de Janeiro: Elsevier, 2004.