1 Introdução

Propaganda
Tópicos Avançados de Orientação a
Objetos
Sumário –
1
Introdução
O objeto da disciplina Tópicos Avançados de Orientação a Objetos é explorar técnicas de
design avançado em orientação a objetos, como o uso de Componentes e Design Patterns.
Também são exploradas novas tecnologias e metodologias empregadas no
desenvolvimento de aplicações OO, como Web services e XP Programming.
Opcionalmente recursos avançados de programação OO, como multithreading e
collections, são também abordados. Como um requerimento do design avançado de
aplicações OO, a linguagem UML é revista com ênfase
2
Paradigma de OO
A medida que as aplicações tornaram-se mais complexas as linguagens de programação
tradicionais mostraram-se insuficientes para modelar situações cada vez mais complexas
(estruturas de dados, tipos de novos etc.). A orientação a objeto aparece então como um
poderoso instrumento de modelagem em que qualquer entidade, como um cliente, uma
conta ou estruturas de dados como uma pilha ou um grafo, podem ser representados em
termos do nome da entidade, suas propriedades e seus comportamentos. Esse é o
paradigma da orientação a objeto.
As linguagens que suportam esse paradigma [1], como SmallTalk, C++ e Java, trazem
uma série de características comuns como:
Encapsulamento do objeto,
Herança,
Polimorfismo,
Definição de tipos do usuário,
Comunicação dos objetos através de mensagens,
Essas características dão às linguagens de programação OO (LPOO) um forte potencial
para o reaproveitamento de código (pense por exemplo nos recursos de herança e
polimorfismo) e o desenho de soluções robustas (pense por exemplo nos recursos de
encapsulamento e herança). A possibilidade de reuso de código e de soluções robustas
(menor manutenção de código) está diretamente ligada a redução no custo do
desenvolvimento de aplicações. Isso pode ser refletido na forma de redução de prazos e
custos de desenvolvimento ou no aumento da qualidade das aplicações.
[1] Existem muitos outros paradigmas de linguagens como as linguagens funcionais
(LISP).
Curva de aprendizado OO e aplicações mais complexas
O uso de linguagens OO, entretanto, não trouxe em um primeiro momento (entenda-se
anos 80) uma redução no custo das aplicações. Destacam-se dois fatores:
1. As linguagem OO apresentam uma curva de aprendizado bastante maior que o das
linguagens procedurais comuns (Pascal, Cobol, C etc.) limitando os benefícios da LPOO
à capacidade do programador ou projetistas utilizar os seus recursos.
2. À medida que as LPOO foram sendo introduzidas as aplicações também tornaram-se
mais complexas (em boa parte viabilizado pela OO) com interfaces mais sofisticadas ao
usuário (interfaces gráficas, web etc.) e tipos de dados novos (imagens, XML, sons etc.).
Com isso a redução do custo é minimizada: o custo da linha de código é menor, mas
passamos a criar mais linhas de código.
Exercícios
1. Relacione e explique as vantagens de LPOO. Alguma desvantagem com relação a
linguagens procedurais tradicionais como Pascal e C?
2. Por que SmallTalk é considerada uma linguagem puramente orientada a objetos?
3. O desenvolvimento de aplicações OO é mais complexo. Justifique.
3
Desenvolvimento de aplicações corporativas
O desenvolvimento de aplicações corporativas requer produtividade (menores custos e
maior qualidade). Essa produtividade buscada em termos de:
Menor tempo de desenvolvimento
Menor quantidade de recursos
Aplicações de fácil manutenção
Aplicações fáceis de testar
Aplicações com menor quantidade de linhas de código
Aplicações tolerantes a falha (um aspecto de qualidade)
etc.
Existem também uma série de aspectos que permitem prover soluções de forma produtiva
em uma empresa:
Reuso de aplicações e código previamente existente
Interoperabilidade entre diferentes plataformas (hardware e software)
Suporte a transações
etc.
O uso de uma LPOO [1] não é suficiente para garantir a maior parte dessas características
no desenvolvimento de aplicações corporativas. Às primeiras vamos chamar de
características do projeto OO e as demais de requerimentos não-funcionais (termos
empregados aqui livremente apenas para facilitar a exposição).
[1] Isso não é nenhum demérito para as LPOO. Muitos desses objetivos são objetivos
secundários de uma linguagem e devem ser atingidos por outros meios.
Aplicações corporativas e OO
Como obter boas características de projeto e atender requerimentos não-funcionais no
desenvolvimento de aplicações com LPOO? A idéia é que produzir aplicações
corporativas requer mais que uma linguagem de programação. O desenvolvimento de
uma aplicação corporativa é um projeto complexo, com diversas fases (levantamento,
design, codificação, testes etc.), e uma linguagem de programação tem influência
limitada no resultado de todas essas fases. Vejamos somente o da fase de codificação.
Codificação e IDE’s
IDE é a sigla de Integrated Development Environment. São exemplos de IDE o Visual
Studio da Microsoft, o Eclipse para Java e o JBuilder da Borland. Embora possamos
desenvolver uma aplicação em Java ou C++ empregando apenas um simples editor de
texto como o notepad e um compilador, esses ambientes fornecem uma série de
facilidades para o desenvolvimento de código de forma profissional:
Editor com recursos específicos para linguagem
Identação de código
Help de sintaxe
Numeração de linhas
Avanço e retrocesso de alterações
Organização do código (classes, interfaces etc.)
etc.
Ferramentas para buscas e comparação de fontes
Árvore de objetos (“Explorer”)
Compilador
Sinalização das linhas com erro
Organização dos objetos para compilação (ordem, agrupamentos etc. “makefile”)
Geração de código para deploy de aplicações
Geração de componentes (stub, proxy e skeleton files)
Ferramentas para depuração
Ferramentas de documentação
Poderosos contrutores de interface gráficas (“GUI Builder”)
Além de integração com inúmeros plugins:
Interfaces de acesso a bancos de dados
Ferramentas de design de código (como ferramentas para UML)
Geradores de código
Ferramentas de refatoração de código
Ferramentas de versionamento de fontes
De todos esses recursos basta pensarmos nos contrutores de interface gráficas (“GUI
Builder”) para vermos o quanto a produtividade, e estamos falando somente da fase de
codificação, dependente de muitos outros recursos além da linguagem empregada
(imagine-se programando um único elemento gráfico como um botão de ”OK” em uma
linguagem como C++ ou Java sem o uso de um IDE).
Produzindo aplicações OO com produtividade
Concluímos então que para produzirmos aplicações OO com produtividade precisamos
empregar uma série de técnicas e recursos que garantam as qualidades da LPOO e que
ainda expandam seus benefícios. Aqui, selecionamos algumas dessas técnicas e recursos
que parecem ser importantes para o desenvolvimento produtivo de aplicações e valem ser
exploradas em maior detalhe:
Design avançado
A garantia de qualidades como reusabilidade e extensibilidade das LPOO dependem
muito mais das técnicas de análise e definição do projeto (design) que das linguagens ou
ferramentas que são empregadas. De fato, sob esses aspectos as linguagens e ferramentas
em geral oferecem recursos muito semelhantes ente si. Técnicas avançadas de design
incluem uso extensivo da UML (a linguagem padrão para o design de aplicações OO);
técnicas e boas práticas para definição das soluções do projeto: que entidades formarão
classes? Que tipo de relacionamento melhor expressa uma situação problema? Quando
empregar uma técnica de delegação de classes? Essas são algumas perguntas que fazem
parte do que podemos chamar uma metodologia de design; por último encontramos
algumas técnicas mais avançadas que visam oferecer boas soluções de design como os
Padrões de Projeto (Design Patterns).
Metodologias de desenvolvimento
Metodologias tradicionais de desenvolvimento como a análise estruturada ou a análise
funcional nem sempre trazem os melhores resultados no desenvolvimento de aplicações
OO. De fato, metodologias tradicionais partem, em geral, de modelos de dados (como o
modelo entidade-relacionamento) levando a soluções fortemente centradas a dados.
Recentemente diversas metodologias vêm surgindo em resposta à necessidade do rápido
desenvolvimento de aplicações OO. Algumas metodologias envolvem diretamente o
design da aplicação e ferramentas, como a programação orientada a aspectos, outras
podem envolver a prática do desenvolvimento colaborativo, como a prática do
Extremming Programming (XP Programming).
Distribuição e interoperabilidade de objetos
Um objeto em C++ ou Java é um objeto instanciado na memória de uma única instância
de processamento (um computador) e, na ausência de recursos adicionais, somente pode
ser compartilhado por programas e objetos que residam na mesma máquina e baseados na
mesma linguagem. Isso é uma forte limitação no desenvolvimento de soluções de
software uma vez que muitas vezes encontramos código pronto para solução de
problemas mas que pode, entretanto, estar desenvolvido em um linguagem diferente e
executar sistemas diferentes do resto da solução. A isso denominamos interoperabilidade.
Outra necessidade é a de as aplicações (e portanto os objetos) serem distribuídas.
Soluções genericamente chamadas de componentes endereçam tanto a interoperabilidade
como a distribuição de objeto e vem sendo oferecidas pelos principais plataformas de
aplicações como o J2EE e .Net.
Outros recursos
Os itens acima não esgotam o conjunto de recursos empregados no desenvolvimento
produtivo de aplicações pelas empresas, mas parecem ser aqueles que mais exploram
aspectos suficientemente gerais para serem estudados. Outras necessidades são por
exemplo o versionamento de código, soluções para o deployment das aplicações e
soluções para a persistência de objetos.
Exercícios
1. O que é refatoração?
2. Procure identificar as facilidades indicadas para os IDE’s em algum IDE que você
utilize.
3. Procure justificar a necessidade ferramentas de versionamento de código no
desenvolvimento de aplicações corporativas.
4. Das técnicas que você conhece para o desenvolvimento de aplicações cite aquelas que
você acha inadequadas no desenvolvimento OO e explique por que.
5. Cite as vantagens de termos objetos distribuídos nas aplicações.
6. Cite soluções encontradas para a persistência de objetos.
4
Modelagem
(ver [Booch, 1999] capítulo 1)
A base de um projeto (design) de aplicação é a modelagem. A modelagem é uma
simplificação da realidade e os modelos possibilitam entendermos melhor as aplicações
que desenvolvemos [1]. Construímos modelos sempre que um sistema é bastante
complexo que não possa ser inteiramente compreendido como um todo. Podemos
entender a modelagem como uma estratégia de redução da complexidade que divide um
problema que não pode ser tratado como um único todo.
Objetivos da modelagem
1. Ajuda a visualizar um sistema existente ou que queremos construir.
2. Permitem especificar a estrutura e o comportamento de um sistema.
3. Fornecem uma guia para a construção das aplicações.
4. Documentam as decisões de projeto.
Princípios de modelagem
1. A tipo de modelo empregado tem uma forte influência em como o problema é tratado e
na forma da solução (um modelo de dados leva a soluções centradas em dados!).
2. Todo modelo pode ser expresso com diferentes níveis de precisão ou detalhamento.
3. Os melhores modelos são conectados a realidade.
4. Nenhum único modelo é completamente suficiente. Qualquer sistema não trivial é
melhor representado através de um pequeno conjunto de modelos mais ou menos
independentes.
Modelagem OO
A modelagem ou o projeto de aplicações OO tem os mesmos objetivos e segue os
mesmos princípios acima, gerais para qualquer modelagem. Devemos ter em mente, pelo
primeiro princípio, que o modelo OO deve levar a soluções diferentes de uma solução,
por exemplo, orientada a dados. Por exemplo, o encapsulamento, é uma característica que
deve ser mais presente em aplicações com origem em modelos OO.
Exercícios
1. Considere o modelo [velocidade_final = velocidade_inicial + aceleração * tempo].
Você reconhece neste modelo os princípios da modelagem?
2. Identifique no modelo ER (Entidade-Relacionamento) os objetivos e os princípios da
modelagem.
3. Cite características que são mais enfatizadas em aplicações que tem origem em
modelos de dados (modelo ER e relacional) e modelos OO.
4. O modelo ER e relacional são modelos diferentes? Explique.
5. Relacione ao menos 3 benefícios da modelagem de aplicações.
[1] O desenho de aplicações é uma modelagem no domínio da solução, o que difere do
domínio do problema.
5
UML, Introdução
(ver [Booch, 1999] capítulo 2)
O propósito da UML (Unified Modeling Language) é o de:
Visualizar
Especificar
Construir
Documentar
versões etc.
Apresenta graficamente os elementos da aplicação
Define a estrutura o comportamento dos elementos da aplicação
Fornece uma guia para análise e codificação das aplicações
Documenta requerimentos, arquitetura, código, testes, protótipos,
Para sistemas orientados a objeto, sendo empregada principalmente em sistemas
intensivos em software [1].
Building Block, “Lego”
A UML é uma linguagem constituída de elementos básicos que podem, por sua vez,
serem combinados de modo a formar novos elementos. Esses building blocks podem ser
de 3 tipos: Elementos, Relacionamentos e Diagramas.
Elementos
Estruturais
componentes, nós
Comportamentais
Elementos de agrupamento
Elementos de anotação
Classes, interfaces, colaborações, casos de uso,
Mensagens, estados de objetos
Pacotes
Notas
Relacionamentos
Dependência
(<<include>>, <<extend>>~, <<import>> são alguns
estereótipos de dependência)
Associação
(composição, agregação e associações com navegabilidade
são casos especiais)
Generalização
(o termo empregado para herança e especializações na
UML)
Realização
(empregado especialmente na realização de interfaces)
Diagramas
Diagrama de classes
Diagrama de Objetos
(Diagramas de Interação)
Diagramas de Seqüência
Diagramas de Colaboração
Diagramas de Estado
Diagramas de Atividades
Diagramas de Componentes
Diagramas de Distribuição
Níveis e diferentes visões dos diagramas
Dependendo do nível de detalhe os diagramas da UML podem ser: Conceituais, de
Especificação (Desenho) ou de Implementação (Codificação). Por oferecer diferentes
visões de um mesmo sistema a UML apresenta uma visão Ortogonal das aplicações.
Ciclo de vida de desenvolvimento de software
A UML é independente do ciclo de vida de desenvolvimento de software empregado.
Entretanto a UML se beneficia de métodos de desenvolvimento:
Direcionados pelos Casos de Uso
Centrados na arquitetura
Interativos e Incrementais
Não sendo de forma alguma um processo seqüencial e linear de desenvolvimento (ver
figura abaixo).
Exercícios
1. Identifique os diagramas Estruturais, Comportamentais e de Arquitetura da UML.
2. Dê exemplos de classes com diferentes níveis de detalhe e que correspondam a
modelos Conceituais, de Especificação (Desenho) ou de Implementação (Codificação).
3. Defina e explique o aspecto ortogonal da UML.
4. Quais as 5 visões oferecidas pela UML em um projeto de software?
R. Visão do caso de uso; visão de desenho (design ou projeto); de processo; de
implementação; e de distribuição (deployment).
5. Explique a frase sobre o ciclo de vida de desenvolvimento de software empregado com
a UML: “Não sendo de forma alguma um processo seqüencial e linear de
desenvolvimento”.
6. Explique como a fase de teste (“Test”) no ciclo de vida pode ocorrer na fase de
elaboração de um projeto.
6
UML, Hello World!
(ver [Booch, 1999] capítulo 3)
Os diagramas UML embora possam ser empregados para modelagem de classes de dados
têm o propósito de modelarem classes mais genéricas. Chamaremos essas classes de
classes programa.
Import java.awt.Graphics;
Class HelloWorld extends java.applet.Applet {
Public void paint (Graphics g) {
g.drawString(“Hello, World!”, 10, 10);
}
}
Exercícios
1. Identifique na classe HelloWorld métodos (declarados e empregados); herança; objetos
e parâmetros.
2. Aplicações em Java podem ser de 2 tipos: aplicativos e applets. Diferencie esses dois
tipos de aplicações Java.
7
UML, Casos de Uso
(ver [Booch, 1999] capítulo 16)
Geral
Casos de Uso
Atores
Caso de uso
Relacionamentos
dependência; generalização;
Dependência
Diagramas estruturais
Agentes externos ao sistema
Representam um funcionalidade autocontida
Associações Atores-Casos de Uso;
Estereótipos: <<include>>; <<extend>>
Fluxo de Eventos
Para cada caso de uso do diagrama deve haver uma descrição textual com os seguintes
elementos:
Nome do caso de uso
Atores participantes
Condições de entrada
(Condições que precisam ser satisfeitas antes do
caso de uso ser iniciado)
Fluxo de eventos principais
Fluxo de eventos secundários
Condições de saída
(Condições que precisam ser satisfeitas
depois do caso de uso estar completado)
Requerimentos especiais
Cenários
Os cenários são instâncias de casos de uso e devem ser empregados quantos cenários
forem necessários para que se complemente a descrição dos casos de uso. Alguns tipos de
cenários úteis:
Cenários “As-is”
Cenários futuros
Cenários para avaliação
Cenários para treinamento
Requerimentos não funcionais
Os requerimentos não funcionais, como considerações de performance e de segurança do
sistema, não são exatamente parte dos diagramas UML mas devem fazer parte do
levantamento e da descrição de qualquer sistema (ver exercício abaixo).
Boas práticas
Identificando Atores:
Identifique grupos de usuários: a) suportados pelo sistema em seu trabalho; b)
grupos que executam as principais funções do sistema e funções secundárias; c)
interações do sistema com agentes externos de hardware ou software.
Identificando Cenários:
Identifique grupos de usuários que criam, modificam, acessam e removem os
dados.
Identifique as tarefas que cada grupo de usuários deseja executar.
Identifique a frequencia e a validade das informações dadas e fornecidas pelo
sistema.
Identificando Casos de Uso:
Lembre-se os casos de uso são estruturais e, portanto, descrevem grandes
estruturas ou partes do sistema.
Na descrição, seja dos diagramas, fluxo de eventos ou cenários, deve-se empregar
sempre a linguagem do usuário.
Exercícios
1. Forneça uma lista de ao menos 10 possíveis requerimentos não funcionais de sistemas.
2. Diferencie e dê exemplo das dependências do tipo <<include>> e <<extend>> em
casos de uso.
3. Casos de uso devem fazer uso da linguagem do usuário. Justifique.
4. Os cenários são sempre construídos antes da criação dos diagramas de casos de uso.
Justifique.
5. Não existe nenhum sentido de fluxo ou sequencia nos diagramas de casos de uso.
Justifique.
6. Os diagramas de casos de uso substituem o diagrama de contexto de outras práticas de
modelagem. Justifique.
8
UML, Diagramas de classe
(ver [Booch, 1999] capítulos 8, 9, 10)
Uma classe simples
Uma classe simples em Java com um a único atributo e uma única operação.
public class Employee {
private int empID;
public double calcSalary(){
... }
}
Atributos
[visibilidade] nome [multiplicidade] [:tipo] [=valor inicial] [{outras propriedades}]
+ public
[0..5]
*item
frozen
# protected
int
changeable
- private
String
addOnly
O atributo ainda pode ser sublinhado para indicar escopo de classe no lugar de escopo de
instância.
Operações
[visibilidade] nome [ (lista de parâmetros) ] [: tipo de retorno ] [{outras propriedades}]
isQuery
sequential
concurrent
(lista de parâmetros) := [direção] nome : tipo [=valor inicial]
in
out
inout
Principais relacionamentos
Dependência
public class Employee {
public void calcSalary(Calculator c) {
...
}
}
Associação simples e navegabilidade
public class Employee {
private TimeCard _tc[];
public void maintainTimeCard() {
...
}
}
Agregação
public class Employee {
private EmpType et[];
public EmpType getEmpType() {
...
}
}
Composição
public class Employee {
private TimeCard tc[];
public void maintainTimeCard() {
...
}
}
Generalização
public abstract class Employee { }
public class Professor extends Employee { }
Realização
public interface CollegePerson { }
public class Professor implements CollegePerson { }
Um exemplo completo
Diagrama de Objetos
Diagrama de Objetos correspondente ao Diagrama de Classes do exercício 1.
:TreeMap
topNode
:TreeMapNode
- itsKey = "Martin"
nodes[LESS]
nodes[GREATER]
:TreeMapNode
:TreeMapNode
- itsKey = "Bob"
- itsKey = "Robin"
nodes[LESS]
nodes[GREATER]
nodes[LESS]
:TreeMapNode
:TreeMapNode
:TreeMapNode
:TreeMapNode
- itsKey = "Alan"
- itsKey = "Don"
- itsKey = "Paul"
- itsKey = "Sam"
nodes[GREATER]
Abbott`s Rules
As regras abaixo são heurísticas bastante simples que podem ser empregadas para modelagem de aplicações OO à partir dos discursos que a
descrevem.
Parte do discurso
Substantivos próprios
Substantivos comuns
Verbos com sentido de
Fazer
Ser
Ter
Obrigação
Adjetivo, adjetivados
Componente do modelo
Objeto
Classe
Exemplos
Anna, Shell
Aluno, Empresa, Funcionário
Operação
Generalização
Agregação
“Constraints”
Atributo
Cria, submete, seleciona
É um tipo de, é outro, é um
Tem, consiste de, inclui
Deve, precisa
Descrição do incidente, nota do aluno, custo da ação
Boas práticas
Tenha foco na estrutura do sistema.
Foque em um aspecto estrutural do sistema, empregando mais de um diagrama se for necessário descrever mais que um aspecto.
Represente somente elementos que são essenciais para descrever um aspecto.
Isto é especifique somente os aspectos que você deseja que sejam garantidos na aplicação.
Empregue nomes que comuniquem seu propósito.
Tente não mostrar muitos relacionamentos. Em geral existem relacionamentos predominantes.
Organize conjuntos de classes em pacotes.
Exercícios
2
TreeMap
+ add(key, value)
+ get(key)
topNode
nodes
TreeMapNode
+ add(key, value)
+ find(key)
itsKey
«interface»
Comparable
itsValue
Object
1. Considere o diagrama de classes acima. Codifique as respectivas classes Java.
public class TreeMap {
TreeMapNode topNode = null;
public void add(Comparable key, Object value) {…}
public Object get(Comparable key) {…}
}
class TreeMapNode {
private Comparable itsKey;
private Object itsValue;
private TreeMapNode nodes[] = new TreeMapNode[2];
public TreeMapNode(Comparable key, Object value) {…}
public Object find(Comparable key) {…}
public void add(Comparable key, Object value) {…}
}
2. Além dos compartimentos para nome, atributos e operações, existe ainda um quarto compartimento para a representação de classes. Justifique.
O quarto compartimento é empregado para descrevermos a responsabilidade da classe.
3. O que são e para que são empregados os cartões CRC?
4. Construa e codifique uma classe associativa e as classes relacionadas.
5. Defina e diferencie associações do tipo agregação e composição.
6. Crie exemplos de associações com diferentes multiplicidades e navegabilidades codificando as respectivas classes.
9
UML, Diagramas de Interação
(ver [Booch, 1999] capítulos 18, 27)
São diagramas que descrevem o comportamento de um sistema, seu comportamento ” inter-classes”. São de dois tipos: os diagramas de
sequência que privilegiam a ordem cronológica em que ocorrem as mensagens e eventos do sistema; e os diagramas de colaboração, que
privilegiam a representação da estrutura de classes que colaboram na execução de um dada tarefa (responsabilidade).
Diagramas de Seqüência
Diagramas de Colaboração
Boas práticas
A construção de diagramas de colaboração pode partir da organização já representada no diagrama de classes.
Represente somente elementos que são essenciais para descrever um aspecto.
Isto é especifique somente os aspectos que você deseja que sejam garantidos na aplicação.
Exercícios
1. Converta o diagrama Sequência dado acima para um diagrama de Colaboração.
2. Converta o diagrama Colaboração dado acima para um diagrama de Sequência.
3. Podem aparecer mais de um objeto da mesma classe em um diagrama de Sequência? Justifique.
4. Para cada um dos diagramas dados construa o correspondente diagrama de classes. Comece identificando os métodos de cada classe e a
navegabilidade.
5. Diagramas de seqüência ou de colaboração podem exibir mensagens simultâneas como as que ocorrem em processos paralelos (como
processos multithreading)? Justifique sua resposta.
6. A ativação de objeto pode ocorrer mais que uma vez em um diagrama de seqüência? Justifique.
7. As mensagens em um diagrama de seqüência são mensagens síncronas, mensagens assíncronas são representadas por setas com a terminação
parcial. Explique o que são mensagens síncronas e assíncronas.
10
UML, Diagramas de Estado
(ver [Booch, 1999] capítulos 21, 24)
São diagramas que descrevem o comportamento de um sistema do ponto de vista ” intra-classes”. Os diagramas de estado também podem ser
empregados para representar estados mais genéricos e mais abstratos do sistema como “em produção” ou “em análise”.
Boas práticas
Empregue diagramas de estados para representações de estado do “sistema” (mais gerais) e não unicamente para “estados de objetos/classes”.
Represente somente elementos que são essenciais para descrever um aspecto.
Isto é especifique somente os aspectos que você deseja que sejam garantidos na aplicação.
Algoritmos complexos devem fazer uso de diagramas de atividades.
Exercícios
1. Elabore um diagrama de estados que represente um controlador de temperatura. Acima (abaixo) de uma determinada temperatura o sistema
passa a esfriar (esquentar). O sistema também possui uma temperatura limite (mais alto e mais baixo) à partir do qual o sistema alarma e deixa de
operar.
2. Cite aspectos que diferenciam um DFD de um diagrama de estados.
11
UML, Diagramas de Atividades, Pacotes e Componentes
(ver [Booch, 1999] capítulos 12, 25, 29)
Diagrama de Atividades
requisitante :
Leitor
a biblioteca :
Biblioteca
Verifica
disponibilidad
e
Vem
requisitar
[ disponível
]
[ indisponível
]
[ espera
]
[ desiste
]
Coloca em lista de
: requisição
[espera disponibilidade]
espera
Aguarda
disponibilidad
e
disponível
Vem
levantar
Recebe a
publicaçã
o
Avisa o
requisitant
e
Empresta a
publicaçã
o
: requisição
[espera levantamento]
: requisição
[espera devolução]
Consulta a
publicaçã
o
Devolve a
publicaçã
o
Recolhe a
publicaçã
o
Os diagramas de atividades são utilizados principalmente para:
Descrever fluxos de processos do sistema
Descrever algoritmos complexos
Descrever processos paralelos
: requisição
[finalizada]
Pacotes
package BusinessObjects;
public class Employee { }
Dependência de pacotes
package A;
import B.*;
public class SomeAClass {
private ClassInB b;
}
GUI
Client
+ OrderForm
-
WindowsGUI
MacGUI
+
Client
GUI
«import»
Estereótipos em Pacotes
«system»
«subsystem»
«façade»
«framework»
«stub»
«layer»
Componentes
representa o sistema completo
representa uma parte independente de sistema
constitui uma visão sobre outro pacote (não acrescenta funcionalidades, apenas apresenta de forma diferente)
representa um conjunto de classes abstratas e concretas concebido para ser estendido, implementando a
funcionalidade de um determinado domínio de aplicação
pacote que serve como proxy para o conteúdo público de outro pacote
pacote que representa uma camada horizontal do um sistema
Estereótipos em componentes
<<executable>>
componente que pode ser executado num nó
<<library>>
biblioteca estática ou dinâmica
<<database>>
banco de dados
<<table>>
tabela de um banco de dados
<<file>>
arquivo contendo código fonte ou dados
<<document>>
documento genérico
Boas práticas
Represente somente elementos que são essenciais para descrever um aspecto.
Isto é especifique somente os aspectos que você deseja que sejam garantidos na aplicação.
Algoritmos complexos devem fazer uso de diagramas de atividades.
Tente agrupar classes em pacotes que tenham uma unidade com <<subsistema>>
Exercícios
1. Relacione as vantagens e desvantagens do uso da UML para representação de modelos de dados como o modelo relacional. Pense em aspectos
do modelo relacional que não têm correspondente na UML.
2. Explique como diagramas de componentes e pacotes podem ser utilizados para organização do código e distribuição do aplicativo.
12
UML, Deployment, Patterns e Frameworks
(ver [Booch, 1999] capítulos 26, 28, 30)
Este tópico não será tratado em sala de aula mas deverá ser estudado pelo aluno como atividade complementar e obrigatória.
Exercícios
1. Explique por que o deployment é um aspecto importante do desenvolvimento das aplicações OO e modelado através da UML (ver [Booch,
1999] capítulos 26, 30).
2. Defina e diferencie Patterns de Frameworks (ver [Booch, 1999] capítulo 28).
13
Design Patterns, Introdução
MVC, Model-View-Controller
O padrão Modelo-Visão-Controlador, embora constitua-se em um padrão, não é um dos design patterns padrão que aparecem em [Gamma,
1995], onde estão definidos os clássicos padrões do GoF. Entretanto o MVC aparece como uma introdução natural aos padrões de projeto.
Princípios de Design Patterns
Os padrões de projeto buscam seguir bons princípios de design de objeto. Dentre alguns desses princípios encontramos:
Open Close Principle
Dependency Inversion Principle
Interface Sergregation Principle
Single Responsibility Principle (delegação)
Liskov's Substitution Principle
Tipos de Design Patterns
Os padrões de projeto podem ser divididos em padrões de Criação, Estruturais e Comportamentais, segundo o seu principal propósito.
Padrões de Criação
Singleton
Factory
Factory Method
Abstract Factory
Builder
Prototype
Object Pool
Padrões Estruturais
Adapter
Bridge
Composite
Decorator
Façade
Flyweight
Proxy
Padrões Comportamentais
Chain of Responsibility
Command
Interpreter
Iterator
Strategy
Template Method
Visitor
Definindo Design Patterns
A definição e descrição de um design pattern deve ser constituída ao menos de:




Nome do padrão
Problema, ou propósito
Solução, muitas vezes aqui incluindo-se uma aplicação
Conseqüências do padrão
Caracterizando um Design Patterns
As seguintes características devem estar presente em um design pattern:




Descrever e justificar a solução para um problema concreto e bem definido
A solução descrita deve ser comprovada previamente
Descrever relações entre conceitos, mecanismos e estruturas existentes nos sistemas
O problema tratado deve ocorrer em diferentes contextos
Exercícios
1. Defina e exemplifique a técnica de projeto OO denominada delegação.
2. Apresente as principais vantagens do uso de interfaces.
3. Relacione os principais padrões de projeto GoF associados ao MVC.
4. Cite os principais propósitos dos padrões de projeto.
Os padrões de projeto visam diretamente o reuso de soluções e compartilhar o conhecimento entre os projetistas de software.
14
Design Patterns, Singleton
//--------------------------------------------------------------------------------------------package jandl.pattern.singleton;
import java.sql.*;
public final class DBConnection {
// Referência para instância única
private static Connection instance = null;
// Construtor privado
private DBConnection()
throws ClassNotFoundException, SQLException {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
System.out.println("[Driver loaded]");
instance = DriverManager.getConnection("jdbc:odbc:Mamute");
System.out.println("[Connection done]");
}
// Fornece acesso a instância única
public static Connection getConnection()
throws ClassNotFoundException, SQLException {
if (instance == null) {
// Lazy instantiation: só quando preciso
new DBConnection();
}
System.out.println("[Connection obtained]");
return instance; // Retorna instância única da conexão
}
// Encerra conexão adequadamente
public static void shutdown()
throws ClassNotFoundException, SQLException {
if (instance != null) {
instance.close();
instance = null;
System.out.println("[Connection closed]");
}
}
}
//--------------------------------------------------------------------------------------------package jandl.pattern.singleton;
import java.sql.*;
public class DBConnectionTest {
public static void main(String a[]) throws Exception {
Connection con;
Statement stmt;
// Obtém conexão
con = DBConnection.getConnection();
stmt = con.createStatement();
int r = stmt.executeUpdate("INSERT INTO USERS VALUES('"+
a[0] + "','"+ a[1] +"')");
System.out.println(r + " row(s) affected");
stmt.close();
// Obtém (a mesma) conexão
con = DBConnection.getConnection();
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM USERS");
while (rs.next()) {
System.out.println(rs.getString(1) + ":" +
rs.getString(2));
}
rs.close();
stmt.close();
// Encerra conexão
DBConnection.shutdown();
}
}
Exercícios
1. Adapte o padrão Singleton para oferecer um ponto de acesso único a um pool de instâncias no lugar de uma única instância.
15
Design Patterns, FactoryMethod
//--------------------------------------------------------------------------------------------package jandl.pattern.factorymethod;
public interface IConverter {
public double convert(double value);
}
//--------------------------------------------------------------------------------------------// Conversor Farenheit to Celsius
package jandl.pattern.factorymethod;
public class F2C implements IConverter {
// Método definido na interface IConverter
public double convert(double value) {
return 5*(value - 32)/9;
}
}
// Conversor Celsius to Farenheit
package jandl.pattern.factorymethod;
public class C2F implements IConverter {
// Método definido na interface IConverter
public double convert(double value) {
return 9*value/5 + 32;
}
}
//--------------------------------------------------------------------------------------------package jandl.pattern.factorymethod;
public interface IConverterFactory {
public IConverter createConverter(int inS, int outS);
}
//--------------------------------------------------------------------------------------------package jandl.pattern.factorymethod;
public class ConverterFactoryImpl
implements IConverterFactory {
// constantes de escalas disponíveis
public static final int CELSIUS=0, FARENHEIT=1, KELVIN=2;
public static final String scales[] = {
"Celsius", "Farenheit", "Kelvin" };
// método fábrica
public IConverter createConverter(int in, int out) {
switch(in) {
case CELSIUS:
switch(out) {
case FARENHEIT: return new C2F();
case KELVIN: return new C2K();
}
break;
case FARENHEIT:
switch(out) {
case CELSIUS: return new F2C();
case KELVIN: return new F2K();
}
break;
case KELVIN:
switch(out) {
case CELSIUS: return new K2C();
case FARENHEIT: return new K2F();
}
break;
}
return null;
}
}
//--------------------------------------------------------------------------------------------package jandl.pattern.factorymethod;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import javax.swing.*;
public class ConverterUI extends JFrame {
private JComboBox chScIn, chScOut;
private JTextField tfValIn, tfValOut;
private ConverterFactoryImpl factory = new ConverterFactoryImpl();
private DecimalFormat df = new DecimalFormat("#####.00");
public ConverterUI() {
super("ConverterUI");
Container c = getContentPane();
c.setLayout(new GridLayout(3, 3, 2, 2));
// adição dos componentes no ContentPane
c.add(new JLabel());
c.add(new JLabel("In"));
c.add(new JLabel("Out"));
c.add(new JLabel("Scale"));
c.add(chScIn = new JComboBox(factory.scales));
c.add(chScOut = new JComboBox(factory.scales));
c.add(new JLabel("Value"));
c.add(tfValIn = new JTextField());
c.add(tfValOut = new JTextField());
// listeners e ajustes nos componentes
tfValIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
doConvertion();
}
});
tfValOut.setEditable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setResizable(false);
}
private void doConvertion() {
IConverter conv = factory.createConverter(
chScIn.getSelectedIndex(), chScOut.getSelectedIndex());
try {
double value = df.parse(tfValIn.getText()).doubleValue();
if (conv!=null) {
value = conv.convert(value);
}
tfValOut.setText(df.format(value));
} catch (Exception e) {
tfValIn.selectAll();
tfValIn.requestFocus();
Toolkit.getDefaultToolkit().beep();
tfValOut.setText("");
}
}
public static void main(String a[]) {
new ConverterUI().setVisible(true);
}
}
Exercícios
1. Empregue o exemplo dado para criar uma aplicação que calcula a área de figuras com um quadrado ou um círculo criando instâncias
específicas através do FactoryMethod.
16
Design Patterns, Façade
//--------------------------------------------------------------------------------------------package jandl.pattern.facade;
import jandl.pattern.singleton.*;
import java.sql.*;
import java.util.*;
public class QueryFacade {
private Connection con;
// construtor
public QueryFacade() {
try {
// usamos Singleton de conexão ao BD
con = DBConnection.getConnection();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
// método que encapsula consulta
public List executeQuery(String query) {
try {
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
ResultSetMetaData rsmd = rs.getMetaData();
int colsCount = rsmd.getColumnCount();
List result = new LinkedList();
while (rs.next()) {
String row[] = new String[colsCount];
for(int i=0, j=1; i<colsCount; i++, j++) {
row[i] = rs.getString(j);
}
result.add(row);
}
rs.close();
stmt.close();
return result;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
// método que encapsula shutdown da conexão ao BD
public void shutdown() {
try {
DBConnection.shutdown();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
//--------------------------------------------------------------------------------------------package jandl.pattern.facade;
import java.util.*;
public class QueryFacadeTest {
public static void main(String a[]) {
// instanciação e uso do Facade
QueryFacade qf = new QueryFacade();
List result = qf.executeQuery("SELECT * FROM USERS");
// processamento dos dados
Iterator i = result.iterator();
StringBuffer data = new StringBuffer();
int c;
while (i.hasNext()) {
String row[] = (String[])i.next();
for(c=0; c<row.length-1; c++) {
data.append(row[c]);
data.append(",");
}
data.append(row[c]);
data.append("\n");
}
// exibição e finalização
System.out.println(data.toString());
qf.shutdown();
}
}
//---------------------------------------------------------------------------------------------
Exercícios
1. Com base no código apresentado crie uma outra aplicação (livre) do padrão Façade.
17
Design Patterns, Proxy
Este tópico não será tratado em sala de aula mas deverá ser estudado pelo aluno como atividade complementar e obrigatória.
//--------------------------------------------------------------------------------------------public class ProxyDisplay extends JxFrame
{
public ProxyDisplay()
{
super("Display proxied image");
JPanel p = new JPanel();
getContentPane().add(p);
p.setLayout(new BorderLayout());
ImageProxy image = new ImageProxy(this, "elliott.jpg",
321,271);
p.add("Center", image);
setSize(400,400);
setVisible(true);
}
//--------------------------------------------------------------------------------------------public ImageProxy(JFrame f, String filename,
int w, int h)
{
height = h;
width = w;
frame = f;
tracker = new MediaTracker(f);
img = Toolkit.getDefaultToolkit().getImage(filename);
tracker.addImage(img, 0); //watch for image loading
imageCheck = new Thread(this);
imageCheck.start(); //start 2nd thread monitor
//this begins actual image loading
try{
tracker.waitForID(0,1);
}
catch(InterruptedException e){}
}
//--------------------------------------------------------------------------------------------public void run()
{
//this thread monitors image loading
//and repaints when the image is done
try{
Thread.sleep(1000);
while(! tracker.checkID(0))
Thread.sleep(1000);
}
catch(Exception e){}
repaint();
}
//--------------------------------------------------------------------------------------------public void paint(Graphics g)
{
if (tracker.checkID(0))
{
height = img.getHeight(frame); //get height
width = img.getWidth(frame); //and width
g.setColor(Color.lightGray); //erase box
g.fillRect(0,0, width, height);
g.drawImage(img, 0, 0, frame); //draw image
}
else
{
//draw box outlining image if not loaded yet
g.drawRect(0, 0, width-1, height-1);
}
}
//---------------------------------------------------------------------------------------------
Exercícios
1. Estude o propósito, a solução e a implementação Java do padrão Proxy (acima um exemplo da implementação). A fonte/referência para este
exercício é livre.
Booch, G., Rumbaugh, J., Jacobson, I. The Unified Modeling Language User Guide, Addison-Wesley, 1999.
Knoernschild, K. Java™ Design: Objects, UML, and Process, Addison-Wesley, 2001.
Jandl, P.Jr. Padrões de Projeto em Java, revista Mundo Java nº 6, 2004, http://www.mundojava.com.br/NovoSite/6codigos.shtml.
Bruegge, B., Dutoit, A.H. Object-Oriented Software Engineering: Conquering Complex and Changing Systems, Prentice-Hall, 2000.
Gamma, E., Helm, R., Johnson, R., Vlissides, J. Design Patterns: elements of reusable object-oriented software, Addison-Wesley, 1995.
Cooper, J.W. The Design Patterns: Java Companion, Addison-Wesley, 1998.
Kantek, A. Uma Introdução a Objetos Distribuídos, revista Mundo Java nº 6, 2004, http://www.mundojava.com.br/NovoSite/6codigos.shtml.
Download