Análise e Projeto de Sistemas Orientados a Objeto
Objetivos Gerais Aprender a analisar, projetar e implementar sistemas usando a orientação a objeto (OO). Ao terminar a disciplina, o aluno terá desenvolvido um projeto prático completo utilizando os conceitos gerais apresentados.
Objetivos Específicos Introduzir os conceitos básicos relacionados com a orientação a objeto, incluindo
sua aplicabilidade a Análise Orientada a Objeto (OOA), o Projeto Orientado a Objeto (OOD) e a Programação Orientada a Objeto (OOP)
Apresentar a linguagem de modelagem padrão de mercado Unified Modeling Language (UML) largamente utilizada para a Análise e Projeto de sistemas de software de grande escala
Apresentar um processo completo de desenvolvimento de software utilizável com a linguagem UML
Exemplificar OOA, OOD, OOP, UML e o processo de desenvolvimento através de um estudo de caso completo
Apresentar técnicas básicas de Projeto Orientado a Objeto. O enfoque é mostrar em que consiste um bom projeto.
Apresentar Padrões de Projeto, chaves para o bom projeto de software. Apresentar rapidamente assuntos mais "quentes" relacionados com a tecnologia
OO. Permitir que o aluno aprofunde seu conhecimento dos conceitos apresentados
através da elaboração de um sistema completo
apoo-1 programa próxima
Page 1 of 1Análise e Projeto de Sistemas Orientados a Objeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\apoo1.htm
Análise e Projeto de Sistemas Orientados a Objeto
Programa 1. Introdução à Análise e Projeto de Sistemas Orientados a Objeto
1.1 Análise e projeto orientados a objeto (Capítulo 1 do livro de Larman) 1.2 Introdução a um processo de desenvolvimento (Capítulo 2) 1.3 Modelos e artefatos (Capítulo 3)
2. Fase de Planejamento e Elaboração
2.1 Estudo de caso: Terminal Ponto de Venda (PDV) (Capítulo 4) 2.2 Entendendo requisitos (Capítulo 5) 2.3 Use cases: descrição de processos (Capítulo 6) 2.4 Priorização de use cases (Capítulo 7)
3. Fase de Análise 1
3.1 Elaboração de um modelo conceitual (Capítulo 9) 3.2 Modelo conceitual: adição de associações (Capítulo 10) 3.3 Modelo conceitual: adição de atributos (Capítulo 11) 3.4 Construção do glossário (Capítulo 12) 3.5 Comportamento dinâmico: diagramas de sequência (Capítulo 13) 3.6 Comportamento dinâmico: contratos (Capítulo 14)
4. Fase de Projeto 1
4.1 Da análise ao projeto (Capítulo 15) 4.2 Projeto arquitetural (Capítulo 22) 4.3 Descrição de use cases reais (Capítulo 16) 4.4 Diagramas de colaboração (Capítulo 17) 4.5 Padrões para atribuir responsabilidades (Capítulo 18) 4.6 Projeto de soluções com objetos e padrões (Capítulo 19) 4.7 Visibilidade (Capítulo 20) 4.8 Diagramas de classe para a fase de projeto (Capítulo 21) 4.9 Esquema de banco de dados e mapeamento OO-Relacional (Capítulo 38)
5. Fase de Implementação
5.1 Mapeamento do projeto para código (Capítulo 23) 5.2 Programa exemplo em Java (Capítulo 24) 5.3 Testes de unidade 5.4 Adicionando uma interface com o usuário
6. Fase de Análise 2
6.1 Escolha de requisitos da segunda iteração (Capítulo 25) 6.2 Relacionando múltiplos use cases (Capítulo 26) 6.3 Extensão do modelo conceitual (Capítulo 27) 6.4 Generalização (Capítulo 28) 6.5 Organizando o modelo conceitual com packages (Capítulo 29) 6.6 Refinamento do modelo conceitual (Capítulo 30) 6.7 Modelo conceitual no estudo de caso (Capítulo 31)
Page 1 of 2Análise e Projeto de Sistemas Orientados a Objeto: Programa
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\apoo2.htm
6.8 Comportamento do sistema: Diagramas de sequência e contratos na Segunda Iteração (Capítulo 32) 6.9 Comportamento do sistema: Diagramas de estado (Capítulo 33)
7. Fase de projeto 2
7.1 Polimorfismo 7.2 Interfaces 7.3 Composição versus herança 7.4 Padrões de Projeto (Design Patterns)
7.4.1 O que são Design Patterns? 7.4.2 Elementos essenciais de um Design Pattern 7.4.3 Design Pattern: Factory Method 7.4.4 Design Pattern: Iterator 7.4.5 Design Pattern: Composite 7.4.6 Design Pattern: Strategy 7.4.7 Design Pattern: Decorator 7.4.8 Design Pattern: Template Method 7.4.9 Design Pattern: Observer 7.4.10 Comentários finais sobre Design Patterns
8. Tópicos avançados
8.1 Refactoring 8.2 Extreme Programming 8.3 Frameworks 8.4 Componentes
apoo-2 home
Page 2 of 2Análise e Projeto de Sistemas Orientados a Objeto: Programa
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\apoo2.htm
1. Introdução à Análise e Projeto de Sistemas Orientados a Objeto
Análise e projeto orientados a objeto Introdução a um processo de desenvolvimento Modelos e artefatos
intro programa
Page 1 of 11. Introdução à Análise e Projeto de Sistemas Orientados a Objeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\intro\index.htm
Análise e Projeto Orientados a Objeto
Objetivos
Comparar e contrastar Análise e Projeto Definir Análise e Projeto Orientados a Objeto
O que vamos fazer na disciplina?
Saber uma linguagem de programação orientada a objeto (OO) não é suficiente para criar sistemas OO
Tem que saber Análise e Projeto OO (APOO) Isto é, Análise e Projeto usando uma perspectiva de objetos
Usaremos um estudo de caso para concretizar a discussão Usaremos a linguagem UML (Unified Modeling Language) para criar modelos (de
análise e de projeto) Um modelo é uma representação abstrata dos aspectos essenciais de um
sistema O que é "essencial" depende do momento da modelagem A UML usa uma representação principalmente gráfica para representar os
modelos UML é muito popular hoje em dia para modelar sistemas
Usaremos Design Patterns (padrões de projeto) para mostrar soluções abstratas para problemas que surgem frequentemente durante o projeto de sistemas OO
Os patterns tratarão principalmente de: Como atribuir responsabilidades a objetos (uma das atividades mais difícil
no desenvolvimento de sistemas OO) Como separar o que muda do que é constante numa determinada situação,
com o objetivo de ganhar flexibilidade Para evitar "o efeito gelatina"
Explicaremos e seguiremos um processo de desenvolvimento que mostra claramente quais são as etapas a seguir para produzir software de qualidade
Veremos também quais artefatos devem ser produzidos na várias fases e etapas do processo
O que é Análise e Projeto?
Diferenças entre análise e projeto: tem mais do que uma definição empregada Primeira alternativa:
A análise modela o problema e consiste das atividades necessárias para entender o domínio do problema (o que deve ser feito). É uma atividade de investigação.
O projeto modela a solução e consiste das atividades de criação (como pode ser feito)
Page 1 of 4Análise e Projeto Orientados a Objeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\intro\intro1.htm
Segunda alternativa: A análise consiste de todas as atividades feitas com ou para o conhecimento
do cliente. A informação produzida é aquela que o cliente deve discutir e aprovar
O projeto inclui as atividades que resultam em informação que interessa apenas ao programador
Com essa definição, a análise invade um pouco o "lado da solução", pois o cliente deve discutir alguns tipos de interações que ocorrerão na interface do usuário, etc.
Observe portanto que não definição binária que isole "análise" de "projeto" Nesta disciplina, adotaremos a segunda alternativa, pois queremos associar as
palavras "análise" e "projeto" aos artefatos (deliverables) entregues nos final de cada fase
Um modelo de análise deve ser aprovado pelo cliente e pode incluir alguma (pequena) discussão da solução, principalmente no que diz respeito à interface com usuário, etc.
Apesar do nome da disciplina, vamos ver também as fases de requisitos, implementação e testes
A obtenção de requisitos é frequentemente incluída na fase de análise ("análise de requisitos")
Page 2 of 4Análise e Projeto Orientados a Objeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\intro\intro1.htm
O que é Análise e Projeto Orientados a Objeto (APOO)?
A perspectiva empregada é de objetos (coisas, conceitos ou entidades) Durante a Análise OO, a ênfase está em achar e descrever objetos (ou conceitos)
no domínio do problema Por exemplo, num sistema de informação para uma biblioteca, alguns dos
conceitos são Livro, Biblioteca, Usuário. Tais objetos podem ter atributos e responsabilidades
Durante o projeto orientado a objeto, a ênfase está em achar objetos lógicos de software que poderão ser eventualmente implementados usando uma linguagem de programação OO
Tais objetos pode ter atributos e métodos Durante a construção (programação OO), os objetos do projeto são implementados
e testados
APOO versus AP Orientados a Funções (APOF)
Com ambas as técnicas, usa-se decomposição (chamado modularização em APOF) para lidar com a complexidade
A APOF (também chamados de Análise e Projeto Estruturados), a decomposição é por função ou processo
Page 3 of 4Análise e Projeto Orientados a Objeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\intro\intro1.htm
Por que queremos Orientação a Objeto? Quais são as vantagens?
As abstrações podem corresponder às coisas do domínio do problema O nível é mais natural É mais fácil comunicar-se com o usuário ou domain expert na linguagem dele
Os mesmos objetos existem em todas as fases e uma notação única (objetos) facilita portanto a integração entre fases de desenvolvimento (passar de uma fase para a outra)
Fases posteriores adicionam novos objetos mas os objetos do domínio do problema permanecem: são estáveis
Isso ajuda o rastreamento de decisões de projeto e implementação É mais fácil entender o domínio do problema quando esta é quebrado em pedaços:
gerenciamento da complexidade através da modularização O mesmo pode ser dito no domínio do computador (projetando e programando
com objetos) A abstração controla a complexidade (escondendo algo através da separação da
interface e da implementação) A encapsulação facilita as mudanças (através do isolamento) A hierarquia (grafo de herança) permite uma melhor reutilização Hierarquia promove a flexibilidade de fazer mudanças de forma localizada
Exemplo: novos trechos de programas podem usar uma sub-classe nova e código antigo continua usando a superclasse e não toma conhecimento das mudanças
Porém, há problemas de acoplamento com herança que veremos em outro capítulo
A reutilização de pedaços é mais difícil usando paradigmas anteriores (modularização via funções) porque não posso usar coisas pré-existentes tão facilmente
Com objetos, posso dizer: "me dê dois daqueles" porque objetos têm estado Não posso fazer isso com funções porque elas não encapsulam estado
intro-1 programa próxima
Page 4 of 4Análise e Projeto Orientados a Objeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\intro\intro1.htm
Modelos e Artefatos
Objetivos
Definir os modelos e artefatos a serem produzidos durante o proceso de desenvolvimento de software
Os modelos e outros artefatos (deliverables)
Artefatos da fase de elaboração Documento de business case (investigação preliminar) Documento de orçamento e cronograma Documento de especificação de requisitos
Requisitos funcionais (Modelo de use case) Requisitos não funcionais
Modelo conceitual inicial Glossário Projeto arquitetural (poderá incluir un Modelo de componentes)
Fase de construção Refinamento dos requisitos funcionais (Modelo de use case) Refinamento do modelo conceitual (Modelo conceitual)
Inclui vários tipos de diagramas UML Refinamento do projeto arquitetural (poderá incluir un Modelo de componentes) Refinamento do glossário Projeto de baixo nível (Modelo de projeto)
Inclui vários tipos de diagramas UML Esquema de banco de dados
Planos de testes Fase de implantação
Planos de publicação Planos de testes alfa, beta Planos de treinamento
intro-3 programa anterior
Page 1 of 1Modelos e Artefatos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\intro\intro3.htm
2. Fase de Planejamento e Elaboração Estudo de caso: Terminal Ponto de Venda (PDV) Entendendo requisitos Use cases: descrição de processos Priorização de use cases
plan programa
Page 1 of 12. Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\index.htm
Estudo de caso: Terminal Ponto de Venda (PDV)
Objetivos
Introduzir o estudo de caso utilizado na disciplina
O Terminal de Ponto de Venda (PDV)
Nosso estudo de caso envolve um Terminal PDV Um sistema computadorizado que registra vendas e trata de pagamentos Tipicamente usado numa loja de varejo Tipicamente está acoplado a um leitor de código de barra
Trataremos do desenvolvimento do software que controla o terminal usando um processo de desenvolvimento iterativo-incremental
Falaremos de requisitos, análise, projeto e implementação Este sistema envolve um sistema de informação típico e nos fará cruzar com
muitas situações típicas
Arquitetura em camadas e ênfase do estudo
Um sistema de informação típico é organizado usando as camadas apresentadas abaixo
As camadas arquiteturais apresentadas são:
Page 1 of 2Estudo de caso: Terminal Ponto de Venda (PDV)
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan1.htm
Apresentação Interface gráfica, janelas
Lógica de aplicação - Objetos do domínio de problema Objetos representando conceitos do domínio (business objects) Contém o que se chama também business logic
Lógica de aplicação - Objetos de serviço Objetos que não pertencem ao domínio do problema mas oferecem serviços
tais como interfaceamento para um banco de dados, etc. Armazenamento
Mecanismos de armazenamento persistente (SGBDOO, SGBDR, SGBDOR) Usam-se Análise e Projeto OO principalmente nas camadas de lógica de aplicação Falaremos em mais detalhes sobre arquiteturas em camadas na seção 4.2 (Projeto
arquitetural) Boa parte da disciplina tratará do business logic A seção 4.9 tratará de objetos para serviços de persistência
plan-1 programa próxima
Page 2 of 2Estudo de caso: Terminal Ponto de Venda (PDV)
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan1.htm
Entendendo Requisitos
Objetivos
Descrever os artefatos do processo de desenvolvimento relacionados aos requisitos Identificar e categorizar requisitos funcionais do sistema Identificar e categorizar requisitos não-funcionais do sistema (atributos do sistema)
Requisitos
Requisitos são uma descrição de necessidades ou desejos para um produto. Motivo da fase de levantamento de requisitos: saber que sistema deve ser construido Se houver sucesso no levantamento de requisitos, não haverá surpresas desagradáveis para o
usuário na entrega do sistema Artefatos típicos a serem criados
Breve descrição do sistema Descrição dos clientes alvo
Pode incluir como eles operam hoje e quais problemas eles enfrentam Descrição das metas do sistema Descrição dos requisitos funcionais do sistema Descrição dos requisitos não funcionais do sistema
Usaremos o estudo de caso (Terminal PDV) para exemplificar a obtenção de requisitos
Breve descrição do sistema
O objetivo do projeto é de criar um sistema para um Terminal Ponto de Venda (TPDV) a ser usado no comércio varejista.
Descrição dos clientes alvo
O cliente é Xpto, Ltda., que vende TPDVs a lojas varejistas.
Descrição das metas do sistema
A meta básica é de melhorar a automação do balcão de vendas, incluindo: Checkout mais rápido para o cliente Análise rápida e precisa das vendas Automatizar o controle de estoque
Observe que, no Brasil, haveria outras considerações de ordem legal, incluindo o recolhimento
Page 1 of 3Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan2.htm
de impostos
Descrição dos requisitos funcionais do sistema
Requisitos funcionais descrevem o que o sistema deve fazer As categorias de requisitos funcionais são:
Funcionalidade básica A lista abaixo não é exaustiva mas servirá de exemplo para explicar as atividades do
processo de desenvolvimento Observe que o levantamento dos requisitos funcionais deve ser completado usando use
cases (discutidos no próximo capítulo) Use cases descrevem os processos do domínio do problema A lista abaixo pode servir para nortear o levantamento de use cases Alguns desenvolvedores usam apenas use cases para levantar os requisitos funcionais De toda forma, a tabela abaixo exemplifica o que se entende por requisito funcional
Funcionalidade associada ao pagamento
Descrição dos requisitos não funcionais do sistema
Requisitos não funcionais incluem requisitos das seguintes categorias Facilidade de uso necessária Tipo de interface desejada Quem utilizará o produto Volume de utilização (número de usuários, número de transações, ...) Hardware e software alvo para o produto Qualidade/robustez
Categoria de funcionalidade Significado
Evidente Usuário está ciente de que a função está sendo feita
Escondida Embora a função seja feita, ela é invisível ao usuário. Tal funcionalidade frequentemente é esquecida ao levantar requisitos
Friso Funcionalidade opcional; sua adição não afeta outras funções ou o custo significativamente
Referência Funcionalidade Categoria
R1.1 Registrar a vanda corrente (os itens comprados) Evidente
R1.2 Calcular o total de venda, incluindo impostos e descontos aplicáveis Evidente
R1.3
Capturar a informação do item sendo comprado através de um leitor de código de barra, ou manualmente usando um código de produto tal como o Universal Product Code (UPC)
Evidente
R1.4 Dar baixa no inventário ao terminar uma venda Escondida
R1.5 Manter um log de vendas feitas Escondida
R1.6 O caixa deve fazer login com uma identificação e uma senha antes de usar o sistema Evidente
R1.7 Deve prover um mecanismo persistente de armazenamento Escondida
R1.8 Prover integração com outros sistemas Escondida
R1.9 Exibir a descrição e o preço do item sob consideração Evidente
Referência Funcionalidade Categoria
R2.1 Tratar de pagamentos à vista com dinheiro, capturando o valor entregue e calculando o troco Evidente
R2.2
Tratar de pagamentos por cartão de crédito, capturando a informação do cartão através de um leitor de cartões ou por digitação manual e autorizando o pagamento usando o serviço de autorização de crédito da loja (um sistema externo) usando uma conexão via modem
Evidente
R2.3
Tratar de pagamentos por cheque, capturando a informação de identidade/CPF por digitação manual e autorizando o pagamento usando o serviço de verificação de cheques da loja (um sistema externo) usando uma conexão via modem
Evidente
R2.4Lançar os pagamentos via cartão de crédito no sistema de contas a receber, já que o serviço de cartão de crédito deve dinheiro à loja
Escondida
Page 2 of 3Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan2.htm
Tolerância a falha Desempenho Segurança Compatibilidade com outros produtos/versões e necessidades de migração Necessidades de internacionalização do produto Necessidades de customização do produto pelo cliente Suporte Preço da solução Documentação necessária Uso de padrões Aspectos legais Integração com outros produtos Packaging Requisitos de instalação Riscos aceitáveis
Os requisitos não funcionais também são chamados de atributos do sistema Alguns exemplos seguem
plan-2 programa anterior próxima
Atributo Detalhes ou condição limite
Tempo de resposta (Condição limite) Ao registrar um item sendo vendido, a descrição e preço devem aparecer em 2 segundos
Tipo de interface(Detalhe) Usar formulários para entrada de dados e dialog boxes
(Detalhe) Maximizar a facilidade de uso via teclado e não via mouse
Tolerância a falhas (Condição limite) Deve fazer log dos pagamentos autorizados via cartão de crédito em 24 horas, mesmo com falhas de energia ou de dispositivo
Plataformas operacionais (Detalhe) Microsoft Windows 95, Windows, 98, Windows NT e Windows 2000
Page 3 of 3Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan2.htm
Use Cases: Descrição de Processos
Objetivos
Identificar e escrever use cases Diagramar use cases Constrastar use cases de alto nível e expandidos Contrastar use cases essenciais e reais
Introdução
Use cases são usados para descrever os processos do domínio de problema São uma excelente forma de explorar e documentar os requisitos funcionais Antes de elaborar use cases, pode valer a pena elaborar uma tabela de funções básicas como vimos na
seção anterior
Use cases
Um use case é um documento narrativo que descreve uma sequência de eventos feitos por um ator no uso de um sistema para completar um processo de interesse deste ator.
Use cases são "estórias" ou "casos" no uso de um sistema As estórias acabam revelando as funcionalidade desejada do sistema
Em UML, um use case é representado assim:
Exemplo de um Use Case de alto nível: Comprar item Segue uma breve descrição do processo de comprar um item numa loja quando um TPDV é utilizado
Use case: Comprar item Atores: Cliente, Caixa Tipo: primário (a ser explicado logo) Descrição: Um cliente chega ao caixa com itens a comprar. O caixa registra os itens comprados e recebe pagamento. No fim, o cliente sai com os itens comprados.
UML não força o formato exato de um Use Case. A clareza na descrição é o essencial. Iniciamos acima com um Use Case de alto nível, fornecendo poucos detalhes
Útil para entender rapidamente os processos principais envolvidos
Exemplo de um Use Case expandido: Comprar item com dinheiro vivo Ignoramos a questão de dar baixa no inventário aqui
Use case: Comprar item com dinheiro Atores: Cliente (iniciador), Caixa Propósito: Capturar uma venda e seu pagamento em dinheiro Resumo: Um cliente chega ao caixa com itens a comprar. O caixa registra os itens comprados e recebe pagamento. No fim, o cliente sai com os itens comprados. Tipo: primário e essencial Referência cruzada: R1.1, R1.2, R1.3, R1.7, R1.9, R2.1 (pode fazer referência a outros use Cases)
Sequência típica de eventos
Ação do ator Resposta do sistema
1. O Use Case inicia quando um cliente chega a um caixa munido de TPDV com itens a comprar
2. O caixa registra a identificação de cada item 3. Determina o preço do item e adiciona a informação ao total da transação de
venda
Page 1 of 4Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan3.htm
Sequências alternativas: Linha 2: Entrada de um identificador inválido. Indica erro. Linha 7: Cliente não tinha dinheiro suficiente. Cancela transação de venda.
Atores
Um ator é uma entidade externa ao sistema que, de alguma forma, participa das estórias relatadas no Use Case
Um ator tipicamente estimula o sistema com eventos de entrada ou recebe algo so sistema Atores são representados pelo papel que desempenham (e não por nome de pessoa, etc.) Em UML, o ícone que representa um ator é o seguinte:
Para cada Use Case, um dos atores é o iniciador e outros atores podem ser participantes Atores correspondem frequentemente a papeis de seres humanos mas, às vezes, outros sistemas ou
dispositivos elétricos ou mecânicos podem ser atores
O motivo de usar Use Cases
Para decidir e descrever a funcionalidade de comum acordo com o cliente Servem de documento básico de referência durante todo o processo sobre o que foi prometido Serve como base para elaborar os testes funcionais do sistema final Para poder rastrear requisitos funcionais dentro dos modelos de análise, projeto e implementação
Sabemos que requisitos causaram o aparecimento de determinadas soluções
Um erro frequente ao criar Use Cases
Iniciantes costumam representar cada etapa, operação ou transação como Use Case separado (exemplo: login como Use Case)
Um Use Case deve representar uma iteração completa e útil para os atores Use Cases são geralmente processos inteiros, cabo-a-rabo e normalmente envolvem muitas etapas ou
transações Eles modelam os Business Processes do negócio
Etapas comuns a vários Use Cases podem ser agrupados em Use Cases Abstratos, no sentido de minimizar a duplicação de informação
Falaremos mais sobre isso em outro capítulo Exemplos de processo:
Sacar dinheiro num caixa eletrônico Fazer pedido de um produto Cadastrar-se num curso numa escola Verificar a grafia de um documento num processador de texto Atender uma chamada telefônica
Identificação de Use Cases
De forma geral, deve-se verificar a lista de requisitos levantados e usar técnicas de brainstorming Duas formas comuns:
Se houver mais itens, o caixa pode informar a quantidade também
A descrição e preço do item corrente são exibidos
4. Ao completar a entrada dos itens, o caixa indica este fato ao TPDV 5. Calcula e apresenta o total da venda
6. O caixa informa o total da venda ao cliente
7. O cliente efetua o pagamento com dinheiro, possivelmente maior que o total da venda
8. O caixa registra a quantidade de dinheiro recebida 9. Mostra o valor do troco ao cliente
Gera um recibo impresso
10. O caixa deposita o dineiro recebido e extrai o troco a devolver O caixa entrega o troco e o recibo impresso ao cliente
11. Faz log da venda completada
12. O cliente sai da loja com os itens comprados
Page 2 of 4Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan3.htm
Foco nos atores Identificar os atores relacionados com o sistema Para cada ator, identificar os processos que eles iniciam ou dos quais participam Para identificar atores, faça as seguintes perguntas sobre o sistema:
Quem vai usar a funcionalidade principal do sistema (atores principais)? Quem vai precisar do suporte do sistema para desempenhar suas tarefas do dia-a-dia? Quem deverá manter e administrar o sistema (atores secundários)? Que dispositivos de hardware o sistema precisa manusear? Com que outros sistemas este interage? Quem ou o que tem interesse nos resultados (valores produzidos) do sistema?
Foco nos eventos Identificar os eventos externos aos quais um sistema deve responder Relacione os eventos aos atores e Use Cases
Diagramas de Use Case
Em UML, um diagrama de Use Case tem o formato seguinte:
O diagrama identifica e relaciona os Use Cases e os relaciona com os atores Observe que o diagrama de Use Case determina com precisão o que é o "sistema"
Use Cases Primários, Secundários e Opcionais
Use Cases primários: representam processos importantes e/ou comuns (comprar itens) Use Cases secundários: representam processos menos importantes ou raros (Pedido de reposição de
estoque) Use Cases opcionais: representam processos que talvez não sejam considerados
Use Cases Essenciais versus Reais
Use Cases essenciais: possui uma descrição breve, muito abstrata, sem detalhes, sem mencionar tecnologias empregadas (poderia incluir uma frase: "cliente se identifica" sem maiores detalhes porque a forma de identificação pode mudar com tempo e com a disponibilidade de tecnologia)
Use Cases reais: muito mais concretos, mencionando tecnologias correntemente usadas ("cliente se identifica passando seu Smart Card no leitor")
Use Cases essenciais são usados mais cedo no processo (antes do design) e Use Cases podem ser transformados em Use Cases reais durante o design
Durante o processo de desenvolvimento: Durante o levantamento de requisitos
Crie Use Cases em formato de alto nível Crie um diagrama de Use Cases, indicando os relacionamentos Selecione os Use Cases mais críticos, que deverão influenciar o sistema mais ou que envolvam
mais risco e escreva uma versão Expandida Essencial Priorize os Use Cases (próximo capítulo)
Durante a fase de análise Escreva uma versão Expandida Essencial dos Use Cases sendo atacados na iteração corrente (se já
não estiver pronta) Durante a fase de projeto
Escreva uma versão Expandida Real dos Use Cases sendo atacados na iteração corrente
Estudo de Caso: O sistema TPDV
Identificar o sistema, atores e Use Cases O sistema será a combinação de hardware (o terminal) e software executando nele
Page 3 of 4Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan3.htm
Os atores relevantes e alguns processos que eles iniciam são:
Escrever Use Cases em formato de alto nível
Use case: Comprar item Atores: Cliente (iniciador), Caixa Tipo: primário Descrição: Um cliente chega ao caixa com itens a comprar. O caixa registra os itens comprados e recebe pagamento. No fim, o cliente sai com os itens comprados.
Use case: Start Up Atores: Gerente Tipo: primário Descrição: Um gerente liga um TPDV para o preparar para uso pelos Caixas. O gerente verifica que a data e horas estão corretas. O sistema está pronto para uso pelos Caixas
Elaborar um diagrama de Use Cases
Escrever alguns Use Cases no formato Expandido Essencial Favor ver livro, seção 6.16.5
Priorizar os Use Cases Ver próximo capítulo
plan-3 programa anterior próxima
Caixa Fecha caixa
Cliente Compra itens Devolve itens
Gerente Start Up Shut Down
Administrador do sistema Adiciona novos usuários
Page 4 of 4Fase de Planejamento e Elaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan3.htm
Priorização de Use Cases
Objetivos
Priorizar Use Cases Quando necessário, criar versões simplificadas de Use Cases Alocar os Use Cases às iterações de desenvolvimento
Introdução
De forma geral, cada iteração da fase de construção vai tratar de um ou mais Use Cases identificados Às vezes, um Use Case pode ser tratado em duas ou mais iterações, com versões simplificadas tratadas
primeiro
Priorização de Use Cases
Normalmente, quem prioriza os Use Cases é o cliente (ou Domain Expert) Os técnicos podem ajudá-lo fornecendo estimativas de esforço de desenvolvimento para os vários Use Cases Mas lembre que é o cliente que sabe o Business Value de cada Use Case
Alguns parâmetros que podem aumentar a prioridade de um Use Case Afetam muito a arquitetura
O primeiro incremento deveria ser um teste arquitetural (uma validação da viabilidade da arquitetura) O processo de desenvolvimento deve ser "architecture-centric"
Pouco esforço dando muito insight sobre o projeto do sistema Use Cases que envolvem muito risco, são críticos no tempo
O processo de desenvolvimento deve ser "risk-confronting" Envolvem business processes fundamentais
Deixe o cliente falar! Podem aumentar significativamente o lucro ou diminuir as despesas/custos
Deixe o cliente falar!
O estudo de caso
Uma possibilidade de priorização
O Use Case Start Up poderia ser feito numa versão mínima se ele for necessário ao funcionamento do resto Escalonamento final dos Use Cases no estudo de caso
Teremos que atacar Comprar Itens na primeira iteração além de uma versão reduzida de Start Up Como Comprar Itens é complexo, pode-se quebrá-lo em várias versões incrementais:
Comprar Itens versão 1: Pagamento em dinheiro apenas Sem atualização de estoque Loja stand-alone, sem integração a uma organização maior Entrada manual de UPC, sem leitor de código de barras Sem cálculo de impostos
Prioridade Use Case Justificativa
Alta Comprar itens Satisfaz quase todos os critérios de aumento de prioridade
MédiaAdicionar novos usuários Login Devolver itens
Afeta a segurança Afeta a segurança Processo importante; afeta a contabilidade
BaixaFechamento de caixa Start Up Shut Down
Efeito mínimo na arquitetura Definição depende de outros Use Cases Efeito mínimo na arquitetura
Page 1 of 2Priorização de Use Cases
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan4.htm
Sem descontos especiais Sem log in Sem manutenção de perfil de usuário (preferências, ...) Sem controle contábil do valor em caixa Recibo não contém informação completa (sem ID do Caixa, ID do TPDV)
Comprar Itens versão 2: (todas as formas de pagamentos) Comprar Itens versão 3: (versão completa)
As três versões (além dos outros Use Cases) são distribuídas ao longo dos incrementos
plan-4 programa anterior
Page 2 of 2Priorização de Use Cases
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\plan\plan4.htm
3. Fase de Análise 1 Elaboração de um modelo conceitual Modelo conceitual: adição de associações Modelo conceitual: adição de atributos Construção do glossário Comportamento dinâmico: diagramas de sequência Comportamento dinâmico: contratos
anal1 programa
Page 1 of 13. Fase de Análise 1
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\index.htm
Início de uma Iteração de Construção Para iniciar uma iteração, lembre que certos refinamentos são feitos antes de iniciar a
análise detalhada da funcionalidade desejada na iteração O capítulo que inicia agora trata de análise, ou da elaboração de um modelo conceitual
Elaboração de um Modelo Conceitual
Objetivos
Criar um modelo conceitual inicial Distinguir entre atributos corretos e incorretos Adicionar conceitos de descrição, quando apropriado Comparar e contrastar os termos conceito, tipo, interface e classe
Introdução
O modelo conceitual é o artefato mais importante criado durante a análise O modelo conceitual ilustra os conceitos importantes do domínio do problema, suas
associações e atributos Falaremos de associações e atributos nos próximos capítulos Levantar um conjunto rico e expressivo de conceitos (objetos) durante a análise ajuda
muito a conduzir as fases de projeto e implementação É importante lembrar que os conceitos levantados aqui são do domínio do problema e
não conceitos associados a software
Modelos conceituais
Ao fazer análise OO, a decomposição do domínio do problema utiliza objetos e não funções ou processos como na análise estruturada
Exemplo de um modelo conceitual (com conceitos, associações e atributos) Apenas a parte diagramática está sendo mostrada UML permite associar descrições mais detalhadas dos conceitos, atributos, etc.
Page 1 of 6Início de uma Iteração de Construção
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal1.htm
Criar o modelo conceitual ajuda a elaborar o glossário, definindo os termos importantes do domínio do problema
Muito importante para a comunicação entre os envolvidos (clientes e desenvolvedores)
Modelos conceituais não representam entidades de software mas conceitos do domínio do negócio
Exemplo correto
Exemplos errados
Cuidado! Alguns profissionais acham correto introduzir responsabilidades (ou operações) no modelo conceitual
Embora ninguém ache certo introduzir métodos (que implementam operações) no modelo conceitual
Estratégias para identificar conceitos (objetos)
Regra fundamental: é melhor ter conceitos demais (muitos conceitos de granularidade pequena) do que conceitos de menos no modelo conceitual
Novos conceitos podem ser descobertos com tempo (quando se está identificando associações ou atributos, por exemplo) e a elaboração de um modelo conceitual é portanto uma atividade iterativa
Na modelagem de dados para bancos de dados, há um critério de modelagem que diz que algo sobre o qual não precisamos lembrar nada não precisa entrar no modelo conceitual
Page 2 of 6Início de uma Iteração de Construção
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal1.htm
Com o ponto de visto de persistência, a regra faz sentido Mas na modelagem OO, objetos com apenas comportamento (sem atributos)
também são importantes (embora raros) e não devem ser excluídos do modelo
Usando a lista de categoria de conceitos Conceitos são comumente descobertos nas categorias da tabela seguinte
Os exemplos são referentes aos domínios de uma loja e reserva de passagem aérea
Achando conceitos através de substantivos Uma técnica simples para a identificação de conceitos é de isolar os substantivos nas
descrições textuais dos Use Cases Muitos dos substantivos serão conceitos ou atributos
Categoria de Conceito Exemplos
Objetos físicos ou tangíveis Terminal Ponto De Venda (TPDV) Aeronave
Especificações, projetos ou descrições de coisas Especificação de produto Descrição de um vôo
Lugares Loja Aeroporto
Transações (um momento notável) Venda, Pagamento Reserva
Detalhes de transação (Line item) Item de detalhe de uma venda
Papeis de pessoas Caixa Piloto
Coleções de outras coisas (containers) Loja, Prateleira Aeronave
Coisas dentro das coleções Item Passageiro
Outros sistemas externos a nosso sistema Sistema de autorização de cartão de crédito Sistema de controle de tráfego aéreo
Conceitos abstratos Fome Acrofóbia (medo de altura)
Organizações Departamento de vendas Voamos Baixo, Ltda.
Eventos Venda, Roubo, Reunião Vôo, Desastre, Aterrissagem
Processos (frequentemente não é representado como conceito, mas pode ocorrer)
Fazer a venda de um produto Fazer uma reserva de lugar num vôo
Regras e políticas Política de devolução Política de cancelamento
Catálogos Catálogo de produtos Catálogo de peças
Registros de assuntos financeiros, de trabalho, de contratos, legais
Recibo, Plano de contas, Contrato de emprego Log de manutenção
Instrumentos e serviços financeiros Linha de crédito Estoque
Manuais, livros Manual do empregado Manual de reparos
Page 3 of 6Início de uma Iteração de Construção
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal1.htm
Exemplo: Use Case expandida "Comprar Item com Dinheiro Vivo"
Alguns desses substantivos são conceitos (objetos), outros são atributos de conceitos Falaremos mais sobre as diferenças em outro capítulo Uma regra útil: Se pensarmos sobre um conceito X como número ou texto no mundo
real, ele pode ser um atributo; caso contrário, sempre será um conceito Na dúvida, crie um conceito separado Exemplo: Destino é um atributo de um vôo ou um conceito separado?
É um conceito separado (pensamos no destino como sendo um aeroporto)
Conceitos candidatos para o domínio do TPDV
Usando as técnicas acima, temos a seguinte relação de candidatos:
Relatórios são objetos? Um recibo é um relatório Deveria ser um conceito (objeto) A favor de excluir:
Um recibo é apenas um relatório de uma venda Incluí-lo no modelo conceitual não seria útil porque toda sua informação é derivada
de outros objetos A favor de incluir
Um recibo tem um papel importante nas regras de negócio porque permite que o cliente devolva itens comprados
Ação do ator Resposta do sistema
1. O Use Case inicia quando um cliente chega a um caixa munido de TPDV com itens a comprar
2. O caixa registra a identificação de cada item Se houver mais itens, o caixa pode informar a quantidade também
3. Determina o preço do item e adiciona a informação ao total da transação de venda A descrição e preço do item corrente são exibidos
4. Ao completar a entrada dos itens, o caixa indica este fato ao TPDV 5. Calcula e apresenta o total da venda
6. O caixa informa o total da venda ao cliente
7. O cliente efetua o pagamento com dinheiro, possivelmente maior que o total da venda
8. O caixa registra a quantidade de dinheiro recebida 9. Mostra o valor do troco ao cliente
Gera um recibo impresso
10. O caixa deposita o dinheiro recebido e extrai o troco a devolver O caixa entrega o troco e o recibo impresso ao cliente
11. Faz log da venda completada
12. O cliente sai da loja com os itens comprados
TPDV Especificação de produto
Item Item de detalhe de uma venda
Loja Caixa
Venda Cliente
Pagamento Gerente
Catálogo de produtos
Page 4 of 6Início de uma Iteração de Construção
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal1.htm
Na primeira iteração de desenvolvimento, os Use Cases não consideram a devolução do produto e não incluiremos o objeto Recibo
Em outra iteração, poderá ser incluído
Modelagem do mundo não real
Em certos domínios de problema, os conceitos são muito abstratos Exemplo: domínio de redes de computadores ou telecomunicações
Conceitos possíveis são: Mensagem, Conexão, Diálogo, Protocolo, etc.
Modelando descrições
Não se deve incluir como atributos descrições de conceitos a instâncias desses conceitos por dois motivos
Repetição de informação A descrição some se não houver instância
Exemplo: Não está correto incluir a descrição de um produto no conceito Produto É melhor criar um novo conceito DescriçãoDeProduto que descreve instâncias de
Produtos
Outro exemplo: O conceito Vôo deveria incluir toda a descrição do vôo? Não! Se nenhum vôo RG321 ocorrer, a descrição do vôo RG321 deve continuar em
algum lugar: é um conceito à parte
Termos empregados na UML
UML não emprega a palavra "conceito" As alternativas são tipo e classe
Page 5 of 6Início de uma Iteração de Construção
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal1.htm
A diferença entre tipo e classe é que um tipo é abstrato (sem implementação) enquanto a classe sempre inclui alguma implementação
Portanto, o tipo é uma especificação e a classe é uma implementação (de um tipo) A diferença entre as duas coisas se torna mais importante durante a fase de Projeto
Por enquanto, basta dizer que usaremos "conceito" para falar do domínio do problema e "classe" para falar de entidades de software
anal1-1 programa próxima
Page 6 of 6Início de uma Iteração de Construção
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal1.htm
Comportamento Dinâmico: Diagramas de Sequência Ainda estamos em Análise
Objetivos
Identificar eventos e operações do sistema Criar diagramas de sequência do sistema para Use Cases
Introdução
O modelo conceitual visto no capítulo anterior é um modelo estático Agora, vamos considerar um modelo do comportamento dinâmico do sistema Um diagrama de sequência do sistema ilustra eventos partindo de atores e estimulando
o sistema Como ainda estamos investigando o que o sistema faz (e não como), tais diagramas
fazem parte do modelo de análise Cuidado! Embora o autor do livro texto (Larman) indique que diagramas de sequência do
sistema são utilizados apenas na análise, eles podem ser utilizados no projeto também Os diagramas de sequência do sistema são altamente dependentes dos Use Cases, pois
é a partir deles que criamos os diagramas Trataremos o sistema como "caixa preta", isto é, investigando o que ele faz, mas não
como
Diagramas de sequência do sistema
Os Use Cases sugerem como atores interagem com o sistema Os atores geram eventos para o sistema, pedindo que alguma operação seja feita
Exemplo: quando o caixa entrega o UPC do item sendo comprado ao sistema, o caixa pede que o sistema registre a compra deste item
Queremos entender o sistema melhor examinando as operações que um ator requisita do sistema
Um diagrama de sequência do sistema mostra, para um cenário particular de um Use Case, os eventos gerados pelos atores externos, sua ordem, além de eventos envolvendo outros sistemas
Todos os sistemas são tratados como caixas preta Portanto, os eventos cruzam fronteiras de sistemas
Page 1 of 3Comportamento Dinâmico: Diagramas de Sequência
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal5.htm
Diagramas de sequência do sistema são elaborados para os Use Cases mais importantes e as alternativas mais cruciais dos Use Cases
Cuidado! Não gere diagramas de sequência do sistema para situações óbvias ou de fácil entendimento
Exemplo de um diagrama de sequência
No diagram abaixo, o tempo flui para baixo Eventos podem incluir parâmetros
Operações do sistema
Para cada evento, há uma operação correspondente que o sistema desempenha Podemos enxergar o sistema como possuindo operações, necessárias para descrever um
comportamento dinâmico No modelo conceitual, isso não era necessário pois estávamos descrevendo um
modelo estático Exemplo:
Mostrando o texto dos Use Cases nos diagramas de sequência
Útil para mostrar a relação entre as operações e a descrição dos Use Cases Exemplo:
Page 2 of 3Comportamento Dinâmico: Diagramas de Sequência
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal5.htm
Cuidado! Só utilize diagramas de sequência para esclarecer iterações mais complexas entre os atores e o sistema
O exemplo mostrado aqui é simples demais e não merece um diagrama de sequência
anal1-5 programa anterior próxima
Page 3 of 3Comportamento Dinâmico: Diagramas de Sequência
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal5.htm
Modelo Conceitual: Adição de Associações Ainda estamos em Análise
Objetivos
Identificar associações num modelo conceitual Diferenciar associações de conhecimento e associações de entendimento de modelo
Introdução
Queremos associar conceitos de forma a: Satisfazer as necessidades de acesso a informação dos conceitos Deixar o modelo conceitual mais fácil de entender
Associações
Uma associação é um relacionamento estrutural entre conceitos que indica uma conexão interessante e útil
Critério de associações úteis Associações "de conhecimento" (need-to-know) representam a conhecimento de um
relacionamento que deve ser preservado por algum tempo Entre quais objetos precisamos ter memória de um relacionamento? Exemplo: Um "Item de detalhe de uma venda" tem uma associação com uma
instância de uma Venda Caso contrário, não poderíamos calcular o total da venda, emitir o recibo, etc.
Vão implicar em algum tipo de navegação no projeto e na implementação
Page 1 of 6Modelo Conceitual: Adição de Associações
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal2.htm
Outras associações que podem ser úteis são aquelas que melhoram o entendimento do modelo conceitual
Notação UML para associações
Associações são sempre bi-direcionais Não há informação de navegabilidade num modelo conceitual Conceitualmente, a navegabilidade existe nos dois sentidos Escolher o verbo para representar uma direção ou outra é arbitrário
Prefere-se manter a voz ativa no verbo É melhor "Registra-a-atual" do que "É-registrada-por"
Não há implicação sobre a existência de ponteiros, chaves estrangeiras, etc. A seta de direção de leitura é opcional e indica como ler o nome da associação
A seta não possui informação semântica Pode haver informação de multiplicidade nas extremidades das associações
Como achar associações: a lista de associações comuns
Os exemplos são dos domínios de uma Loja e da reserva de passagem aérea Categoria de Associação Exemplos
A é uma parte física de B Gaveta-TPDV Asa-Aeronave
A é uma parte lógica de B Item de detalhe de vanda-Venda Trecho de vôo-Rota de vôo
A é fisicamente contido em B TPDV-Loja, Item-Prateleira Passageiro-Aeronave
A é logicamente contido em B Descrição de item-Catálogo Vôo-Schedule de vôo
Page 2 of 6Modelo Conceitual: Adição de Associações
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal2.htm
Algumas categorias de associações sempre são úteis num modelo conceitual A é uma parte física ou lógica de B A está fisicamente ou logicamente contido em B A é registrado em B
Nível de detalhamento das associações
Não inclua associações demais no modelo É muito mais importante achar conceitos do que associações
Nomes de associações
Use uma frase com verbo que facilite a leitura quando juntada com os conceitos em cada extremidade
Exemplo: Loja Estoca Item Associações são normalmente lidas da esquerda para a direita e de cima para baixo
A é uma descrição de B Descrição de item-Item Descrição de vôo-Vôo
A é uma linha de detalhe de uma transação ou relatório B Item de detalhe de vanda-Venda Tarefa de manutenção-Log de manutenção
A é conhecido/logado/registrado/reportado/capturado por ou em B
Venda-TPDV Reserva-Lista de passageiros
A é um membro de B Caixa-Loja Piloto-Viação aérea
A é uma subunidade organizacional de B Departamento-Loja manutenção-Viação aérea
A usa ou gerencia B Caixa-TPDV Piloto-Aeronave
A se comunica com B Cliente-Caixa Agente de reserva-Passageiro
A está relacionado com uma transação B Cliente-Pagamento Passageiro-Ticket
A é uma transação relacionada com outra transação B Pagamento-Venda Reserva-Cancelamento
A é vizinho de B TPDV-TPDV Cidade-Cidade
A pertence a B TPDV-Loja Aeronave-Viação aérea
Page 3 of 6Modelo Conceitual: Adição de Associações
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal2.htm
Associações múltiplas entre dois tipos
Exemplo segue
Associações e implementação
Durante a análise associações não implicam em fluxos de dados ou informação de navegabilidade
A implementação de uma associação será frequentemente uma referência entre dois objetos
Porém, algumas associações da análise não serão implementadas Novas associações que forem implementadas (na fase de implementação) devem ser
adicionadas ao modelo conceitual (foram esquecidas durante a modelagem conceitual)
Associações no Domínio do TPDV
Usam-se as duas técnicas mostradas acima para identificar associações Associações de conhecimento (que implicam que um objeto deve conhecer o outro) Usando a lista de associações comuns
Associações de conhecimento na loja As seguintes associações são do tipo "conhecimento"
Usando a lista de associações comuns
Associação Por que implica em conhecimento
TPDV Captura Venda Para poder conhecer a venda corrente, calcular o total e imprimir um recibo
Venda Paga-com PagamentoPara poder saber se a venda foi paga, comparar o valor recebido do cliente com o total e imprimir um recibo
CatálogoDeProduto Registra EspecificaçãoDeItem
Para poder obter uma especificação de item, dado um código UPC
Page 4 of 6Modelo Conceitual: Adição de Associações
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal2.htm
Examinemos a aplicabilidade de cada categoria
O modelo conceitual para o domínio TPDV
Ver modelo conceitual parcial (sem atributos) abaixo
Categoria de Associação Sistema TPDV
A é uma parte física de B não se aplica
A é uma parte lógica de B Item de detalhe de venda-Venda
A é fisicamente contido em B TPDV-Loja Item-Loja
A é logicamente contido em B Especificação de produto-Catálogo de produtos Catálogo de produto-Loja
A é uma descrição de B Especificaão de produto-Item
A é uma linha de detalhe de uma transação ou relatório B Item de detalhe de venda-Venda
A é conhecido/logado/registrado/reportado/capturado por ou em B
Venda (completada)-Loja (é logada por) Venda (atual)-TPDV (é capturada por)
A é um membro de B Caixa-Loja
A é uma subunidade organizacional de B não aplicável
A usa ou gerencia B Caixa-TPDV Gerente-TPDV Gerente-Caixa (mas provavelmente não aplicável no sistema)
A se comunica com B Cliente-Caixa
A está relacionado com uma transação B Cliente-Pagamento Caixa-Pagamento Reserva-Cancelamento
A é uma transação relacionada com outra transação B Pagamento-Venda
A é vizinho de B TPDV-TPDV (mas provavelmente não aplicável no sistema)
A pertence a B TPDV-Loja
Page 5 of 6Modelo Conceitual: Adição de Associações
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal2.htm
Pode-se debater cada associação para verificar a utilidade de ser incluída no modelo Uma associação que implica conhecimento normalmente fica As demais ficam se esclarecerem o modelo
Não há modelo único "correto" Podemos argumentar que algumas associações do modelo poderiam sumir
Exemplos Nenhuma das associações seguintes implica em conhecimento
Venda Entrada-por Caixa Isso mudaria se precisássemos da identificação do caixa no recibo
TPDV Iniciado-por Gerente Venda Iniciada-por Cliente Loja Estoca Item LinhaDetalheVenda Registra-Venda-de Item
anal1-2 programa anterior próxima
Page 6 of 6Modelo Conceitual: Adição de Associações
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal2.htm
Modelo Conceitual: Adição de Atributos Ainda estamos em Análise
Objetivos
Identificar atributos num modelo conceitual Distinguir entre atributos corretos e incorretos
Introdução
Precisamos identificar os atributos que servirão para satisfazer as necessidades de informação dos Use Cases sob consideração na iteração corrente
Lembre que os atributos são do domínio do problema
Atributos
Um atributo é um valor de dado lógico de um objeto (ou instância de conceito) Os atributos são identificados primariamente localizando a necessidade de lembrar
informação Exemplo: Uma Venda tem atributos data e hora
Notação UML para atributos
Os tipos podem ser opcionalmente mostrados
Atributos válidos
Manter os atributos de tipos simples Atributos são normalmente de tipos básicos
Boolean, Date, Number, String (ou Text), Time
Page 1 of 3Modelo Conceitual: Adição de Atributos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal3.htm
Podem ser de outros tipos comuns tais como Endereço, Cor, Geométricos (Point, Rectangle, ...), Fone, CPF, UPC (Universal
Product Code), SKU (Stock Keeping Unit), CEP Não se deve representar associações como atributos
Repetição de um exemplo anterior em que um destino de vôo não é um atributo
Valores puros de dados Um valor é puro quando não possuem identidade
Não precisamos distinguir entre instâncias de mesmo valor Exemplos: não precisamos distinguir entre
Instâncias separadas do Number 5 Instâncias separadas do String "mamãe" Instâncias separadas de Fone contendo o mesmo número de telefone Instâncias separadas de Endereço contendo o mesmo endereço
Por outro lado, duas Pessoas chamadas "Sicrano da Silva" devem ser distinguida (têm identidade diferente), apesar do nome igual
Resultado: apenas um valor puro de dado pode ser representado como atributo
Não usar chaves estrangeiras como atributos Na construção de esquemas lógicos de bancos de dados, é comum usar chaves
estrangeiras como atributos Isso não deve ser feito num modelo conceitual (OO ou não)
Exemplo
Page 2 of 3Modelo Conceitual: Adição de Atributos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal3.htm
Uso de tipos não primitivos Pode-se escolher entre usar tipos não primitivos que representem valores puros como
associação ou como atributo, conforme o desejo do analista ou a situação particular O importante é que a comunicação das idéias sobre o modelo esteja clara
Exemplo
Modelagem de quantidades e unidades Cuidado! Certos atributos parecem "números" mas podem ter algo mais associado
Valores financeiros podem ter uma moeda, além do valor Uma quantidade pode ter uma unidade (velocidade em km/s), além do valor
Atributos para o sistema TPDV
Só estamos considerando os Use Cases da primeira iteração Para achar os atributos, lêem-se os requisitos, Use Cases da iteração, outros
documentos explicativos Muitos atributos poderão não ser descobertos na análise e serão identificados apenas no
projeto ou na implementação Podemos ver o modelo conceitual final com os atributos abaixo
anal1-3 programa anterior próxima
Page 3 of 3Modelo Conceitual: Adição de Atributos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal3.htm
Comportamento Dinâmico: Contratos Ainda estamos em Análise
Objetivos
Criar contratos para as operações do sistema
Introdução
Estamos continuando a investigar o comportamento dinâmico do sistema Contratos descrevem os efeitos que as operações têm no sistema Em UML, contratos são especificados usando pré-condições e pós-condições Contratos são estabelecidos depois temos o modelo conceitual, que fizemos os
diagramas de sequência e que identificamos as operações no sistema Continuamos com uma visão de caixa preta para o sistema (queremos caracterizar o que
o sistema faz e não como o faz)
Contratos
O diagrama de sequência não menciona a funcionalidade das operações Isto é, o comportamento do sistema
Um contrato é um documento que descreve o que uma operação promete cumprir As pré- e pós-condições descrevem as mudanças de estado do sistema Contratos podem ser associados a operações do sistema como um todo ou a métodos
individuais (na fase de projeto) Consideraremos apenas contratos de operações de sistema
Exemplo de um contrato
Page 1 of 3Comportamento Dinâmico: Contratos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal6.htm
Segue um contrato possível para a operação entrarItem
Alguns comentários O tipo pode ser Sistema, Classe de software ou Interface, dependendo do tipo de
contrato que se está elaborando As anotações podem indicar dicar para a fase de projeto, algoritmos especiais
desejados, etc. A saída indica informação que sai do sistema (mensagens, registros, ...), sem incluir
a interface com o usuário As pré-condições mencionam as suposições sobre o estado do sistema antes da
execução da operação Muitas dessas coisas poderão ser testadas durante a implementação
(programação defensiva) As pós-condições mencionam as alterações ao estado do sistema como resultado da
execução da operação (isto, é depois que a operação terminou) As pós-condições podem ser descobertas nas seguintes categorias:
Criação e destruição de instâncias Modificação de atributos Associações formadas e quebradas
Não mencione ações que são feitas na operação mas mudanças que ocorreram no estado do sistema
Tire uma foto do sistema antes e depois da operação e descreva a diferença entre as duas fotos
Descrevemos o que ocorreu e não como ocorreu Outros contratos podem ser vistos no livro de Larman
Relação com outros artefatos
Nome entrarItem(upc:número, quantidade:integer)
Responsabilidades Registrar a venda de um item a adicionar seu valor ao total da venda. Exibir a descrição do item e seu preço
Tipo Sistema
Referências cruzadas Funções do sistema: R1.1, R1.3, R1.9
Anotações
Exceções Se o UPC não for válido, indicar erro
Saída Faz log da venda completada
Pré-condições UPC é conhecido pelo sistema
Pós-condições
Se for uma nova venda, uma Venda foi criada (criação de instância) Se for uma nova venda, a nova Venda foi associada ao TPDV (formação de associação) Uma LinhaDetalheVenda foi criada (criação de instância) A LinhaDetalheVenda foi associada à Venda (formação de associação) LinhaDetalheVenda.quantidade recebeu o valor quantidade (mudança de atributo) A LinhaDetalheVenda foi associada com uma EspecificaçãoProduto, baseado no casamento de
UPC (formação de associação)
Page 2 of 3Comportamento Dinâmico: Contratos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal6.htm
anal1-6 programa anterior
Page 3 of 3Comportamento Dinâmico: Contratos
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal6.htm
Construção do Glossário Ainda estamos em Análise
Objetivos
Expressar termos num glossário
Introdução
Um glossário é um documento simples que descreve termos A definição de termos do domínio do problema é importantíssimo para manter limpa a
comunicação entre desenvolvedores e clientes Para reduzir o risco de falahas de entendimento Para ajudar a introduzir novos membros na equipe no meio do projeto
O glossário é elaborado em paralelo com outras fases e é elaborado ao longo da vida do projeto Pode incluir definições de tipos, business rules, Use Cases, atributos, etc.
Eu particularmente não gosto de repetir informação aqui que esteja em outro lugar Exemplo: descrição de atributos que poderão estar em outro documento
Serve como dicionário particular do projeto
Exemplo de glossário (incompleto) para o domínio TPDV
anal1-4 programa anterior próxima
Termo Categoria Comentário
Comprar Itens Use Case Descrição do processo que envolve a compra de itens por um cliente numa loja
EspecificaçãoProduto.descrição atributo Uma descrição curta de um item de venda
Item tipo Um item à venda numa Loja
Pagamento tipo Um pagamento em dinheiro vivo
LinhaDetalheVenda.quantidade atributo A quantidade de um tipo de item comprado
Venda tipo Uma transação de venda
LinhaDetalheVenda tipo O detalhamento da venda de um item particular numa Venda
Loja tipo O lugar onde vendas de itens ocorrem
Venda.total atributo O valor total de uma Venda
EspecificaçãoProduto.UPC atributo O Universal Product Code do item
Page 1 of 1Construção do Glossário
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal1\anal4.htm
4. Fase de Projeto 1 Da análise ao projeto Projeto arquitetural Descrição de use cases reais Diagramas de colaboração Padrões para atribuir responsabilidades Projeto de soluções com objetos e padrões Visibilidade Diagramas de classe para a fase de projeto Esquema de banco de dados e mapeamento OO-Relacional
proj1 programa
Page 1 of 14. Fase de Projeto 1
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\index.htm
Da Análise ao Projeto A análise se concentra na questão "O quê?"
Entendimento dos requisitos, conceitos e operações relacionados a um sistema A próxima fase é a de Projeto, onde a questão "Como?" é abordada O projeto de um sistema é dividido em duas partes
Projeto arquitetural (ou Projeto de Alto Nível) Projeto detalhado (ou Projeto de Baixo Nível)
O projeto arquitetural lida com questões "macro" O projeto detalhado lida com objetos individuais e suas interações
Procura-se resolver o problema de atribuir responsabilidades às classes Também trata de resolver as questões de persistência de objetos Padrões de Projeto (Design Patterns) são extremamente úteis durante o Projeto
detalhado
proj1-1 programa próxima
Page 1 of 1Da Análise ao Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj1.htm
Projeto Arquitetural
Resumo da seção
Projeto de uma arquitetura Decomposição do sistema: partições e camadas Arquiteturas em n camadas Uso de UML para modelar a arquitetura Estruturas de controle Opções de persistência Reutilização: Frameworks e componentização Resumo: Perguntas a fazer ao elaborar um projeto arquitetural
Projeto de uma arquitetura
O que é um projeto arquitetural? Decisões estratégicas que terão consequências profundas As decisões são tomadas num alto nível
Exemplos de decisões Modularização do projeto em subsistemas Escolha de uma estrutura de comunicação e controle entre os subsistemas Escolha da divisão de trabalho entre membros de uma equipe ou entre equipes de
desenvolvimento Definição das interfaces entre subsistemas para possibilitar o trabalho paralelo de
desenvolvimento Escolha de uma estratégia de persistência Escolha do paradigma de DBMS a usar Determinação de oportunidades para o reuso de software Atendimento a requisitos especiais de desempenho Atendimento a outros requisitos (custo, mobilidade, uso de padrões, etc.) Exposição das interfaces para facilitar a futura integração de aplicações (Enterprise
Application Integration - EAI) etc.
Observe que sempre deve-se ter um olho na satisfação dos requisitos levantados Veremos vários aspectos do projeto arquitetural
A discussão é direcionada mais a sistemas de informação
Page 1 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Decomposição do sistema: partições e camadas
Uma estrutura elegante pode frequentemente ser elaborada usando camadas e partições Uma camada é um subsistema que adiciona valor a subsistemas de menor nível de
abstração Uma partição é um subsistema "paralelo" a outros subsistemas
Lembre que subsistemas devem ser coesos (trata de responsabilidades fortemente relacionadas)
Tem forte acoplamento dentro de um subsistema Tem fraco acoplamento entre subsistemas
Para minimizar o acoplamento, camadas frequentemente se comunicam apenas com as camadas "vizinhas"
A decomposição pode terminar quando você atingir subsistemas com temas claros que sejam simples de entender
Alguns sistemas muito pequenos não necessitam de camadas e partições
Arquiteturas em n camadas
Para sistemas de informação que incluam uma interface com o usuário e persistência (isto é, quase todos!), usa-se frequentemente uma arquitetura em 3 camadas (3-tier architecture)
As camadas verticais são: Apresentação: janelas, relatórios, etc.
Também chamada de Camada de Interface com o Usuário, Camada de Serviços do Usuário
Page 2 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Lógica da Aplicação: tarefas e regras que governam o processo Também chamada de Camada de Aplicação, Ccamada de Serviços de Aplicação
Dados: mecanismo de armazenamento persistente Também chamada de Camada de Gerência de Dados, Camada de Serviços de
Dados, Camada de Armazenamento O que vai em cada camada pode mudar ligeiramente
Exemplo: é possível (e pode ser desejável) ter alguma lógica de aplicação na camada de dados usando Stored Procedures
Exemplo: é possível (mas em geral indesejável) ter alguma lógica de aplicação na camada de apresentação usando linguagens de scripts
Em que máquina cada camada roda pode variar, mas hoje em dia, a distribuição física completa é comum
Por que uma arquitetura em 3 camadas? Sistemas em camadas surgiram para aproveitar os PCs da empresa e oferecer
sistemas com interface gráficas amigáveis e integradas ao desktop Os primeiros sistemas cliente-servidor eram de duas camadas (juntando as camadas
de apresentação e de aplicação) mas sofriam de vários problemas: Falta de escalabilidade (conexões a bancos de dados) Enormes problemas de suporte (mudanças à lógica de aplicação forçava
instalações) Nenhum suporte a Thin Clients (PDA, celulares, smart cards, quiosques, ...) Dificuldade de acessar fontes heterogêneas (legado CICS, 3270, ...) Dificuldade de criar software reutilizável para rodar em clientes
Além do mais, a arquitetura em 3 camadas permite: Usar o browser como cliente universal, levando ao conceito de Intranet Evitar instalação em computadores de clientes, parceiros, fornecedores, etc. Implementar serviços automáticos de persistência, tolerência a falhas com fail-
over, gerência de transações, balanceamento de carga, resource pooling, etc. Enterprise JavaBeans, COM+
Arquitetura em n camadas Podemos dividir a camada de aplicação em mais de uma camada
Frequentemente feito separando as aspectos relacionados ao domínio do problema e os aspectos de serviços
Podemos também dividir a camada de dados em mais camadas (usando um datawarehouse, por exemplo)
Uso de UML para modelar a arquitetura
UML provê o conceito de package para agrupar elementos Este mecanismo pode ser utilizado para evidenciar os subsistemas e suas dependências Um package em UML:
Page 3 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
A arquitetura em camadas pode ser representada em UML:
A arquitetura detalhada e as dependências (acoplamento) entre packages podem ser representadas em UML:
Estruturas de controle
O paradigma de controle externo da aplicação deve ser escolhido O paradigma diz como uma aplicação é controlada "de fora" e como interage com
seus usuários e outras aplicações O controle interno dos objetos da aplicação não é visível fora da aplicação
Page 4 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Há vários paradigmas de controle externo Controle orientado a procedimento
Tem um único thread no programa Métodos executam chamadas para obter dados de entrada e esperam os dados O estado do programa pode ser guardado em variáveis locais aos procedimentos
(na pilha de execução) Vantagem: fácil de implementar com linguagens convencionais Desvantagem: qualquer paralelismo inherente aos objetos deve ser mapeado a
um fluxo de controle sequencial Frequentemente usado em aplicações que possuem uma interface não gráfica
Controle orientado a evento Um dispatcher é provido pela linguagem, SGBD, linguagem ou sistema
operacional Métodos da aplicação são amarrados a eventos
Quando o evento ocorre, o método correspondente é chamado Todos os métodos retornam o controle para o dispatcher em vez de esperar que
os dados de entrada cheguem O estado do programa deve ser guardado em variáveis globais já que os métodos
retornam o controle (e não ficam com ele) Vantagem: ajuda a separar a lógica da aplicação da interface com o usuário Frequentemente usado com SGBD munido de linguagem de quarta geração Muito usado com bancos de dados Quase sempre usado para controlar uma interface gráfica
Controle concorrente O controle fica com vários objetos autônomos, cada um respondendo a eventos A concorrência é provida pelo sistema operacional
Usando paralelismo em hardware ou não Observe que estamos nos referindo a controle concorrente dentro da aplicação e
não entre aplicações Este último é muito comum (sessões paralelas de acesso a BD, por exemplo)
Infrequentemente usado, embora seu uso tenda a crescer com o CORBA (framework de objetos distribuídos)
Controle declarativo O programa usa um fluxo de controle implícito beaseado em statements
declarativos Usado em sistemas especialistas baseados em regras
Dois padrões de controle frequentemente utilizados na arquitetura são: Observer Pattern (ou Publish-Subscribe) para acoplar objetos ou subsistemas Model-View-Controller (MVC) para separar os objetos de domínio dos objetos de
interface Serão descritos em outro capítulo (sobre Design Patterns)
Opções de persistência
Tratamos aqui apenas dos aspectos arquiteturais da persistência Um capítulo à frente trata mais detalhadamente do mapeamento de projetos OO para
esquemas de BD relacionais Três grandes pontos devem ser tratados com respeito à persistência de objetos:
Escolha da forma básica de persistência (na memória, em arquivos, usando um SGBD)
Escolha do paradigma de SGBD (se usar um SGBD) Determinação da estratégia de interação entre a aplicação e os dados
Page 5 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Escolha da forma básica de persistência As alternativas básicas são:
Dados na memória Dados em arquivos Dados sob controle de um BD
Muitas aplicações requerem necessariamente os serviços de um BD, mas algumas podem funcionar bem com uma alternativa mais simples
Os seguintes pontos devem ser avaliados para tomar a decisão sobre a forma de persistência:
Persistência de dados Arquivos e SGBDs são fortes Ficar com os dados na mamória requer um suporte especial de memória e fontes
de alimentação para prevenir a perda de informação Custo de aquisição
Um SGBD pode ser muito caro Se houver um site license já em uso, o custo incremental pode ser pequeno
O hardware para manter dados na memória pode ser caro Arquivos nada custam pois são inherentemente suportados pelo sistema
operacional Custo total de posse (Total Cost of Ownership)
Custos incluem a aquisição, treinamento, desenvolvimento, implantação, operação e manutenção
Qualquer uma das 3 alternativas pode ganhar aqui Exemplo: SGBD pode reduzir custos de desenvolvimento mas aumenta custos
de operação (incluindo recursos humanos) Exemplo: arquivos não têm custo de aquisição mas têm um alto custo de
manutenção Quantidade de dados
SGBDs podem armazenar gigantescas quantidades de informação Recursos de hardware limitam a quantidade de dados que pode ser armazenada
na memória Arquivos são limitados em tamanho pelo sistema operacional
Cuidado com sistemas que limitam arquivos a 32 bits (4 GBytes) Desempenho
xdados na memória são acessados mais rapidamente SGBDs têm algoritmos e estruturas de dados especiais para lidar com grandes
quantidades de dados Arquivos podem ser rápidos se couberem na memória ou se forem eficientemente
acessados sequencial ou randomicamente Extensibilidade
SGBDs oferecem independência de dados de forma que o desenvolvedor pode se concentrar nos aspectos lógicos dos dados, sem preocupação imediata com detalhes de implementação física
Acesso concorrente A granularidade de travamento pode afetar o desempenho Tipicamente, arquivos são travados por completo
Travamento de registros de arquivos requer muita programação A granularidade é melhor com dados na memória SGBDs podem ter boa granularidade (record locking) ou menos boa (page
locking) Além do mais, SGBDs podem escalonar travamentos e resolver conflitos
Page 6 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
automaticamente sem programação adicional Recuperação de crash
Arquivos: Arquivos de backup são necessários SGBDs: têm lógica sofisticada para recuperação de crash Memória: requer o uso de shadow memory
Integridade Apenas SGBDs oferecem o suporte a regras de integridade (definidas pelo
programador) Suporte a transações
Apenas SGBDs oferecem suporte a transações Distribuição
Apenas (alguns) SGBDs oferecem suporte à distribuição de dados e vários sites Linguagem de consulta
SGBDs oferecem linguagens de consulta para facilitar o manuseio de dados Alguns produtos do mercado oferecem linguagens de consulta simples para dados
em arquivos Segurança
Arquivos podem ser protegidos pelo sistema operacional (mas sem sofisticaão) SGBDs podem implementar segurança com passwords, views, etc.
Metadados SGBDs permitem a manipulação da estrutura dos dados (metadados) em tempo
de execução Um sumário segue:
Em suma, algumas aplicações naturalmente se beneficiam de cada alternativa de persistência:
Dados na memória Dados para dispositivos eletrônicos (celulares, PDAs, ...) Dados para smart cards, cartuchos de jogos Dados para aplicações que não podem tolerar o custo ou falta de confiabilidade
de um disco Arquivos
Dados na memória Arquivos SGBDs
Persistência de dados Requer hardware especial Bom suporte Bom suporte
Custo de aquisição Custo do hardware especial Não há Pode ser caro
Custo total de posse Variável Variável Variável
Quantidade de dados Limitado pelo hardwareLimitado pelo sostema operacional; A memória limita files em cache
Essencialmente sem limite
Desempenho Muito rápidoRápido para acesso sequencial, certos acessos randômicos e para arquivos em cache
Rápido
Estensibilidade Limitada Limitada Excelente
Acesso concorrente Locking de objetos Locking de arquivos
Locking de objetos ou de registros; Alguns SGBDs só têm locking de páginas
Recuperação de crash Shadow memory Arquivos de backup Bom suporte
Integridade Não há Não há Projetista pode especificar regras
Suporte a transações Não há Não há Transações curtas
Distribuição Não há Não há Às vezes
Linguagem de consulta Não há Parcial Poderosa
Segurança Não há Proteção simples do sistema operacional Pode ser simples ou sofisticado
Metadados Não há Não há Sim
Page 7 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Dados de grande volume, com pouca densidade de informação (archival files, registros históricos detalhados, logs, ...)
Dados crus que devem ser sumarizados num BD (exe.: aquisição de dados, telemetria, ...)
Quantidades modestas de dados com estrutura simples (quando não tem SGBD ou este seria complexo demais para a empresa manter)
Dados acessados sequencialmente Dados que são lidos por inteiro na memória
SGBDs Dados que requerem atualização com níveis finos de granularidade por múltiplos
usuários Dados que devem ser acessados por várias aplicações Grandes quantidades de dados que devem ser eficientemente manipulados Dados de longa duração e muito valiosos a uma organização Dados que devem ser acessados com sofisticado controle de segurança Dados sujeitos a análise sofisticada para o apoio à decisão
Finalmente, observe que é comum utilizar mais do que uma única alternativa para dados diferentes
Escolha do paradigma de SGBD Se usar um SGBD, ainda deve-se escolher entre SGBDs relacionais, objeto-relacionais e
orientados a objeto Os detalhes fogem do escopo desta disciplina Resumindo:
SGBDRs são maduros mas sofrem de um problema sério: impedance mismatch entre objetos e relações
As grandes desvantagens são: Navegação lenta (usando joins de tabelas) Protocolos de travamento inflexíveis (por serem automáticos) Poucos tipos de dados Tudo tem que ser uma tabela
Mostraremos como mapear um projeto OO para um esquema relacional num capítulo à frente
SGBDOOs não são tão maduros mas não sofrem de impedance mismatch e apresentam recursos avançados (evolução de esquema, controle de versões, long transactions, notificações de mudanças, ...)
Oferecem navegação rápida mas ainda carecem até de uma teoria completa! Há ainda a alternativa de SGBDs Objeto-Relacionais que mantêm o paradigma relacional
mas resolvem algumas questões (tais como melhor suporte a tipos de dados)
Determinação da estratégia de interação entre a aplicação e os dados Quais são as estratégias para conectar sua aplicação a um SGBD? Pré-processador e pós-processador batch
Em alguns casos, é melhor que a aplicação não acesse o BD Aplicações batch existentes podem fazer uso de um BD de forma indireta Pode ser útil em algos (raros?) casos em que se usa software legado ou sem código
fonte dentro de uma aplicação (como subsistema)
Page 8 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Arquivos de script Para certas aplicações simples, basta executar um ou mais arquivos contendo
comandos de uma linguagem de consulta (SQL, OQL, ...) Bom para certas situações tais como criar esquemas, popular um BD, prorotipagem
Comandos embutidos da linguagem de manipulação de dados de um SGBDOO Neste caso, a aplicação acessa o BD diretamente Parece natural devido ao casamento entre a linguagem hospedeira (digamos Java) e
um SGBDOO Cuidado! Ao proceder assim, o acoplamento com o SGBDOO fica muito forte e pode
ser difícil mudar de SGBD posteriormente Use o padrão ODMG para melhorar a portabilidade
Comandos SQL estáticos embutidos Código SQl estático é conhecido em tempo de compilação É relativamente simples de usar, mas:
Sem muitos cuidados (batching, etc.), pode resultar numa execução lenta Acopla muito o código da aplicação ao esquema do BD Resulta em código difícil de se ler
Em suma, tenta-se desta forma resolver o impedance mismatch com código estático Implementar uma API customizada de acesso aos dados
Os acessos ao BD são encapsulados em poucos métodos da aplicação Ajuda a manter a consistência dos dados Ajuda a manter o escopo de transações Ajuda a não contaminar a aplicação com um monte de código de acesso ao BD Técnica muito usada
Métodos armazenados no BD Stored procedures Boa forma de reuso para várias aplicações Certos cuidados ao usar Stored Procedures serão tratados num capítulo posterior
sobre persistência Cuidado! Stored Procedures não são implementados de forma portável pelos vários
SGBDs do mercado O padrão SQL não é obedecido pelos fabricantes
Linguagem de quarta geração SGBDRs normalmente vêm com uma linguagem 4GL Podem reduzir o esforço de desenvolvimento, mas não são portáveis
Page 9 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Camada Genérica Orientada a Objeto Uma camada OO é escrita para completamente esconder o BD Ela pode ser genérica (para qualquer objeto, qualquer aplicação) com bastante
esforço Geralmente sofre com desempenho
Interação baseada em Metamodelo A camada de acesso ao BD acessa o metamodelo e constroi a consulta
dinamicamente A consulta resultante acessa o BD Solução frequentemente usada com frameworks Cuidado! Essa técnica requer muito esforço!
É melhor usar uma solução pronta, tal como Toplink
Uso de Middleware Os serviços de persistência podem ser obtidos automaticamente usando Middleware
Enterprise JavaBeans COM+
Vantagem: muitos serviços são obtidos além da persistência: Gerência de transações distribuídas Directory/Naming Segurança Tolerância a falha com Failover Balanceamento de carga Resource pooling Monitoring, logging, ...
Reutilização: Frameworks e componentização
Devido à sua importância, dedicamos um capítulo à frente sobre o tema de reutilização Frameworks
Criação de uma aplicação quase pronta que permite rapidamente criar várias aplicações de um mesmo domínio de problema
Componentes Pedaços de software que permitem a composição visual de aplicações em tempo
Page 10 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
de design
Resumo: Perguntas a fazer ao elaborar um projeto arquitetural
Sobre entidades externas ao sistema Quais sistemas externos devem ser acessados? Como serão acessados? Há integração com o legado a ser feita? Como?
Determinação de oportunidades para o reuso de software Há interesse/conveniência/tempo em aproveitar tais oportunidades? Como isso pode ser feito?
Com componentes? Construindo um framework?
Sobre a organização geral do sistema O sistema é centralizado ou distribuído? Como modularizar em subsistemas? Como minimizar acoplamento entre os pedaços? Lembrando que um sistema pode ser visto como sendo composto de três grandes
camadas lógicas ... Tais camadas serão lógicas ou terão existência física separada? Onde colocar o business logic (como dividir entre as camadas)? Qual é o nível de acoplamento, frequência de interações, volumes de dados trocados
entre as camadas? Qual seria a estrutura de comunicação e controle entre os subsistemas (como ligar as
camadas)? Usando o Observer Pattern? Usando o Model-View-Controller Pattern?
Quais são as interfaces importantes entre os pedaços? Qual é o formato das mensagens (xml, ...)? Como é feita a comunicação remota? CORBA? RPC? RMI? Message Queue?
A programação será feita com qual paradigma? OO? Que linguagens e ferramentas serão usadas?
Sobre a camada de interface O sistema será acessado usando que tipos de clientes?
Browser? Uso de applet? Uso de script cliente?
Como fazer a interface gráfica? Com que ferramentas? Com que componentes visuais?
Serão desenvolvidos? comprados? Javascript ou outra linguagem de script do lado cliente será usada?
Que modelo de componentes visuais será usado? Activex? Javabeans?
Se a interface usar um browser, como será feita a geração de HTML dinâmico? Servlets? JSP? ASP?
Page 11 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Que ferramentas usar para a formatação de relatórios? Há packages a desenvolver que poderiam ser comuns a várias partes da interface?
Sobre a camada de lógica da aplicação Escolha de middleware: qual modelo de componentes de servidor será usado?
COM+? EJB?
Quais são os componentes principais a fazer? Serão componentes persistentes? Serão componentes com ou sem estado? De que forma atender aos requisitos para uso multiusuário?
Soluções para resolver a concorrência Que APIs serão usadas para acesso a:
Dados persistentes? Serviço de mail? Serviço de nomes?
Há packages a desenvolver que poderiam ser comuns a várias partes da lógica da aplicação?
Qual é a organização interna dos modulos executáveis? Determinar sub-camadas e partições
Quais são as interfaces importantes entre os pedaços? Onde verificar os business rules?
No SGBD? No middleware?
Como implementar aspectos de segurança? Como implementar os requisitos de auditoria?
Sobre a camada de dados persistentes Quais são as fontes de dados? externas? internas? existentes? novas? Como acessa-las? Que estratégia de persistência será usada:
Na memória (com recursos especiais como pilha)? Em arquivos? Usando um SGBD?
Qual paradigma de SGBD usar? Relacional? O-R? O-O?
Onde usar stored procedures para implementar os business rules ou garantir a integridade dos dados?
Qual será a estratégia de interação entre a aplicação e os dados? De que forma atender aos requisitos para uso multiusuário (concorrência)? Como resolver o impedance mismatch entre a camada de lógica de aplicação e o
esquema de persistência? Para grandes escalas, como oferecer connection pooling? Como implementar a segurança no SGBD? Como será feita a população dos bancos de dados?
Sobre requisitos de desempenho Há necessidade de bolar formas especiais de atender aos requisitos de desempenho?
Como prover escala? Como prover failover?
Page 12 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
O que deve ser produzido? Quais são os módulos executáveis a produzir?
Executáveis, DLLs, ... Quais são os arquivos importantes (de configuração, etc.) e seu formato (xml, ...)? Como será resolvida a instalação do produto? O que será comprado, feito, modificado? O que será gerado automaticamente com uma ferramenta especial?
Exemplo: geração de esquema através de ferramentas CASE, ...
Sobre a integração futura Que interfaces devem ser expostas para facilitar a futura integração de aplicações
(Enterprise Application Integration - EAI)? Pode-se usar uma camada de API para expor a camada de business logic, colocar
uma camada de script acima disso e ainda camada(s) de interface para ativar a business logic através de scripts.
Vantagens: Fácil criação de macros e outras formas de automação Fácil criação de testes de regressão Clara separação de business logic da interface para o usuário
Como será feita a exposição? Com XML? Através de uma API?
Perguntas adicionais Que ferramentas de desenvovimento serão geradas? Como será o atendimento a outros requisitos (custo, mobilidade, uso de padrões, etc.) Há considerações especiais de administração a levar em conta?
Como será a troca de versões? Como será a distribuição do software?
Via Internet/Intranet? Via mídia?
Pergunta final Você já verificou que a arquitetura bolada pode atender a todos os requisitos
levantados?
proj1-2 programa anterior próxima
Page 13 of 13Projeto Arquitetural
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj2.htm
Descrição de Use Cases Reais
Use Cases reais são uma redefinição de Use cases essenciais mostrando o projeto do Use case em termos de tecnologias específicas de entrada e saída
Exemplo: se uma GUI é usada, as telas com todos seus campos podem ser usadas para detalhar o Use Case, mostrando as interações de baixo nível
Use Cases reais normalmente não são criados, só sendo necessários quando o cliente exige uma alto grau de detalhamento da interface com o usuário
Normalmente, basta ter um esboço das telas com os detalhes sendo aprontados durante a implementação
Exemplo
Use Case: Comprar item - versão 1 (pagamento à vista)
Atores: Cliente (iniciador), Caixa
Objetivo: Capturar uma venda e seu pagamento à vista
Resumo: Um Cliente chega ao caixa de saída com itens sendo comprados. O Caixa registra os itens comprados e recebe pagamento em espécie. No final, o Cliente sai com os itens.
Tipo: Primário e real
Referências cruzadas: Funções: R1.1, R1.2, R1.3, R1.7, R1.9, R2.1
Sequência Típica de Eventos
Ação do ator Resposta do Sistema
1. O Use Case inicia quando um Cliente chega ao TPDV com itens sendo comprados
2. Para cada item, o Cliente digita o Código Universal de Produto (UPC) no campo A acima. Se houver mais de um item, a
3. Adiciona o preço do item ao valor total da compra.
Page 1 of 2Descrição de Use Cases Reais
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj3.htm
proj1-3 programa anterior próxima
quantidade é digitada no campo E. H é pressionado apõs a entrada de cada item
A descrição e preço do item corrente são exibidos nos campos B e F
4. Ao completar a entrada dos itens, o Cliente indica o fato pressionando I 5. Calcula e exibe o total da venda em C
6. ...
Page 2 of 2Descrição de Use Cases Reais
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj3.htm
Diagramas de Colaboração
Introdução
Dois tipos de diagramas podem ser usados para mostrar as interações (mensagens) entre objetos
Diagramas de Sequência Diagramas de Colaboração
Os dois tipos de diagramas são chamados diagramas de interação O objetivo é de mostrar como as pós-condições dos contratos serão realizadas O diagrama de sequência é mais simples de usar quando se deseja mostrar apenas as
sequências de interações O diagrama de colaboração é mais adequado quando se deseja expressar mais detalhes
da colaboração entre objetos Exemplo de um diagrama de sequência:
Exemplo de um diagrama de colaboração
Page 1 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
No exemplo acima: A mensagem façaPagamento é enviada a uma instância de uma TPDV O TPDV envia a mensagem façaPagamento a uma instância de Venda O objeto da classe Venda cria uma instância de um Pagamento
Sobre a importância de diagramas de interação
Uma das coisas mais difíceis de fazer no projeto de um sistema é a atribuição de responsabilidades a objetos e a consequente colaboração entre objetos
Os diagramas de interação ajudam muito a construir o sistema e uma boa parcela do tempo deve ser dedicado à sua construção
É principalmente aqui que bons princípios de projeto serão usados Esta seção discute apenas a notação empregada em diagramas de colaboração Seções subsequentes tratarão da distribuição de responsabilidades entre objetos e
apresentar padrões de projeto
Como criar diagramas de colaboração
1. Criar um diagrama separado para cada operação do sistema sendo desenvolvida na iteração corrente. Para cada mensagem de operação do sistema, um diagrama é consttuído com essa mensagem inicial
2. Se o diagrama ficar complexo (não cabe numa única página), quebre-o em diagramas menores
3. Usando o contrato das operações (principalmente as pós-condições) e os Use Cases como ponto de partida, projete um sistema de objetos interagindo entre si para realizar as tarefas. Aplique padrões de projeto para desenvolver um bom projeto
Relação entre diagramas de colaboração e outros artefatos
Page 2 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
O Use Cases sugerem os eventos do sistema, os quais são mostrados explicitamente nos diagramas de sequência do sistema
Uma primeira aproximação do efeito das operações do sistema é descrita nos contratos As operações do sistema são mensagens que iniciam um diagrama de interação, o qual
ilustra como os objetos realizam a tarefa
Notação básica para diagramas de colaboração
Classe e instâncias
Links Um link é uma conexão entre dois objetos
É uma instância de uma associação Indica alguma forma de navegabilidade e visibilidade
Mensagens Observe o número de sequência das mensagens
Parâmetros O tipo do parâmetro é opcional
Page 3 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
Valor de retorno
Sintaxe de mensagem Pode-se usar a sintaxe UML (como acima) ou de outra linguagem (Java, por exemplo)
Mensagens a "this"
Iteração A iteração é mostrada com um número de sequência e um *
A mensagem é enviada repetidamente
Valores de recorrência podem ser incluídos
Mais de uma mensagem pode ser enviada na iteração
Page 4 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
Criação de instâncias A mensagem de criação independente de linguagem é "create" O estereótipo «new» pode ser usado
Sequenciamento de mensagens A primeira mensagem não é numerada
Tem várias alternativas para numerar as demais mensagens, incluindo um esuqema hierárquico
Page 5 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
Mensagens condicionais A mensagem só é enviada se o teste resultar em TRUE
Caminhos condicionais mutuamente exclusivos
Coleções Um conjunto de instâncias (multiobjeto)
Mensagens para coleções Na UML 1.1, uma mensagem enviada para uma coleção vai para o objeto-coleção e não
para todos os objetos da coleção Na UML 1.0, a mensagem ia para todos os objetos
Page 6 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
Outros exemplos de mensagens para objetos e coleções
Mensagens para a classe (métodos estáticos) Classe não está sublinhada
proj1-4 programa anterior próxima
Page 7 of 7Diagramas de Colaboração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj4.htm
Padrões Para Atribuir Responsabilidades
Introdução
Um sistema OO é composto de objetos que enviam mensagens uns para os outros Uma mensagem é um método executado no contexto de um objeto
Escolher como distribuir as responsabilidades entre objetos (ou classes) é crucial para um bom projeto Uma má distribuição leva a sistemas e componentes frágeis e difíceis de entender, manter, reusar e estender
Mostraremos alguns padrões de distribuição de responsabilidades Padrões GRASP (General Responsibility Assignment Software Patterns) São padrões de Larman
Ao mostrar padrões, apresentaremos princípios de um bom projeto OO Veremos mais padrões de projeto em outros capítulos Os padrões são utilizados enquanto se cria diagramas de interação
Responsabilidades
Responsabilidades são obrigações de um tipo ou de uma classe Obrigações de fazer algo
Fazer algo a si mesmo Iniciar ações em outros objetos Controlar ou coordenar atividades em outros objetos
Obrigações de conhecer algo Conhecer dados encapsulados Conhecer objetos relacionados Conhecer coisas que ele pode calcular
Exemplos Uma Venda tem a responsabilidade de criar linha de detalhe (fazer algo) Uma Venda tem a responsabilidade de saber sua data (conhecer algo)
Granularidade Uma responsabilidade pode envolver um único método (ou poucos)
Exemplo: Criar uma linha de detalhe Uma reponsabilidade pode envolver dezenas de classes e métodos
Exemplo: Responsabilidade de fornecer acesso a um BD Uma responsabilidade não é igual a um método
Mas métodos são usados para implementar responsabilidades
Diagramas de interação evidenciam responsabilidades
O diagrama indica que objetos da classe Venda têm responsabilidade de criar linhas de detalhe de venda Eles devem colaborar com objetos da classe LinhaDetalheVenda
Page 1 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Padrões
Uma definição informal: "Cada padrão descreve um problema que ocorre frequentemente e então descreve o cerne da solução ao problema
de forma a poder reusar a solução milhões de vezes em situações diferentes" Observe que o que é reutilizado são as classes e suas colaborações
Reuso de idéias, não código Consistem de micro-arquiteturas de classes, objetos, suas responsabilidades e suas colaborações
Contêm o somatório da experiência dos melhores projetistas O-O! Estão revolucionando o projeto de software desde 1995 quando o famoso livro da "Gang of Four" (GoF) apareceu com
o primeiro catálogo de 23 padrões Ver bibliografia Tem muito mais padrões aparecendo sempre OOPSLA é uma grande fonte de padrões
Ficará mais claro com alguns exemplos Design Patterns iniciaram a febre de padrões
Analysis Patterns Testing Patterns Business Patterns Pedagogical Patterns e mais ...
Os padrões GRASP são de Larman e são do tipo Design Patterns Veremos padrões GRASP e GoF (em outro capítulo)
Elementos essenciais de um Design Pattern
Um Nome Descreve o problema de projeto, suas soluções e consequências em poucas palavras Permite projetar num nível mais alto de abstração Permite falar com outros sobre soluções e documentar código, já que os nomes de padrões estão ficando padronizados
"Todo mundo" conhece os 23 padrões da GoF É equivalente a padronizar "lista encadeada", "pilha", etc. no mundo das estruturas de dados Cuidado! Nem todo mundo conhece os padrões de Larman
O Problema Descreve quando aplicar o padrão Descreve o problema e o contexto Pode descrever problemas específicos de projeto
Exemplo: como representar algoritmos como objetos? Pode descrever estruturas de objetos ou de classes que são sintomas de um projeto inflexível Às vezes, o padrão lista condições que devem se aplicar para usar o padrão
A Solução Descreve os elementos constituintes do projeto, seus relacionamentos, responsabilidades e colaborações A solução não descreve um projeto ou implementação concretos porque um padrão é um gabarito de solução para
várias situações
As Consequências Os resultados e trade-offs da aplicação do padrão Diz respeito a trade-offs de espaço, tempo, flexibilidade, extensibilidade, portabilidade
Os padrões GRASP deste capítulo
Expert Creator Low Coupling High Coesion Controller
Expert
Problema Qual é o princípio mais fundamental para atribuir responsabilidades?
Solução Atribuir uma responsabilidade ao expert de informação - a classe que possui a informação necessária para preencher a
responsabilidade
Exemplo No estudo de caso, alguma classe precisa saber o total de uma venda Podemos dizer isso sobre a forma de uma responsabilidade:
Page 2 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Quem deveria ser reponsável pelo conhecimento do total de uma venda? Pelo padrão Expert, escolhemos a classe que possui a informação necessária para determinar o total Considere uma parte do modelo conceitual:
Qual é a informação necessária? Precisamos conhecer (ter acesso a) todos os LinhaDetalheVenda Qual é information expert? É a classe Venda
Podemos agora fazer parte do diagrama de colaboração e do diagrama de classes
Ainda não terminamos. Qual informação é necessária para determinar o subtotal para um item (uma linha de detalhe)? Precisamos de LinhaDeVenda.quantidade e de EspecificaçãoDeProduto.preço Quem é o information expert? É a classe LinhaDeVenda
Chegamos aos seguintes diagramas:
Qual é o information expert para saber o preço de um produto? É EspecificaçãoDeProduto
Chegamos aos seguintes diagramas:
Discussão É o padrão mais usado de todos para atribuir responsabilidades A informação necessária frequentemente está espalhada em vários objetos
Portanto, tem muitos experts parciais Exemplo: determinar o total de uma venda requer a colaboração de 3 objetos, em 3 classes diferentes
Mensagens são usadas para estabelecer as colaborações O resultado final é diferente do mundo real
No mundo real, uma venda não calcula seu próprio total Isso seria feito por uma pessoa (se não houvesse software) Mas no mundo de software, não queremos atribuir essa responsabilidade ao Caixa ou ao TPDV!
Page 3 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
No mundo de software, coisas inertas (ou até conceitos como uma venda) podem ter responsabilidades: Tudo está vivo!
Consequências A encapsulação é mantida, já que objetos usam sua própria informação para cumprir suas responsabilidades
Leva a fraco acoplamento entre objetos e sistemas mais robustos e fáceis de manter Leva a alta coesão, já que os objetos fazem tudo que é relacionado à sua própria informação
Também conhecido como "Colocar as responsabilidades com os dados" "Quem sabe, faz" "Animação" "Eu mesmo faço" "Colocar os serviços junto aos atributos que eles manipulam"
Creator
Problema Quem deve criar novas instâncias de uma classe?
Solução Atribuir à classe B a responsabilidade de criar instância da classe A se uma das seguintes condições se aplicar:
B agrega objetos da classe A B contém objetos da classe A B registra instâncias da classe A B usa muito objetos da classe A B possui os dados usados para inicializar A
B é um criador (creator) de objetos da classe A Se mais de uma opção se aplica, escolha o B que agregue ou contenha objetos da classe A
Exemplo No estudo de caso, quem deveria criar uma instância de LinhaDetalheVenda? Pelo padrão Creator, precisamos achar alguém que agrega, contém, ... instâncias de LinhaDetalheVenda Considere o modelo conceitual parcial abaixo:
Venda agrega instâncias de LinhaDetalheVenda e é portanto um bom candidato para criar as instâncias Chegamos aos seguintes diagramas:
Discussão Escolhemos um criador que deve estar conectado ao objeto criado, de qualquer forma, depois da criação Isso leva a fraco acoplamento Exemplo de criador que possui os valores de inicialização
Uma instância de Pagamento deve ser criada A instância deve receber o total da venda Quem tem essa informação? Venda Venda é um bom candidato para criar objetos da classe Pagamento
Consequências Fraco acoplamento, já que o objeto criado deve normalmente ser visível ao criador, depois da criação
Low Coupling
Problema Como minimizar dependências e maximizar o reuso?
Page 4 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
O acoplamento é uma medida de quão fortemente uma classe está conectada, possui conhecimento ou depende de outra classe
Com fraco acoplamento, uma classe não é dependente de muitas outras classes Com uma classe possuindo forte acoplamento, temos os seguintes problemas:
Mudanças a uma classe relacionada força mudanças locais à classe A classe é mais difícil de entender isoladamente A classe é mais difícil de ser reusada, já que depende da presença de outras classes
Solução Atribuir responsabilidades de forma a minimizar o acoplamento
Exemplo Considere o seguinte diagrama parcial de classes no estudo de caso
Suponha que temos que criar um Pagamento e associá-lo a uma Venda Que classe deveria ter essa responsabilidade? Alternativa 1: No mundo real, um TPDV "registra" um pagamento e o padrão Creator sugere que TPDV poderia criar
Pagamento TPDV deve então passar o pagamento para a Venda Veja o resultado abaixo
Alternativa 2: Criar o Pagamento com Venda e associá-lo à Venda Veja o resultado abaixo
Supondo que a Venda deva ter conhecimento do pagamento (depois da criação) de qualquer jeito, a alternativa 2 tem menos acoplamento (TPDV não está acoplado a Pagamento)
Dois padrões (Creator e Low Coupling) sugeriram diferentes soluções Minimizar acoplamento ganha
Discussão Minimizar acoplamento é um dos princípios de ouro do projeto OO Acoplamento de manifesta de várias formas:
X tem um atributo que referencia uma instância de Y X tem um método que referencia uma instância de Y
Pode ser parâmetro, variável local, objeto retornado pelo método X é uma subclasse direta ou indireta de Y X implementa a interface Y
A herança é um tipo de acoplamento particularmente forte Uma seção futura esmiuça o assunto
Não se deve minimizar acoplamento criando alguns poucos objetos monstruosos (God classes) Exemplo: todo o comportamento numa classe e outras classes usadas como depósitos passivos de informação
Tipos de acoplamentos (do menos ruim até o pior) Acoplamento de dados Acoplamento de controle Acoplamento de dados globais Acoplamento de dados internos
Acoplamento de dados Situações
Saída de um objeto é entrada de outro Uso de parâmetros para passar itens entre métodos
Ocorrência comum: Objeto a passa objeto x para objeto b Objeto x e b estão acoplados
Uma mudança na interface de x pode implicar em mudanças a b
Page 5 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Exemplo:
class Servidor { public void mensagem(MeuTipo x) { // código aqui x.façaAlgo(Object dados); // dados e x estão acoplados // (se interface de dados mudar x terá que mudar) // mais código } }
Exemplo pior: Objeto a passa objeto x para objeto b x é um objeto composto ou agregado (contém outro(s) objeto(s)) Objeto b deve extrair objeto y de dentro de x Há acoplamento entre b, x, representação interna de x, y Exemplo: ordenação de registros de alunos por matrícula e nome
class Aluno { String nome; long matrícula; public String getNome() { return nome; } public long getMatrícula() { return matrícula; } // etc. } ListaOrdenada listaDeAlunos = new ListaOrdenada(); Aluno novoAluno = new Aluno(...); //etc. listaDeAlunos.add(novoAluno);
Agora, vamos ver os problemas
class ListaOrdenada { Object[] elementosOrdenados = new Object[tamanhoAdequado]; public void add(Aluno x) { // código não mostrado long matrícula1 = x.getMatrícula(); long matrícula2 = elementosOrdenados[k].getMatrícula(); if(matrícula1 < matrícula2) { // faça algo } else { // faça outra coisa } }
O problema da solução anterior é que há forte acoplamento ListaOrdenada sabe muita coisa de Aluno
O fato de que a comparação de alunos é feito com a matrícula O fato de que a matrícula é obtida com getMatrícula() O fato de que matrículas são long (representação de dados) Como comparar matrículas (com <)
O que ocorre se mudarmos qualquer uma dessas coisas? Solução 2: mande uma mensagem para o próprio objeto se comparar com outro
class ListaOrdenada { Object[] elementosOrdenados = new Object[tamanhoAdequado]; public void add(Aluno x) { // código não mostrado if(x.lessThan(elementosOrdenados[K])) { // faça algo } else { // faça outra coisa } }
Reduzimos o acoplamento escondendo informação atrás de um método Problema: ListaOrdenada só funciona com Aluno Solução 3: use interfaces para desacoplar mais ainda
Interface Comparable { public boolean lessThan(Object outro);
Page 6 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
public boolean greaterThan(Object outro); public boolean equal(Object outro); } class Aluno implements Comparable { public boolean lessThan(Object outro) { // compare registro de aluno com outro } } class ListaOrdenada { Object[] elementosOrdenados = new Object[tamanhoAdequado]; public void add(Comparable x) { // código não mostrado if(x.lessThan(elementosOrdenados[K])) { // faça algo } else { // faça outra coisa } }
Em C++, teria outras soluções Apontador de função Apontador de função com tipos genéricos (templates)
Acoplamento de controle Passar flags de controle entre objetos de forma que um objeto controle as etapas de processamento de outro
objeto Ocorrência comum:
Objeto a manda uma mensagem para objeto b b usa um parâmetro da mensagem para decidir o que fazer
class Lampada { public static final ON = 0; public void setLampada(int valor) { if(valor == ON) { // liga lampada } else if(valor == 1) { // desliga lampada } else if(valor == 2) { // pisca } } } Lampada lampapa = new Lampada(); lampada.setLampada(Lampada.ON); lampada.setLampada(2);
Solução: decompor a operação em múltiplas operações primitivas
class Lampada { public void on() { // liga lampada } public void off() { // desliga lampada } public void pisca() { // pisca } } Lampada lampada = new Lampada(); lampada.on(); lampada.pisca();
Ocorrência comum: Objeto a manda mensagem para objeto b b retorna informação de controle para a Exemplo: retorno de código de erro
class Teste { public int printFile(File toPrint) { if(toPrint está corrompido ) { return CORRUPTFLAG; } // etc. etc. } } Teste umTeste = new Teste(); int resultado = umTese.printFile(miniTeste); if(resultado == CORRUPTFLAG) { // oh! oh! } else if(resultado == -243) { // etc. etc.
Solução: use exceções
class Teste { public int printFile(File toPrint) throws PrintExeception { if(toPrint está corrompido ) {
Page 7 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
throw new PrintExeception(); } // etc. etc. } } try { Teste umTeste = new Teste(); umTeste.printFile(miniTeste); } catch(PrintException printError) { // faça algo }
Acoplamento de dados globais Dois ou mais objetos compartilham estruturas de dados globais É um acoplamento muito ruim pois está escondido
Uma chamada de método pode mudar um valor global e o código não deixa isso aparente Um tipo de acoplamento muito ruim
Acoplamento de dados internos Um objeto altera os dados locais de um outro objeto Ocorrência comum:
Friends em C++ Dados protected ou públicos de java
Use com cuidado!
Consequências Uma classefracamente acoplada não é afetada (ou pouco afetada) por mudanças em outras classes Simples de entender isoladamente Reuso mais fácil
High Coesion
Problema Como gerenciar a complexidade? A coesão mede quão relacionados ou focados estão as responsabilidades da classe
Também chamado coesão funcional (ver à frente) Uma classe com baixa coesão faz muitas coisas não relacionadas e leva aos seguintes problemas:
Difícil de entender Difícil de reusar Difícil de manter "Delicada": constantemente sendo afetada por outras mudanças
Uma classe com baixa coesão assumiu responsabilidades que pertencem a outras classes e deveriam ser delagadas
Solução Atribuir responsabilidades que mantenham alta coesão
Exemplo Mesmo exemplo usado para Low Coupling Na primeira alternativa, TPDV assumiu uma responsabilidade de efetuar um pagamento (método façaPagamento())
Até agora, não há problema Mas suponha que o mesmo ocorra com várias outras operações de sistema
TPDV vai acumular um monte de métodos não muito focados Resultado: baixa coesão
A segunda alternativa delega façaPagamento() para a classe Venda Mantém maior coesão em TPDV
Discussão Alta coesão é outro princípio de ouro que deve ser sempre mantido em mente durante o projeto
Page 8 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Tipos de coesão entre módulos Coincidental (pior) Lógico Temporal Procedural De comunicação Sequencial Funcional (melhor)
Coesão coincidental Há nenhuma (ou pouca) relação construtiva entre os elementos de um módulo No linguajar OO:
Um objeto não representa nenhum conceito OO Uma coleção de código comumente usado e herdado através de herança (provavelmente múltipla)
class Angu { public static int acharPadrão(String texto, String padrão) { // ... } public static int média(Vector números) { // ... } public static outputStream abreArquivo(string nomeArquivo) { // ... } } class Xpto extends Angu { // quer aproveitar código de Angu ... }
Coesão lógica Módulo faz um conjunto de funções relacionadas, uma das quais é escolhida através de um parâmetro ao chamar o
módulo Semelhante a acoplamento de controle Cura: quebrar em métodos diferentes
public void faça(int flag) { switch(flag) { case ON: // coisas para tratar de ON break; case OFF: // coisas para tratar de OFF break; case FECHAR: // coisas para tratar de FECHAR break; case COR: // coisas para tratar de COR break; } }
Coesão temporal Elementos estão agrupados no mesmo módulo porque são processados no mesmo intervalo de tempo Exemplos comuns:
Método de inicialização que provê valores defaults para um monte de coisas diferentes Método de finalização que limpa as coisas antes de terminar
procedure inicializaDados() { font = "times"; windowSize = "200,400"; xpto.nome = "desligado"; xpto.tamanho = 12; xpto.localização = "/usr/local/lib/java"; }
Cura: depender de construtores e destrutores
Page 9 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
class Xpto { public Xpto() { this.nome = "desligado"; this.tamanho = 12; this.localização = "/usr/local/lib/java"; } }
Outro exemplo: arquivo de configuração típico
[Macintosh] EquationWindow=146,171,406,661 SpacingWindow=0,0,0,0 [Spacing] LineSpacing=150% MatrixRowSpacing=150% MatrixColSpacing=100% SuperscriptHeight=45% SubscriptDepth=25% LimHeight=25% LimDepth=100% LimLineSpacing=100% NumerHeight=35% DenomDepth=100% FractBarOver=1pt FractBarThick=0.5pt SubFractBarThick=0.25pt FenceOver=1pt SpacingFactor=100% MinGap=8% RadicalGap=2pt EmbellGap=1.5pt PrimeHeight=45% [General] Zoom=200 CustomZoom=150 ShowAll=0 Version=2.01 OptimalPrinter=1 MinRect=0 ForceOpen=0 ToolbarDocked=1 ToolbarShown=1 ToolbarDockPos=1 [Fonts] Text=Times Function=Times Variable=Times,I LCGreek=Symbol,I UCGreek=Symbol Symbol=Symbol Vector=Times,B Number=Times [Sizes] Full=12pt Script=7pt ScriptScript=5pt Symbol=18pt SubSymbol=12pt
Page 10 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Coesão procedural Associa elementos de acordo com seus relacionamentos procedurais ou algorítmicos Um módulo procedural depende muito da aplicação sendo tratada
Junto com a aplicação, o módulo parece razoável Sem este contexto, o módulo parece estranho e muito difícil de entender
"O que está acontecendo aqui!!!????!!" Não pode entender o módulo sem entender o programa e as condições que existem quando o módulo é chamado Cura: reprojete o sistema
Coesão de comunicação Todas as operações de um módulo operam no mesmo conjunto de dados e/ou produzem o mesmo tipo de dado de
saída Cura: isole cada elemento num módulo separado "Não deveria" ocorrer em sistemas OO usando polimorfismo (classes diferentes para fazer tratamentos diferentes
nos dados) Coesão sequencial
A saída de um elemento de um módulo serve de entrada para o próximo elemento Cura: decompor em módulos menores
Coesão funcional (a melhor) Um módulo tem coesão funcional se as operações do módulo puderem ser descritas numa única frase de forma
coerente Num sistema OO:
Cada operação na interface pública do objeto deve ser funcionalmente coesa Cada objeto deve representar um único conceito coeso
Exemplo: um objeto que esconde algum conceito ou estrutura de dados ou recurso e onde todos os métodos são relacionados por um conceito ou estrutura de dados ou recurso
Meyer chama isso de "information-strength module"
Consequências Melhor claridade e facilidade de compreensão do projeto Simplificação da manutenção Frequentemente vai mão na mão com acoplamento fraco Com granularidade baixa e funcionalidade bem focada, aumenta o reuso
Controller
Problema Quem deveria receber a responsabilidade de tratar eventos do sistema? Um evento do sistema é um evento de alto nível gerado por um ator externo Estão associados a operações do sistema que já vimos nos Diagramas de Sequência do Sistema Exemplo do estudo de caso: Caixa pressiona "Fim de venda"
Solução Use um controlador
Um controlador é um objeto que não é de interface GUI responsável pelo tratamento de eventos do sistema Um controlador define métodos para as operações do sistema
Atribuir a responsabilidade pelo tratamento de eventos do sistema a uma classe de acordo com uma das alternativas abaixo:
Representa o "sistema" como um todo (facade controller) Representa o negócio ou organização como um todo (facade controller) Representa algo no mundo real que é ativo (por exemplo, o papel de uma pessoa) que poderia estar envolvido na
tarefa (role controller) Representa um handler artificial de todos os eventos do sistema para um Use Case particular, normalmente
chamado "<NomeDoUseCase>Handler" (use case controller)
Exemplo No estudo de caso, há várias operações de sistema:
Quem deveria ser o controlador para os eventos do sistema?
Page 11 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Pelo padrão Controller, temos as seguintes alternativas: Representa o "sistema": TPDV Representa o negócio ou organização: Loja Representa algo no mundo real ...: Caixa Representa um handler artificial ...: CompraItemHandler
A escolha particular depende de fatores discutidos na seção Discussão Por exemplo, se fosse TPDV, teríamos:
Discussão De forma geral, o mesmo controlador deve ser usado para todas as operações de um mesmo Use Case de forma a
manter a informação de estado do Use Case A informação de estado pode ser útil para detectar sequências erradas de eventos de sistema
Exemplo: façaPagamento() antes de fimDeVenda() Não coloque toda a inteligência no controlador
Delegue para outros objetos,para manter coesão Use um Handler artificial quando as outras alternativas exibem acoplamento alto ou coesão baixa
Quando está surgindo um "God class" Usado em sistemas mais complexos
Observe que classes "Window", "Applet", "Application", "View", "Document" não devem ser controladores Tais classes podem receber o evento e delegá-lo ao controlador Não se deve colocar business logic num objeto de interface com o usuário Um design correto seria:
Um design incorreto seria:
Page 12 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
O Role Controller pode levar a um mau projeto O fato de algo ser feito por uma pessoa no mundo real não necessariamente significa que isso é uma boa
alternativa em software É mais comum "dar vida aos objetos" (não animados)
Consequências Maior possibilidade de reuso, já que o business logic não está nos objetos de interface
Exemplo: embutir o business logic num objeto de interface não permitiria fazer EAI (Enterprise Application Integration)
Ajuda a verificar o sequenciamento das operações do sistema, através do estado do controlador
Responsabilidades, Role Playing e Cartões CRC
Embora não faça parte de UML, uma técnica chamada Cartões CRC é muito usada para atribuir responsabilidades durante o projeto
CRC = Class-Responsibility-Collaborations CRC cards inventadas por Ward Cunningham e Kent Beck (Tektronix)
Cartão CRC é um cartão pequeno (para só escrever o essencial) para cada classe Escreve-se o nome da classe, suas responsabilidades e colaborações
Só pense nas responsabilidades de alto nível
São desenvolvidos em pequenos grupos em que cada pessoa assume o papel (Role) de uma ou mais classes Mais detalhes aqui:
Designing Object-Oriented Software, Wirfs-Brock, Wilkerson e Wiener; Prentice Hall, 1990. Algumas pessoas acham que é melhor usar ferramentas gráficas em vez de CRC
proj1-5 programa anterior próxima
Page 13 of 13Padrões Para Atribuir Responsabilidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj5.htm
Projeto de Soluções com Objetos e Padrões
Introdução
O aluno é responsável por estudar o capítulo 19 do livro-texto (Larman) Trazer dúvidas para a aula
O capítulo utiliza padrões para atribuir responsabilidades e construir diagramas de colaboração para os seguintes Use Cases do estudo de Caso
Comprar Itens, com os seguintes eventos de sistema: entraItem fimDeVenda façaPagamento
Start Up, com o seguinte evento de sistema: startUp
Os diagramas de colaboração são resumidos abaixo
Diagramas de Colaboração
entraItem
Page 1 of 4Projeto de Soluções com Objetos e Padrões
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj6.htm
fimDeVenda
totalDeVenda Não é operação de sistema, mas necessário para o cumprir o contrato
façaPagamento Incluindo log da venda
Page 2 of 4Projeto de Soluções com Objetos e Padrões
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj6.htm
troco Não é operação de sistema, mas necessário para o cumprir o contrato
startUp Criação do objeto inicial de domínio e demais objetos
Conexão entre camadas de apresentação e de domínio
Page 3 of 4Projeto de Soluções com Objetos e Padrões
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj6.htm
proj1-6 programa anterior próxima
Page 4 of 4Projeto de Soluções com Objetos e Padrões
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj6.htm
Visibilidade
Introdução
Mensagens entre objetos só podem ocorrer se o receptor for visível ao remetente Há quatro formas básicas de visibilidade
Visibilidade de atributos Visibilidade de parâmetros Visibilidade declarada localmente Visibilidade global
Visibilidade de atributos
No estudo de caso, para que TPDV possa enviar uma mensagem a CatálogoDeProdutos, usa-se um atributo em TPDV
public class TPDV { private CatálogoDeProdutos catálogo; ... }
Visibilidade de parâmetros
Page 1 of 3Visibilidade
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj7.htm
Um objeto tem visibilidade para outro se este for recebido como parâmetro No estudo de caso, para criar uma linha de detalhe de venda, TPDV chama
criaLinhaDetalhe de Venda, passando a especificação do produto Assim, Venda tem visibilidade para a especificação de produto
A visibilidade de parâmetro frequentemente é convertida para visibilidade de atributo Exemplo: LinhaDetalheVenda recebe a especificação de produto como parâmetro no
construtor e a especificação é armazenada como atributo de LinhaDetalheVenda
Visibilidade declarada localmente
Um objeto é visível a partir de uma variável local de um método Pode inicializar a variável local com um novo objeto, receber como valor de retorno
de alguma chamada, etc. Exemplo do estudo de caso:
Page 2 of 3Visibilidade
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj7.htm
Visibilidade global
Um objeto global é visível a todos Não uma boa forma de ter visibilidade Se for obrigado a ter objetos globais, é melhor usar o padrão de projeto Singleton (GoF)
Visibilidade em UML
Uso de Stereotypes Não é usado em diagramas, normalmente
Visibilidade em Java
public para definir acesso a métodos públicos Que fazem parte da interface ao objeto para quem vai chamá-lo Não usa para atributos
private para acesso estritamente privado ao objeto (na realidade à classe) protected para definir acesso a métodos ou atributos que devem ficar disponíveis para
quem estende a classe (acessível a subclasses) "package" (sem modificador) para acesso quase público a todas as classes do package
Semelhante a friend de C++ usar com cuidado
proj1-7 programa anterior próxima
Page 3 of 3Visibilidade
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj7.htm
Diagramas de Classe para a Fase de Projeto
Introdução
Ao completar os diagramas de interação, pode-se completar o diagrama de classes Na realidade, o diagrama de classes é criado em paralelo com os diagramas de interação
No final, falta incluir alguns detalhes finais
Exemplo de um Diagrama de Classes
Diagrama de classes na fase de projeto
Deve especificar as classes de software e as interfaces da aplicação Não somente das entidades conceituais
Informação tipicamente incluída: Classes, associações e atributos Interfaces, incluindo métodos e constantes Métodos Informação de tipo de atributos Navegabilidade Dependências
Page 1 of 6Diagramas de Classe para a Fase de Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj8.htm
Como construir um diagrama de classes
1. Identificar todas as classes que participam da solução em software
Isso é feito pela análise dos diagramas de interação
2. Inclui-las num diagrama de classes
3. Duplicar os atributos, a partir das entidades associadas no modelo conceitual
4. Adicionar nomes de métodos descobertos nos diagramas de interação
5. Adicoonar informação de tipo aos atributos e métodos
6. Adicionar as associações necessárias para a visibilidade de atributos
7. Adicionar setas às associações para indicar a diração da visibilidade de atributos
8. Adicionar linhas de relações de dependência para indicar a visibilidade que não seja de atributo
Modelo conceitual versus diagrama de classes da fase de projeto
Para ambos, UML usa o diagrama de classes No modelo conceitual, uma entidade não representa uma classe de software mas um
conceito do domínio do problema No diagrama de classes da fase de projeto, as classes são de software
Criação dos diagramas de classe do estudo de caso
Identificar as classes de software Verificar todos os diagramas de interação para identificar classes Adicioná-las ao diagrama de classes, junto com os atributos Não precisa incluir classes que não participam da iteração atual
Page 2 of 6Diagramas de Classe para a Fase de Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj8.htm
Adicionar nomes de métodos Analisar os diagramas de interação para descobrir os métodos de cada classe Alguns detalhes sobre métodos
O método create() de UML não aparece em muitas linguagens, pois é uma chamada a um construtor
Muitas vezes, não se incluem os métodos acessores (getAtributo() e setAtributo()) Se classes de bibliotecas (ex. Vector em Java) são mostrados no diagrama, não se
precisa mencionar seus métodos Pode-se usar a sintaxe da linguagem de programação final, se desejado
Diagrama até agora:
Adição de informação de tipo
Este passo é opcional
Page 3 of 6Diagramas de Classe para a Fase de Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj8.htm
Se o diagrama de classes está sendo criado numa ferramenta CASE (ex. Rational Rose), e a ferramenta será usada para gerar código, todos os detalhes de tipos devem ser dados
Se o diagrama for preparado apenas para leitura por desenvolvedores, o nível de detalhamento pode ser menor
O seguinte diagrama contém toda a informação de tipo
Adicionar Associações e Navegabilidade
A navegabilidade implica visibilidade da fonte para o destino Normalmente navegabilidade de atributo, incluída na implementação
As associações devem ser apenas aquelas necessárias para a visibilidade de objetos Isso é diferente das associações no modelo conceitual, as quais podem ser incluídas
para melhorar o entendimento Os diagramas de interação são usados para descobrir a visibilidade, associações e
navegabilidade Situações comuns que levam a associações:
A envia uma mensagem a B A cria uma instância de B A deve manter conhecimento de B
Exemplo:
Page 4 of 6Diagramas de Classe para a Fase de Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj8.htm
Diagrama de classes até agora:
Adição de relações de dependência
Quando uma classe conhece outra (tem visibilidade), mas a visibilidade não é de atributo, usa-se uma linha tracejada
Exemplo: TPDV recebe um objeto da classe EspecificaçãoDeProduto como retorno do método especificação da classe TPDV
Diagrama de classes com dependências:
Incluindo detalhes de membros de classes
UML possui sintaxe para especificar: Visibilidade Valores iniciais
Page 5 of 6Diagramas de Classe para a Fase de Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj8.htm
etc. Exemplo:
proj1-8 programa anterior próxima
Page 6 of 6Diagramas de Classe para a Fase de Projeto
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj8.htm
Esquema de banco de dados e mapeamento OO-Relacional
Referências
Há uma discussão detalhada de como tratar persistência de objetos de várias formas nos livros: Object-Oriented Modeling and Design for Database Applications, Blaha e Premerlani, Prentice Hall, 1998. Database Design for Smarties, Muller, Morgan Kaufmann Publishers, 1999.
Este livro também cobre o mapeamento para SGBDs Objeto-Relacionais Nossa discussão é um breve resumo do material desses dois livros
Um tratamento completo não pode ser dado nesta disciplina devido a restrições de tempo Também tem uma breve discussão de como montar um framework de persistência no livro:
Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design, Larman, Prentice-Hall, 1998.
Frameworks profissionais de persistência podem ser vistos nos produtos TopLink e CocoBase Falaremos especialmente do mapeamento de um modelo OO para um esquema relacional
Não há tempo para tratar do mapeamento para SGBDs Objeto-Relacionais Supõe-se uma certa familiaridade com o modelo relacional
Resumo da seção
Implementação da identidade de objetos Implementação de domains Implementação de classes Implementação de operações Implementação de associações simples Implementação de associações avançadas Implementação de herança simples Implementação de herança múltipla Resumo dos passos para o mapeamento OO-Relacional
Implementação da identidade de objetos
Em SGBDOOs, objetos possuem identidade baseada na existência, mas isso não é automático num SGBDR Com um SGBDR (ou quando usam-se arquivos para a persistência), pode-se usar uma de duas alternativas:
Identidade baseada na existência O SGBDR gera um identificador único (OID) para cada registro
O OID é armazenado numa coluna adicional e é a chave primária da tabela Identidade baseada em valor
Uma combinação de atributos identifica cada registro As duas alternativas podem ser misturadas num mesmo esquema Vantagens da identidade baseada na existência
A chave primária é um atributo único, pequeno e uniforme em tamanho Algumas tabelas não possuem uma combinação de atributos que possa ser chave primária
Page 1 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Desvantagens da identidade baseada na existência Alguns SGBDs poderão não oferecer a geração de identificadores únicos A geração de identificadores únicos pode necessitar de acesso a dados globais, interferindo assim com o
controle de concorrência e deixando a aplicação potencialmente mais lenta Pode complicar a depuração das aplicações
Já que os OIDs não possuem semântica em nível de aplicação Vantagens da identidade baseada em valor
As chaves primárias possuem semântica clara em nível de aplicação, facilitando a depuração e manutenção do BD
A distribuição do BD pode ser mais fácil Porque não há geração centralizada de identidade Mas manter a unicidade das chaves pode não ser simples
Desvantagens da identidade baseada em valor Chaves primárias podem ser mais difíceis de alterar
Devido à propagação causada por chaves estrangeiras usadas em associações e herança A propagação poderá não ser suportada automaticamente pelo SGBD
Recomendações Usar identidade baseada na existência para esquemas maiores (com mais de 30 classes)
Não precisa incluir o OID como atributo no modelo UML Caso contrário, para aplicações pequenas, considere utilizar a identidade baseada em valor, ou uma
combinação das duas técnicas No modelo UML, acrescente o tag {OID} para os atributos que participam da chave primária
Há quem recomende usar identidade baseada na existência sempre
Implementação de domains
Precisamos agora pensar sobre o tipo de dados que armazenaremos no BD Que tipos serão usados nas declarações de colunas? Domains são usados para lidar com a questão
Um domain é um subconjunto nomeado dos valores possíveis para um atributo Domains:
Promovem um projeto mais consistente do que com o uso direto dos vários tipos de dados Facilitam as mudanças Ajudam a validar consultas
O padrão ANSI SQL-92 suporta o conceito de domain. Exemplo:
CREATE DOMAIN Boolean AS CHAR(1) NOT NULL DEFAULT 'T' CONSTRAINT Bool_Constraint CHECK (Boolean IN ('T', 'F'));
Pode-se assim criar domains para os tipos de dados que serão armazenados no BD Infelizmente, a maioria dos SGBDs não dá suporte a domains!
Portanto, domains são geralmente implementados: Usando cláusulas CHECK do SQL na definição dos atributos Ou usando código de aplicação
Infelizmente, esse código de verificação de domains deve ser inserido sempre que se define um atributo, já que não há suporte a domains ANSI
Para domains simples tais como nomes, Strings e valores financeiros: Use o tipo de dado apropriado e especifique um tamanho
Use tipos ANSI (CHARACTER, CHARACTER VARYING, ...) Ou use tipos do SGBD (Oracle: VARCHAR2, NUMBER, ...)
Para domains de enumeração, há 4 soluções String de enumeração: armazene o atributo de enumeração como string
Use CHECK ou código de aplicação para verificar valores Solução simples mas não pode ser estendida a muitos valores Exemplo:
CREATE TABLE Pessoa ( EstadoCivil CHARACTER(1) NULL CHECK (EstadoCivil IN ('S', 'C', 'D', 'V')) ...
Page 2 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
)
Codificação da enumeração: como acima, mas usando inteiros em vez de strings Uma tabela pode fornecer o mapeamento entre inteiros e strings correspondentes Vantagens:
Mais fácil lidar com múltiplas línguas Usam menos espaço em disco
Desvantagem (séria) Complica a depuração e manutenção (devido ao uso de "números mágicos" sem semântica
própria) Um flag por valor de enumeração: use um atributo booleano para cada valor de enumeração
Funciona bem apenas quando múltiplos valores podem ser aplicáveis (atributos não mutuamente exclusivos)
Exemplo:
CREATE TABLE xxx ( Vermelho CHARACTER(1) NULL Azul CHARACTER(1) NULL Amarelo CHARACTER(1) NULL ... )
Uma tabela de enumeração: os valores possíveis para a enumeração são armazenados numa tabela à parte
Pode haver uma tabela por enumeração ou uma tabela para todas as enumerações O código de aplicação verifica que o valor do atributo pertence à tabela Boa solução quando há muitos valores Vantagem de ter os valores possíveis no próprio BD em vez de tê-los no código Novos valores podem ser inseridos facilmente, sem modificar o código Mas tabelas adicionais complicam o esquema e o código genérico de manipulação
Para pequenas enumerações, é mais fácil usar strings e um constraint em SQL Use quando há muitos valores ou valores desconhecidos durante o desenvolvimento Exemplo:
CREATE TABLE TipoEstadoCivil ( Valor CHAR(1) PRIMARY KEY, DisplayString VARCHAR2(50) NOT NULL, Descricao VARCHAR2(2000)); INSERT INTO TipoEstadoCivil (Valor, DisplayString) VALUES ('S', 'Solteiro'); INSERT INTO TipoEstadoCivil (Valor, DisplayString) VALUES ('C', 'Casado'); INSERT INTO TipoEstadoCivil (Valor, DisplayString) VALUES ('D', 'Divorciado'); INSERT INTO TipoEstadoCivil (Valor, DisplayString) VALUES ('V', 'Viuvo'); ) CREATE TABLE Pessoa ( EstadoCivil CHARACTER(1) NOT NULL DEFAULT 'U' REFERENCES TipoEstadoCivil(Valor), ... )
Para domains estruturados, há três alternativas, todas válidas em certas situações Concatenação: jogue fora a estrutura e armazene o atributo como string
Exemplo Uma Pessoa tem um Endereço O Endereço é um domain estruturado (possui vários atributos)
Page 3 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Armazene o endereço inteiro como string Múltiplas colunas
O Endereço seria armazenado na tabela Pessoa em colunas diferentes Tabela separada
Pessoa referencia um registro da tabela Endereço Para domains multivalorados, use as técnicas de domains estruturados
Não há suporte especial do modelo relacional, porque domains multivalorados não obedecem a primeira forma normal
Implementação de classes
No modelo de projeto, algumas classes são persistentes e outras não As classes persistentes têm o estereótipo UML «persistent»
Tratamos aqui apenas das classes persistentes As demais definem um comportamento transiente que deve ser tratado no código da aplicação
Uma classe contém atributos e operações Discutiremos o que fazer com as operações na próxima subseção
De forma geral, cada classe persistente se transforma numa tabela e cada atributo se transforma numa coluna da tabela
Para cada tabela, trata-se a questão de identidade vista acima Para cada atributo, trata-se a questão de domains vista acima O modelo relacional não trata a visibilidade dos atributos
Todos os atributos são públicos Para atributos que têm tag UML {OID}, use um constraint PRIMARY KEY Para atributos que têm tag UML {alternate OID} (alternate key), use um constraint UNIQUE Para atributos que têm tag UML {nullable}, não use o constraint NOT NULL, caso contrário, use NOT NULL
Alguns SGBDs permitem que você use o constraint NULL que não faz parte do padrão ANSI na definição de colunas
Implementação de operações
Um SGBD Relacional não permite encapsular operações (métodos) com classes Por outro lado, stored procedures são possíveis, o que permite colocar alguma funcionalidade dos métodos
dos objetos da aplicação no SGBD Alguns SGBDs oferecem também stored functions que retornam valor
A questão básica é: "Que tipo de funcionalidade pode ser adequadamente colocada em stored procedures?" No final das contas, podemos particionar o código entre o servidor de BD e as outras camadas (middle
tier, cliente) O que é melhor colocar no SGBD e o que é melhor deixar fora?
Algumas regras sobre o que evitar seguem: Não se pode colocar operações que lidam com aspectos transientes no SGBD
O código de stored procedures não pode acessar os objetos que estão em memória nas outras camadas
Não se deve usar stored procedures para acessar dados atributo por atributo Um SGBDR acessa dados naturalmente por registro, não por atributo individual O acesso ao BD atributo por atributo resultaria numa aplicação muito lenta
Evite stored procedures que tenham que deixar "estado transiente" armazenado no BD para fazer outras operações subsequentes (não armazenar estado comportamental usado entre chamadas)
Embora alguns SGBDs (Oracle, por exemplo) permitam que isso seja feito, é melhor que cada chamada a um stored procedure seja reentrante e não dependa de estado
O sistema resultante é muito mais simples e fácil de manter e depurar Tal tipo de estado deve ser mantido na camada do meio (aplicação)
Evite fazer grandes quantidades de verificação de erro, com condições de aborto, etc. no SGBD. Mantenha isso em outra camada (aplicação ou cliente)
Algumas operações de alto desempenho poderão ser mais rápidas quando executadas numa linguagem compilada (em outra camada), em vez de uma linguagem interpretada para executar stored procedures (como PL/SQL do Oracle, Transact/SQL do SQLServer)
Evite fazer ações transacionais (COMMIT, ROLLBACK) em stored procedures Faça isso em outra camada A semântica de transação é expressa melhor na aplicação em si
Seria ruim um programador chamar um stored procedure e, depois, ao verificar um erro e tentar
Page 4 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
fazer um ROLLBACK, descobrir que a transação já sofreu COMMIT O que pode ser colocado no SGBD como stored procedures?
Fazer uma consulta dando um result set (um conjunto de registros) Insert/update/delete, mas apenas de registros inteiros, não atributo por atributo Verificação de regras de consistência e outros business rules
Talvez este seja o motivo principal do uso de Stored Procedures Triggers podem ser valiosos aqui também
Operações que chamam outros stored procedures (para acessar o dicionário, por exemplo) Verificação de erros (mas apenas erros relacionados com a estrutura do BD)
Como tratar polimorfismo? Ao usar um SGBDR, não há suporte a polimorfismo
Mesmo SGBDORs têm suporte fraco ou inexistente a polimorfismo Evite-o portanto, nas classes persistentes
Pode usar em classes transientes Se o polimorfismo for usado na modelagem de classes persistentes, ele tem que ser transformado em if-
then-else e chamadas as stored procedures diferentes Todas essas restrições explicam porque se fala do impedance mismatch!
Implementação de associações simples
Associações simples são: 1-para-1 0..1-para-1 1-para-muitos muitos-para-muitos
Descrevemos mapeamentos recomendados, alternativos e desencorajados para cada tipo Sempre considere primeiro o mapeamento recomendado Mapeamentos alternativos podem ser usados por uma questão de desempenho, extensibilidade, ou
estilo
Associações 1-para-1 Recomendado
Embutir a chave estrangeira em qualquer uma das classes A chave estrangeira poderá ser nula se houver uma cardinalidade mínima de 0 no alvo
Alternativo A associação pode ser implementada numa tabela à parte A chave primária da tabela de associação pode ser qualquer uma das duas chaves estrangeiras Vantagem: o esquema é mais extensível
Se houver mudança na cardinalidade da associação, basta mudar o constraint, não a estrutura de tabelas
Desvantagens: fragmentação do esquema e maior overhead de navegação (com joins) Desencorajado
Combinação: não junte duas classes e sua associação numa única tabela O esquema é mais fácil de entender se seguir o modelo de objetos
Associações bi-direcionais: não coloque duas chaves estrangeiras, uma em cada tabela referenciando a outra
Os SGBDs não vão manter a consistência das associações redundantes
Associações 0..1-para-1 Recomendado
Embutir a chave estrangeira na classe com a cardinalidade 0..1 A chave estrangeira é NOT NULL
Associações 1-para-muitos Recomendado
Embutir a chave estrangeira na classe com cardinalidade "muitos" Se a cardinalidade 1 (do alvo) puder ser 0-1, a chave estrangeira pode se nula Exemplo:
Page 5 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Alternativo A associação pode ser implementada numa tabela à parte A chave estrangeira para a classe "muitos" é a chave primária da tabela de associação Mesmas vantagens e desvantagens do mapeamento 1-para-1 Exemplo:
Associações muitos-para-muitos Recomendado
A associação é mapeada para uma tabela distinta A chave primária da tabela de associação é uma combinação das chaves estrangeiras Exemplo:
Implementação de associações avançadas
Associações avançadas são: Associação qualificada Classe de associação Associação ordenada Associação ternária
Associação qualificada Lembre que uma associação qualificada é uma associação "para-muitos" onde os objetos envolvidos do lado
"muitos" são total ou parcialmente especificados usando um atributo chamado o qualificador Tais associações aumentam a precisão do modelo Um qualificador seleciona um ou mais dentre vários objetos-alvo, com o efeito de reduzir a cardinalidade,
às vezes até 1 Quando a cardinalidade final é 1, a associação qualificada especifica uma forma precisa de selecionar o
objeto alvo a partir do objeto fonte Exemplo:
Uma descrição de vôo se aplica a muitos vôos A combinação de uma descrição de vôo mais uma data de partida especifica um vôo
Page 6 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Recomendado O mapeamento é tal qual para a associação sem qualificador No exemplo acima, uma chave estrangeira seria incluída na classe Vôo
Classe de associação É uma associação com uma classe que a descreve A classe de associação pode participar de outras associações Recomendado
Implemente a associação com uma tabela distinta A chave primária da classe de associação é uma combinação das chaves primárias das classes
envolvidas na associação Exemplo:
Associação ordenada Ocorre quando as ligações entre objetos possuem uma ordem Exemplo: janelas podem estar ordenadas numa tela (indicando qual está na frente das outras) O tag UML {ordered} é usado na associação ( ou {ordered by ...}) Recomendado
Introduzir um número de sequência como atributo
Associação ternária Exemplo:
Page 7 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Recomendado Uma tabela distinta deve ser usada para representar a associação ternária
Agregações Recomendado
Agregações são associações e são implementadas como tal
Implementação de herança simples (generalização)
Recomendado Normalmente, a herança é implementada com tabelas separadas para a superclasse e cada subclasse Idealmente, um objeto tem a mesma chave primária na hierarquia inteira A superclasse inclui um discriminador que indica qual subclasse se aplica
Isso não é mostrado no modelo de objetos A integridade referencial pode ser usada para garantir que um registro da superclasse exista para cada
registro de uma subclasse Entretanto, se a superclasse for abstrata e exigir que haja um objeto de uma subclasse, a
integridade referencial não pode solucionar o problema O código da aplicação deve implementar a restrição
Exemplo:
Pode-se usar uma View para cada subclasse, no sentido de consolidar os dados herdados e facilitar o acesso ao objeto
Exemplo:
Page 8 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
CREATE VIEW view_PagamentoCC AS SELECT pagamentoID, valor, tipoCC, numeroCC FROM Pagamento AS P JOIN PagamentoCC as CC ON P.pagamentoID = CC.pagamentoCCID
Alternativo Eliminação
Como otimização, subclasses que não contêm atributos, fora a chave estrangeira, podem ser eliminadas
Desvantagens O código de navegação tem que saber se há uma tabela ou não para implementar a subclasse Falta de extensibilidade: se houver uma adição à subclasse, a tabela vai ter que voltar
Exemplo:
Empurrar atributos da superclasse para baixo Elimine a superclasse e duplique seus atributos para cada subclasse Uma única tabela contém todos os dados de um objeto (não há necessidade de join para reconstituir
um objeto) Desvantagens
Introduz redundância no esquema Poderá ser necessário pesquisar várias tabelas para achar um objeto Se vários níveis de hierarquia estiverem envolvidos, a estrutura da generalização (herança) é
perdida Exemplo:
Page 9 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Empurrar atributos da subclasse para cima
Neste caso, as subclasses são eliminadas e todos seus atributos migram para a tabela da superclasse
Atributo desnecessários para certos objetos são nulos Essa alternativa viola a segunda forma normal porque alguns atributos não dependem
completamente da chave primária Exemplo:
Abordagem híbrida Empurrar os atributos da superclasse para baixo mas manter a tabela da superclasse para navegar
nas subclasses Exemplo:
Page 10 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
Tabela de generalização Semelhante ao mapeamento recomendado (tabelas para superclasse e subclasses) mas adicionando
uma tabela de generalização que amarra a chave primária da superclasse à chave primária da subclasse
A chave primária das subclasses é a chave "natural" da tabela e não mais a mesma da superclasse como no mapeamento recomendo inicial
Implementação de herança múltipla
Recomendado Usar o mapeamento recomendado acima (tabelas distintas para superclasse e subclasses)
Resumo dos passos para o mapeamento OO-Relacional
1. Cada classe UML é mapeada para uma tabela
2. Cada atributo da clase é uma coluna da tabela
3. O tipo do atributo é mapeado para um tipo da coluna, de acordo com regras de transformação de tipos
4. Se o atributo tem o tag UML {nullable}, a coluna tem constraint NULL; caso contrário, tem constraint NOT NULL
5. Se o atributo UML tem um inicializador, adicionar a cláusula DEFAULT à coluna
6. Para cada classe sem generalização (é raiz de hierarquia ou não participa de hierarquia) e com identidade baseada na existência, criar uma chave primária inteira; com identidade baseada em valor, adicionar as colunas com tag UML {OID} ao constraint PRIMARY KEY
7. Para subclasses com uma única superclasse com chave primária de uma coluna, adicionar a chave da superclasse ao constraint PRIMARY KEY e adicionar uma cláusula REFERENCES para relacionar a coluna (chave estrangeira) à chave primária da superclasse
8. Para subclasses com uma única superclasse com chave primária de várias colunas, use constraints de tabela PRIMARY KEY e FOREIGN KEY em vez do constraint de coluna do item anterior
9. Para herança múltipla, adicione uma coluna na subclasse para cada chave primária de cada superclasse; adicione um constraint de tabela FOREIGN KEY com todas essas colunas (que referenciam chaves primárias das superclasses)
0. Para classes de associação, adicione uma coluna para a chave primária de cada classe participando da
Page 11 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
associação; use um constraint FOREIGN KEY
1. Para tags UML {alternate OID}, adicione as colunas envolvidas ao constraint UNIQUE
2. Adicione CHECK para cada constraint explícito
3. Crie tabelas para as associações que não usam chaves estrangeiras embutidas (muitos-para-muitos, ternárias, ...), e use constraint de tabela FOREIGN KEY
4. Para agregações, use a opção ON DELETE CASCADE, ON UPDATE CASCADE na tabela agregadora
proj1-9 programa anterior
Page 12 of 12Esquema de banco de dados e mapeamento OO-Relacional
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj1\proj9.htm
5. Fase de Implementação Mapeamento do projeto para código Programa exemplo em Java Testes de unidade Adicionando uma interface com o usuário
impl programa
Page 1 of 15. Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\index.htm
Mapeamento do Projeto para Código
Com os artefatos já produzidos, estamos prontos para implementar (codificar e testar) A codificação é feita a partir dos artefatos de projeto
Diagramas de colaboração e diagrama de classes Deve-se codificar depois de um esforço suficiente de análise e projeto
Porque explorar alternativas é mais barato em fases anteriores No entanto, alguma atividade de prototipagem pode ser feita em fases anteriores Em termos de maturidade de processo de desenvolvimento, codificar cedo demais não
leva a um processo que possa ser repetido Os riscos são muito maiores
A atividade de codificação em si é uma tradução bastante mecânica dos modelos produzidos
A criatividade não ocorre durante a codificação mas antes dela Porém, a codificação frequentemente leva a modificações em decisões anteriores
Portanto, depois da codificação, os artefatos já produzidos devem ser sincronizados com o código
Uma ferramenta CASE que faz Engenharia Reversa pode ajudar aqui Ela lê o código e produz diagramas de modelos
Mapeamento do projeto para código
Deve-se escrever: Código para interfaces e classes Código para os métodos
Criação de definições de interfaces e classes Feita a partir de diagramas de classes Os passos são simples, lembrando que tipos suportados pela linguagem devem ser
escolhidos A navegabilidade indica que atributos referenciando outros objetos devem ser incluídos
na classe É desejável chamar o atributo pelo papel assumido pelo destino da associação
Page 1 of 2Mapeamento do Projeto para Código
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl1.htm
Criação de métodos Feita a partir dos diagramas de colaboração, examinando as mensagens enviadas entre
os objetos
Atualização das definições de classes Após a codificação (e testes), as definições de classes são alteradas para incluir novos
métodos introduzidos, etc.
Tratamento de erros Embora tenhamos nos concentrado na atribuição de responsabilidades, a atividade de
projeto deve também considerar como será feito o tratamento de erros Normalmente usa o mecanismo de exceções Uma parte significativa do código diz respeito ao tratamento de erros
Ordem de implementação Classes individuais devem ser codificadas e sujeitas a testes de unidade na ordem da
menos acoplada à mais acoplada Para minimizar scaffolding
Uma ordem sugerida no estudo de caso seria como mostrado abaixo
impl-1 programa próxima
Page 2 of 2Mapeamento do Projeto para Código
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl1.htm
Programa Exemplo em Java
O código abaixo não inclui sincronização devido a acessos concorrentes, nem tratamento de persistência O código abaixo é diferente do código do livro
Usa interfaces para desacoplar classes Apenas as interfaces externas foram definidas de forma a produzir a documentação externa de quem usa as classes (ver
documentação externa) Outras interfaces (internas) poderiam ser definidas para ter mais polimorfismo dentro do pacote
Inclui comentários javadoc para produzir documentação automaticamente Alguns modificadores de acesso (public, ...) foram alterados Usa Factory Methods (ver Design Patterns, em outro capítulo) Alguns métodos faltam no livro
Exemplo: Loja tem que ter um getCatálogoDeProdutos(), senão a camada de interface com o usuário não consegue obter a descrição de um produto com dado UPC para exibir ao cliente
Está em português Acentuação é usada em atributos e métodos mas não em nomes de classes e interfaces porque, neste último caso, o nome do
arquivo é igual à classe/interface e quero evitar acentuação em nomes de arquivos (portabilidade) Tem tratamento de erro completo com 3 tipos de exceções
Falta tratar mais um ou dois erros possíveis que estou deixando para o aluno descobrir (e tratar!) O resultado é um código mais profissional
Porém, as coisas sempre podem ser melhoradas Por exemplo: o uso de float para representar valores monetários não foi uma boa decisão do autor Larman
Por quê? Como você faria?
Documentação
A documentação externa está aqui Observe que nesta documentação, há apenas a informação que pode ser usada "de fora", isto é, pelas classes da interface do usuário O único objeto que pode ser criado é uma Loja A partir da Loja, pode-se obter um TPDV, ou um catálogo de produtos para fazer as outras operações associada à interface com o
usuário A documentação interna está aqui
Útil para os desenvolvedores do pacote
Interface IPagamento
package tpdv; /** * Interface para qualquer tipo de pagamento. * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ interface IPagamento { /** * Retorna o valor entregue pelo cliente para pagar a venda. * @return O valor entregue pelo cliente para pagar a venda. */ float getValor(); }
Classe Pagamento
package tpdv; /** * Classe que representa um pagamento feito para uma venda.
Page 1 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
* * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ class Pagamento implements IPagamento { /** * O valor do pagamento de uma venda. */ private float valor; /** * Cria um pagamento. * @param valorEntregue O valor entregue para pagar a venda. */ public Pagamento(float valorEntregue) { this.valor = valorEntregue; } /** * Cria um pagamento. * @param valorEntregue O valor entregue para pagar a venda. */ public Pagamento(double valorEntregue) { this.valor = (float)valorEntregue; } /** * Retorna o valor entregue para pagar a venda. * @return O valor entregue para pagar a venda. */ public float getValor() { return valor; } }
Interface IEspecProduto
package tpdv; /** * Interface para qualquer tipo de especificação de produto. * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public interface IEspecProduto { /** * Obtem o Universal Product Code (UPC) do produto. * @return O Universal Product Code (UPC) do produto. */ int getUPC(); /** * Obtem o preço do produto. * @return O preço do produto. */ float getPreço(); /** * Obtem a descrição do produto. * @return A descrição do produto. */ String getDescrição(); }
Classe EspecificacaoDeProduto
package tpdv; /** * Classe que representa uma especificação de um produto do catálogo de produtos. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ class EspecificacaoDeProduto implements IEspecProduto { /** * O Universal Product Code (UPC) do produto.
Page 2 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
*/ private int upc; /** * O preço do produto. */ private float preço; /** * A descrição do produto. */ private String descrição; /** * Cria uma especificação de produto. * @param upc O Universal Product Code do produto. * @param preço O preço do produto. * @param descrição A descrição do produto. */ public EspecificacaoDeProduto(int upc, float preço, String descrição) { this.upc = upc; this.preço = preço; this.descrição = descrição; } /** * Cria uma especificação de produto. * @param upc O Universal Product Code do produto. * @param preço O preço do produto. * @param descrição A descrição do produto. */ public EspecificacaoDeProduto(int upc, double preço, String descrição) { this(upc, (float)preço, descrição); } /** * Obtem o Universal Product Code do produto. * @return O Universal Product Code do produto. */ public int getUPC() { return upc; } /** * Obtem o preço do produto. * @return O preço do produto. */ public float getPreço() { return preço; } /** * Obtem a descrição do produto. * @return A descrição do produto. */ public String getDescrição() { return descrição; } }
Interface ICatalogoDeProdutos
package tpdv; /** * Interface para qualquer tipo de Catálogo de Produtos * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public interface ICatalogoDeProdutos { /** * Obtem a especificação de produto, dado o Universal Product Code (UPC) * @param upc O Universal Product Code (UPC) do produto desejado * @return A especificação de produto, dado o Universal Product Code (UPC) */ public IEspecProduto getEspecificação(int upc) throws ProdutoInexistenteException; }
Classe CatalogoDeProdutos
package tpdv; import java.util.*;
Page 3 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
/** * Classe que representa um catálogo de produtos. * Um catálogo contém várias especificações de produtos. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ class CatalogoDeProdutos implements ICatalogoDeProdutos { /** * O catálogo de produtos é guardado aqui. */ private Map especsProdutos = new HashMap(); /** * Cria um catálogo de produtos. Esta versão não trata de persistência. * O catálogo é fixo e criado no construtor. */ public CatalogoDeProdutos() { int upc1 = 100; especsProdutos.put(new Integer(upc1), makeEspecProduto(upc1, (float)1.99, "produto 1")); int upc2 = 200; especsProdutos.put(new Integer(upc2), makeEspecProduto(upc2, (float)3.49, "produto 2")); } /** * Obtém a especificação de um produto. * @param upc o Universal Product Code do produto cuja especificação se deseja. * @return A especificação do produto desejado. */ public IEspecProduto getEspecificação(int upc) throws ProdutoInexistenteException { IEspecProduto espec = (IEspecProduto)especsProdutos.get(new Integer(upc)); if(espec == null) { throw new ProdutoInexistenteException("Produto inexistente, UPC: " + upc); } return espec; } // factory method protected IEspecProduto makeEspecProduto(int upc, float preço, String descrição) { return new EspecificacaoDeProduto(upc, preço, descrição); } }
Classe ProdutoInexistenteException
package tpdv; /** * Exceção indicando produto inexistente no catálogo de produtos. * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public class ProdutoInexistenteException extends TPDVException { /** * Cria uma exceção de produto inexistente * @param mensagem Mensagem de erro imprimível */ public ProdutoInexistenteException(String mensagem) { super(mensagem); } }
Interface ILinhaDetalhe
package tpdv; /** * Interface para qualquer tipo de linha de detalhe de uma venda. * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */
Page 4 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
interface ILinhaDetalhe { /** * Retorna o subtotal da venda para os itens correspondendo a esta linha de detalhe. * @return O subtotal da venda para os itens correspondendo a esta linha de detalhe. */ float subTotal(); }
Classe LinhaDetalheVenda
package tpdv; /** * Classe que representa uma linha de detalhe de uma venda. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ class LinhaDetalheVenda implements ILinhaDetalhe { /** * A quantidade de itens (do mesmo produto) neste detalhe de venda. */ private int quantidade; /** * A especificação do produto sendo comprado. */ private IEspecProduto espec; /** * Cria uma linha de detalhe de uma venda. * @param espec A especificação do produto sendo comprado. * @param quantidade A quantidade de itens (do mesmo produto) sendo comprados */ public LinhaDetalheVenda(IEspecProduto espec, int quantidade) { this.espec = espec; this.quantidade = quantidade; } /** * Informa o subtotal da venda correspondendo a esta linha de detalhe. * @return O subtotal da venda correspondendo a esta linha de detalhe. */ public float subTotal() { return quantidade * espec.getPreço(); } }
Interface IVenda
package tpdv; /** * Interface externa para qualquer tipo de venda. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public interface IVenda { /** * Retorna o troco da venda, após fazer um pagamento de uma venda. * @return o troco da venda, após fazer um pagamento de uma venda. */ float getTroco(); /** * Retorna o valor total da venda, até agora. * @return o valor total da venda, até agora. */ float total(); }
Classe Venda
package tpdv;
Page 5 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
import java.util.*; /** * Classe que representa uma venda de produtos feita através de um TPDV. * Uma venda é composta de várias linhas de detalhe. * Enquanto a venda não terminou, tais linhas de detalhe podem ser criadas. * Um pagamento pode ser feita para pagar a venda. * Pode-se calcular o troco a ser entregue ao cliente. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ class Venda implements IVenda { /** * As linhas de detalhe da venda. */ private List linhasDetalhe = new Vector(); /** * A data da venda. */ private Date data = new Date(); // hoje /** * Indica se a venda terminou. */ private boolean isTerminada = false; /** * O pagamento efetuado para a venda. */ private IPagamento pagamento; /** * Calcula o valor total da venda. * @return O valor total da venda. */ public float total() { float total = (float)0.0; Iterator it = linhasDetalhe.iterator(); while(it.hasNext()) { total += ((ILinhaDetalhe)it.next()).subTotal(); } return total; } /** * Calcule o troco para a venda, após um pagamento. * @return O troco para a venda. */ public float getTroco() { return pagamento.getValor() - total(); } /** * Chamado para indicar que a venda terminou. */ void terminou() { isTerminada = true; } /** * Obtém o status da venda. * @return true se a venda terminou; false caso contrário. */ boolean isTerminada() { return isTerminada; } /** * Cria uma linha de detalhe para a venda. * @param espec A especificação do produto sendo comprado. * @param quantidade A quantidade de itens (do mesmo produto) sendo comprados. */ void criaLinhaDetalhe(IEspecProduto espec, int quantidade) { linhasDetalhe.add(makeLinhaDetalhe(espec, quantidade)); } /**
Page 6 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
* Faz um pagamento para a venda. * @param valorEntregue O valor entregue pelo cliente para pagar a venda. */ void façaPagamento(float valorEntregue) throws PagamentoInsuficienteException { if(valorEntregue < total()) { throw new PagamentoInsuficienteException("Pagamento insuficiente"); } pagamento = makePagamento(valorEntregue); } // factory methods protected ILinhaDetalhe makeLinhaDetalhe(IEspecProduto espec, int quantidade) { return new LinhaDetalheVenda(espec, quantidade); } protected IPagamento makePagamento(float valorEntregue) { return new Pagamento(valorEntregue); } }
Classe NaoHaVendaException
package tpdv; /** * Exceção indicando operação necessitando de venda sem venda ativa * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public class NaoHaVendaException extends TPDVException { /** * Cria uma exceção de operação necessitando de venda sem venda ativa * @param mensagem Mensagem de erro imprimível */ public NaoHaVendaException(String mensagem) { super(mensagem); } }
Classe PagamentoInsuficienteException
package tpdv; /** * Exceção indicando pagamento insuficiente para uma venda. * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public class PagamentoInsuficienteException extends TPDVException { /** * Cria uma exceção de pagamento insuficiente * @param mensagem Mensagem de erro imprimível */ public PagamentoInsuficienteException(String mensagem) { super(mensagem); } }
Interface ITPDV
package tpdv; /** * Interface para qualquer tipo de Terminal Ponto De Venda (TPDV). * Um TPDV é usado para fazer uma venda (uma única venda de cada vez). * Itens podem ser comprados até o final da venda. * Um pagamento pode ser feito para a venda corrente. * * @author Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public interface ITPDV { /**
Page 7 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
* Obtém a venda corrente sendo realizada pelo TPDV. * @return A venda corrente sendo realizada pelo TPDV. */ IVenda getVenda(); /** * Chamado para indicar que a venda terminou. */ void fimDeVenda() throws NaoHaVendaException; /** * Chamado para adicionar à venda corrente um número de itens sendo comprados. * @param upc O Universal Product Code do item sendo comprado. * @param quantidade O número de itens sendo comprados. */ void entraItem(int upc, int quantidade) throws ProdutoInexistenteException; /** * Realiza um pagamento para uma venda. * @param valorEntregue O valor entregue pelo cliente para pagar a venda. */ void façaPagamento(float valorEntregue) throws PagamentoInsuficienteException; }
Classe TPDV
package tpdv; /** * Classe que implementa um Terminal Ponto De Venda (TPDV). * Um TPDV é usado para fazer uma venda (uma única venda de cada vez). * Itens podem ser comprados até o final da venda. * Um pagamento pode ser feito para a venda corrente. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ class TPDV implements ITPDV { /** * O catálogo de produtos que podem ser vendidos neste TPDV. */ private ICatalogoDeProdutos catálogo; /** * A venda corrente sendo realizada no TPDV. */ private IVenda venda; /** * Cria um TPDV. * @param catálogo Um catálogo de produtos que podem ser adquiridos neste TPDV. */ public TPDV(ICatalogoDeProdutos catálogo) { this.catálogo = catálogo; venda = null; } /** * Obtém a venda corrente sendo realizada no TPDV. * @return A venda corrente sendo realizada no TPDV. */ public IVenda getVenda() { return venda; } /** * Quando chamado, indica que a venda corrente sendo realizada no TPDV terminou. */ public void fimDeVenda() throws NaoHaVendaException { if(venda == null) { throw new NaoHaVendaException("Nao ha venda iniciada"); } venda.terminou(); } /** * Informa um produto e a quantidade de itens deste produto sendo comprados na venda corrente.
Page 8 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
* Caso a venda anterior já tenha terminado, uma nova Venda é criada. * @param upc O Universal Product Code (UPC) do produto sendo comprado. * @param quantidade A quantidade de itens sendo comprados. */ public void entraItem(int upc, int quantidade) throws ProdutoInexistenteException { if(isNovaVenda()) { venda = makeVenda(); } venda.criaLinhaDetalhe(catálogo.getEspecificação(upc), quantidade); } /** * Realiza um pagamento para a venda corrente do TPDV. * @param valorEntregue O valor entregue pelo cliente para pagar a venda. */ public void façaPagamento(float valorEntregue) throws PagamentoInsuficienteException { venda.façaPagamento(valorEntregue); } // visibilidade de package para poder testar boolean isNovaVenda() { return venda == null || venda.isTerminada(); } // factory method protected IVenda makeVenda() { return new Venda(); } }
Classe Loja
package tpdv; /** * Classe que implementa uma Loja. Cada loja tem um catálogo de produtos e um único TPDV. * * @author Craig Larman, Jacques Philippe Sauvé, [email protected] * @version 1.0 */ public class Loja { /** * O catálogo de produtos da loja. */ private ICatalogoDeProdutos catálogo; /** * O terminal ponto de venda (TPDV) da loja. * Uma loja só tem um único TPDV. */ private ITPDV tpdv; /** * Cria uma loja. O catálogo de produtos e o TPDV são automaticamente criados. * @param valorEntregue O valor entregue para pagar a venda. */ public Loja() { catálogo = makeCatálogo(); tpdv = makeTPDV(catálogo); } /** * Obtem o TPDV da loja. * @return O TPDV da loja. */ public ITPDV getTPDV() { return tpdv; } /** * Obtem o TPDV da loja. * @return O TPDV da loja. */ public ICatalogoDeProdutos getCatálogoDeProdutos() { return catálogo; } // factory methods protected ICatalogoDeProdutos makeCatálogo() { return new CatalogoDeProdutos(); } protected ITPDV makeTPDV(ICatalogoDeProdutos catálogo) {
Page 9 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
return new TPDV(catálogo); } }
impl-2 programa anterior próxima
Page 10 of 10Fase de Implementação
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl2.htm
Testes de Unidade
Justificativa
Reduzir defeitos (bugs) apresentados pelo produto Cobrir uma gama maior de equipamentos e ambientes operacionais do que aqueles disponíveis na empresa
através de testes em clientes Assegurar a qualidade final do produto para o cliente, incluindo avaliação de embalagem, manuais,
usabilidade, etc.
Estágios de testes
Testes são feitos em vários estágios Fazer testes monolíticos do produto inteiro aumentaria o tempo necessário à depuração total do software É melhor (mais rápido) testar partes menores para depois testar a integração dessas partes Determinados testes devem ser feitos por pessoas fora da equipe de desenvolvimento no sentido de manter a
maior objetividade possível nessas fases de testes e no sentido de envolver também os usuários finais fora da empresa
Automatização de testes
Os testes devem ser automatizados Pelo menos nas fases em que isso é possível
Scripts de testes desenvolvidos ao longo do tempo aumentam o patrimônio da empresa e garantirão uma qualidade cada vez maior
Tipos de testes
Testes de unidade Para testar classes individuais Feito pelo próprio programador da classe Testa toda a interface da classe
Testes funcionais Para testar os Use Cases Feito pelo time de desenvolvimento
Testes de sistema Uso de Total System Environment
Incluindo outros produtos de software, todas as plataformas, todas as configurações, etc. Feito por uma equipe independente de testes
Testes de regressão Antes de por o sistema na rua, mesmo que tenha havido apenas uma recompilação Normalmente um subconjunto dos testes de sistema
Teste alfa Teste de produto (com embalagem manual, etc.) num "cliente" dentro da empresa
Teste beta Como teste alfa mas incluindo clientes fora da empresa
Page 1 of 3Testes de Unidade
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl3.htm
Testes de Unidade
Necessidade de automação Clica um botão a qualquer momento para testar tudo! Pelo menos um teste por dia (frequentemente vários testes por hora)
Uso de um framework de testes Desenvolvimento e testes em paralelo Absolutamente necessário ter testes de unidade, principalmente se fizer refactoring de código Testar as classes da menos acoplada para a mais acoplada
Na realidade, segue a ordem de desenvolvimento Desenvolvimento e testes de unidade feitos em paralelo!
Exemplo com o framework JUnit (teste da classe Venda) Neste pacote, leia o artigo "Test Infected: Programmers Love Writing Tests" Escrito por Beck (CRC, Extreme Programming) e Gamma (GoF) Todos os testes estão aqui para o código do capítulo anterior
package tpdv; import junit.framework.*; import tpdv.*; /** * Testes da classe Venda. * */ public class TestaVenda extends TestCase { protected IVenda venda1; protected IEspecProduto ep1; protected IEspecProduto ep2; protected IEspecProduto ep3; public TestaVenda(String name) { super(name); } public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } protected void setUp() { venda1 = new Venda(); ep1 = new EspecificacaoDeProduto(100, 1.99, "prod1"); ep2 = new EspecificacaoDeProduto(200, 2.99, "prod2"); ep3 = new EspecificacaoDeProduto(300, 3.99, "prod3"); } public static Test suite() { return new TestSuite(TestaVenda.class); } public void testConstrutor() { assert("1", !venda1.equals(null)); assertEquals("2", 0.0, venda1.total(), 0.0); assert("3", !venda1.isTerminada()); } public void testManipulacao() { venda1.criaLinhaDetalhe(ep1, 1); assertEquals("1", 1.99, venda1.total(), 0.001); venda1.criaLinhaDetalhe(ep2, 2); assertEquals("2", 1.99+(2*2.99), venda1.total(), 0.001); venda1.criaLinhaDetalhe(ep3, 2); assertEquals("3", 1.99+(2*2.99)+(2*3.99), venda1.total(), 0.001); try { venda1.façaPagamento((float)5.0); fail("facaPagamento(5.0) deveria gerar exception"); } catch(PagamentoInsuficienteException e) {
Page 2 of 3Testes de Unidade
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl3.htm
} try { venda1.façaPagamento((float)20.0); } catch(PagamentoInsuficienteException e) { fail("facaPagamento(20.0) nao deveria gerar exception"); } assertEquals("4", 20-1.99-(2*2.99)-(2*3.99), venda1.getTroco(), 0.001); assert("3", !venda1.isTerminada()); venda1.terminou(); assert("3", venda1.isTerminada()); } }
Algumas palavras de Beck e Gamma
Sometimes you just won't feel like writing tests, especially at first. Don't. However, pay attention to how much more trouble you get into, how much more time you spend debugging, and how much more stress you feel when you don't have tests. We have been amazed at how much more fun programming is and how much more aggressive we are willing to be and how much less stress we feel when we are supported by tests. The difference is dramatic enough to keep us writing tests even when we don't feel like it.
impl-3 programa anterior próxima
Page 3 of 3Testes de Unidade
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl3.htm
Adicionando uma Interface com o Usuário
Interface com o usuário
O business logic estando pronto e testado, podemos fazer uma interface com o usuário Pode-se fazer uma interface em 1 camada, 2 camadas, com applets, 3 camadas com servlets ou JSP, 4 camadas com RMI,
etc. Observe que o business logic não muda para qualquer tipo de interface Ao ver o código da interface com o usuário, observe que a lógica é só de apresentação e de verificação de dados de entrada Uma interface Swing em 1 camada pode ser vista aqui
Está no package tpdvui Foi feita com JBuilder 3.0
A interface parece é a seguinte:
A interface não é muito funcional e merece ser repensada
Alguns trechos de código
A classe principal
public class Tpdv { public Tpdv() { TpdvFrame frame = new TpdvFrame(); // ... um monte de coisinhas frame.setVisible(true); } public static void main(String[] args) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { } new Tpdv(); } }
A classe TpdvFrame
Page 1 of 3Adicionando uma Interface com o Usuário
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl4.htm
public class TpdvFrame extends JFrame { Loja loja = new Loja(); ITPDV tpdv = loja.getTPDV(); // ... }
Atendimento ao clique do botão Entra Item Tem umas 8 linhas de interesse e mais de 20 linhas de verificação e captura de erros Isso é perfeitamente normal!
public class TpdvFrame extends JFrame { // ... void entraItem_actionPerformed(ActionEvent e) { if(upc.getText().equals("")) { JOptionPane.showMessageDialog(this, "UPC deve ser informado"); return; } if(quantidade.getText().equals("")) { JOptionPane.showMessageDialog(this, "Quantidade deve ser informada"); return; } int upcInt = 0; int quant = 0; try { upcInt = Integer.parseInt(upc.getText()); } catch(NumberFormatException ex) { JOptionPane.showMessageDialog(this, "Produto " + upc.getText() + " inexistente"); } try { quant = Integer.parseInt(quantidade.getText()); } catch(NumberFormatException ex) { JOptionPane.showMessageDialog(this, "Quantidade deve ser numérica"); } try { tpdv.entraItem(upcInt, quant); } catch(ProdutoInexistenteException ex) { JOptionPane.showMessageDialog(this, ex.getMessage()); return; } upc.setText(""); quantidade.setText(""); total.setText(""); valorEntregue.setText(""); troco.setText(""); } // ... }
Atendimento ao clique do botão Fim Venda 2 linhas de interesse e 5 linhas de verificação e captura de erros
public class TpdvFrame extends JFrame { // ... void fimVenda_actionPerformed(ActionEvent e) { try { tpdv.fimDeVenda(); } catch(NaoHaVendaException ex) { JOptionPane.showMessageDialog(this, ex.getMessage()); return; } total.setText(String.valueOf(tpdv.getVenda().total())); } }
Atendimento ao clique do botão Faça Pagamento 2 linhas de interesse e 9 linhas de verificação e captura de erros
Page 2 of 3Adicionando uma Interface com o Usuário
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl4.htm
public class TpdvFrame extends JFrame { // ... void façaPagamento_actionPerformed(ActionEvent e) { if(valorEntregue.getText().equals("")) { JOptionPane.showMessageDialog(this, "Qual é o valor entregue?"); return; } try { tpdv.façaPagamento((float)Double.parseDouble(valorEntregue.getText())); } catch(PagamentoInsuficienteException ex) { JOptionPane.showMessageDialog(this, ex.getMessage()); return; } troco.setText(String.valueOf(tpdv.getVenda().getTroco())); } }
impl-4 programa anterior
Page 3 of 3Adicionando uma Interface com o Usuário
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\impl\impl4.htm
6. Fase de Análise 2 Escolha de requisitos da segunda iteração Relacionando múltiplos use cases Extensão do modelo conceitual Generalização Organizando o modelo conceitual com packages Refinamento do modelo conceitual Modelo conceitual no estudo de caso Comportamento do sistema: Diagramas de sequência e contratos na Segunda
Iteração Comportamento do sistema: Diagramas de estado
anal2 programa
Page 1 of 16. Fase de Análise 2
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\index.htm
Escolha de Requisitos da Segunda Iteração
Escolheremos o que fazer na segunda iteração visando apresentar novos conceitos na disciplina
No mundo real, os requisitos da segunda iteração poderiam ser diferentes Manteremos os mesmos Use Cases da primeira iteração, mas o Use Case de Compra de
Itens incluirá pagamentos em dinheiro, com cheque e com cartão de crédito Temos a seguinte funcionalidade adicional
Pagamento pode ser em dinheiro, com cheque e com cartão de crédito Apenas um pagamento é feito e de um tipo único Pagamentos em cheque e com CC devem ser autorizados Um serviço diferente de autorização de crédito é usado para cada cartão de crédito
(Visa, Mastercard, ...) Um único serviço de autorização de cheques é usado para todos os cheques O terminal PDV é responsável pela comunicação com o serviço de autorização de
crédito O leitor de CC apenas lê o número do CC e o disponibiliza para o terminal PDV
A comunicação com um serviço externo é feito com um modem Deve-se discar um número de telefone a cada venda
anal2-1 programa próxima
Page 1 of 1Escolha de Requisitos da Segunda Iteração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal1.htm
Organizando o Modelo Conceitual com Packages
Introdução
Quando o modelo conceitual fica grande demais, pode ser quebrado em modelos menores
Já falamos de camadas e partições em outro contexto (Projeto arquitetural), mas a situação se aplica também no modelo conceitual
Packages em UML
Para referencia um conceito de um outro package, usa-se a notação NomeDoPackage::NomeDoConceito
Pode-se incluir dependências entre packages
Organizando um modelo conceitual em packages
Regras para juntar elementos num mesmo package: Os elementos partencem à mesma área conceitual
Page 1 of 3Organizando o Modelo Conceitual com Packages
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal5.htm
Os elementos participam de uma mesma hierarquia de tipos Os elementos participam dos mesmos Use Cases Os elementos Estão fortemente associados
Packages no estudo de caso
Os packages mostrados abaixo são: Conceitos De Domínio Elementos Básicos Vendas Produtos Pagamentos Transações De Autorização
Page 2 of 3Organizando o Modelo Conceitual com Packages
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal5.htm
anal2-5 programa anterior próxima
Page 3 of 3Organizando o Modelo Conceitual com Packages
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal5.htm
Relacionando Múltiplos Use Cases
Introdução
UML tem uma notação especial para Use Cases em dois casos: Use Cases grandes podem ser quebrados em vários Use Cases menores mas relacionados A duplicação de certos passos de Use Cases diferentes pode se fatorada em um Use Case separado
Veremos como fazer isso para os Use Cases seguintes do estudo de caso: Pagar com dinheiro Pagar com cartão de crédito (CC) Pagar com cheque
Relacionamentos "Uses" em UML
Se um Use Case inicia outro Use Case (isto é, inclui o comportamento de outro Use Case), o relacionamento entre os dois é do tipo "Uses"
Exemplo: O Use Case Comprar Itens pode iniciar um dos Use Cases seguintes: Pagar com dinheiro Pagar com cartão de crédito (CC) Pagar com cheque
Ver o diagrama UML abaixo
Na descrição do Use Case, a palavra "initiate" (iniciar) é usada para identificar que um Use Case usa outro
O Use Case Comprar Itens
Use case: Comprar itens Atores: Cliente (iniciador), Caixa Descrição: Um cliente chega ao caixa com itens a comprar. O caixa registra os itens comprados e recebe pagamento. No fim, o cliente sai com os itens comprados.
Sequência típica de eventos
Ação do ator Resposta do sistema
1. O Use Case inicia quando um cliente chega a um caixa munido de TPDV com itens a comprar
2. O caixa registra a identificação de cada item
3. Determina o preço do item e adiciona a informação ao total da transação de venda
Page 1 of 3Relacionando Múltiplos Use Cases
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal2.htm
Sequências Alternativas: Seção 2: Identificador inválido de item informado: Exibit erro. Seção 7: Cliente não pode pagar: Cancelar transação de venda
Use Cases Relacionados: Usa Pagar com dinheiro Usa Pagar com CC Usa Pagar com Cheque
O Use Case Pagar com Dinheiro
Use case: Pagar com Dinheiro Atores: Cliente (iniciador), Caixa Descrição: Um cliente paga uma venda com dinheiro num terminal ponto-de-venda
Sequência típica de eventos
Sequências Alternativas: Seção 2: O Cliente não tem dinheiro suficiente. Pode cancelar a venda ou iniciar um novo método de pagamento Seção 3: A gaveta não tem dinheiro para pagar o troco. Caixa pede dinheiro ao supervisor ou pede ao Cliente para escolher outro método de pagamento
O Use Case Pagar com Cartão de Crédito
Use case: Pagar com Cartão de Crédito Atores: Cliente (iniciador), Caixa, Serviço de Autorização de Crédito, Contas A Receber Descrição: Um cliente paga uma venda com cartão de crédito num terminal ponto-de-venda. O pagamento é validado num serviço externo de autorização de crédito e é lançado num sistema de contas a receber.
Se houver mais itens, o caixa pode informar a quantidade também A descrição e preço do item corrente são exibidos
4. Ao completar a entrada dos itens, o caixa indica este fato ao TPDV 5. Calcula e apresenta o total da venda
6. O caixa informa o total da venda ao cliente
7. O cliente escolhe o método de pagamento: a. Se for dinheiro, iniciar Pagar Com Dinheiro b. Se for CC, iniciar Pagar Com CC a. Se for cheque, iniciar Pagar Com Cheque
8. Faz log da venda completada
9. Gera um recibo impresso
10. O caixa entrega o recibo impresso ao cliente
11. O cliente sai da loja com os itens comprados
Ação do ator Resposta do sistema
1. O Use Case inicia quando um cliente decide pagar uma venda com dinheiro, após descobrir o valor total da venda
2. O cliente entrega o pagamento em dinheiro (o "valor entregue", possivelmente maior que o total da venda
3. O Caixa registra o valor entregue 4. Exibe o troco devido ao Cliente
5. O Caixa deposita o dinheiro recebido e devolve o troco devido
Page 2 of 3Relacionando Múltiplos Use Cases
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal2.htm
Sequência típica de eventos
Sequências Alternativas: Seção 4: A autorização é negada pelo Serviço de Autorização de Crédito. O Caixa sugere um outro método de pagamento.
O Use Case Pagar com Cheque
Use case: Pagar com Cheque Atores: Cliente (iniciador), Caixa, Serviço de Autorização de Cheque Descrição: Um cliente paga uma venda com cheque num terminal ponto-de-venda. O pagamento é validado num serviço externo de autorização de cheque.
Sequência típica de eventos
Sequências Alternativas: Seção 5: A autorização é negada pelo Serviço de Autorização de Cheque. O Caixa sugere um outro método de pagamento.
anal2-2 programa anterior próxima
Ação do ator Resposta do sistema
1. O Use Case inicia quando um cliente decide pagar uma venda com CC, após descobrir o valor total da venda
2. O cliente entrega a informação de crédito para o pagamento 3. Gera um pedido de pagamento com CC e o envia a um Serviço de Autorização de Crédito
4. O Serviço de Autorização de Crédito autoriza o pagamento 5. Recebe uma aprovação de crédito do Serviço de Autorização de Crédito
6. Lança o pagamento com crédito e informação de autorização no sistema de Contas a Receber
7. Exibe uma messagem de sucesso de autorização
Ação do ator Resposta do sistema
1. O Use Case inicia quando um cliente decide pagar uma venda com cheque, após descobrir o valor total da venda
2. O cliente escreve o cheque e se identifica
3. O Caixa registra a informação de identificação e pede a autorização de pagamento com cheque
4. Gera um pedido de pagamento com cheque e o envia a um Serviço de Autorização de Cheque
5. O Serviço de Autorização de Cheque autoriza o pagamento 6. Recebe uma aprovação de crédito do Serviço de Autorização de Cheque
7. Exibe uma messagem de sucesso de autorização
Page 3 of 3Relacionando Múltiplos Use Cases
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal2.htm
Extensão do Modelo Conceitual
Novos conceitos no estudo de caso
Examinando a lista de categorias de conceitos, preenchemos a tabela abaixo Categoria de Conceito Exemplos
Objetos físicos ou tangíveis Cartão de crédito, Cheque
Especificações, projetos ou descrições de coisas
Lugares
Transações (um momento notável) PagamentoComDinheiro, PagamentoComCC, PagamentoComCheque,
Detalhes de transação (Line item)
Papeis de pessoas
Coleções de outras coisas (containers)
Coisas dentro das coleções
Outros sistemas externos a nosso sistema SistemaAutorizaçãoCC, SistemaAutorizaçãoCheque
Conceitos abstratos
Organizações SistemaAutorizaçãoCC, SistemaAutorizaçãoCheque
Eventos
Processos (frequentemente não é representado como conceito, mas pode ocorrer)
Regras e políticas
Catálogos
Page 1 of 2Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal3.htm
Pode-se também identificar conceitos novos através dos substantivos nos Use Cases Identificamos assim:
PedidoAutorizaçãoCC RespostaAutorizaçãoCC PedidoAutorizaçãoCheque RespostaAutorizaçãoCheque
Modelo conceitual inicial resultante
anal2-3 programa anterior próxima
Registros de assuntos financeiros, de trabalho, de contratos, legais ContasAReceber
Instrumentos e serviços financeiros
Manuais, livros
Page 2 of 2Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal3.htm
Refinando o Modelo Conceitual
Introdução
Apresentam-se idéias adicionais associadas à modelagem conceitual
Tipos Associativos
Quando uma Loja usa um Serviço de Autorização, a comunicação envolve uma Identificação de Lojista
Onde seria armazenado o atributo? Não pode ficar na Loja, pois a identificação é diferente para cada Serviço Não pode ficar no Serviço, pois a identificação é diferente para cada Loja (Lojista)
Podemos modelar isso com um tipo associativo (ou Tipo de Associação)
Regras: quando usar um tipo associativo? Um atributo está relacionado com uma associação Instâncias do tipo associativo têm tempo de vida dependentes da associação Há uma associação muitos-para-muitos entre dois conceitos e há informação
associada à associação em si Há uma única instância do tipo associativo para uma associação envolvendo dois
conceitos Exemplo fácil para os alunos: Modele o domínio de problema envolvendo Aluno,
Page 1 of 3Refinando o Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal6.htm
DescriçãoDeDisciplina, DisciplinaCursada, etc. Onde vai o conceito recebido numa disciplina cursada?
Agregação e composição
A agregação é uma associação que modela um relacionamento todo-parte O "todo" é chamado composite As partes não têm nome padronizado (parte, componente, elemento, ...)
Exemplo: todo = mão, partes = dedos Agregação na UML
Agregação composta A cardinalidade do lado composite é 1 O losango é cheio (preto) Significa que o composite possui as partes sozinho, sem compartilhamento
Agregação compartilhada A cardinalidade do lado composite pode ser maior que 1 Significa que uma parte pode estar em mais de um composite Exemplo no domínio de desenho gráfico
Regras para identificar agregação O tempo de vida das partes está incluso no tempo de vida do composite Tem uma relação óbvia de todo-parte ou montagem lógica Algumas propriedades do composite se propagam para as partes
Exemplo: localização Operações aplicadas ao composite propagam paraa as partes
Exemplos: movimento, destruição, ... Usa ou não usar agregação nos diagramas
Não é muito importante e pode ser excluído ao construir um modelo conceitual As vantagens são mais importantes durante a fase de projeto Durante o projeto, a agregação
Identifica mais claramente dependências de tempo de vida Ajuda a identificar o criador das partes (padrão Creator) Alerta para a possível propagação de operações
Exemplo: clone, ou Deep Copy Agregação no estudo de caso
Page 2 of 3Refinando o Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal6.htm
Nomes de papeis na associações
O uso de nomes de papeis, de cada lado de uma associação é possível mas não obrigatório
Associações qualificadas
Numa associação, um qualificador ajuda a determinar um ou mais objetos do lado destino de uma associação
Exemplo: UPC é usado (conceitualmente) para identificar Especificações de Produtos dentro de um Catálogo de Produtos
Observe que a cardinalidade foi afetada
Cuidado! Já que estamos na análise, uma associação qualificada apenas pode ajudar a entender o modelo melhor
Nada significa sobre a escolha de chaves de recuperação no projeto
anal2-6 programa anterior próxima
Page 3 of 3Refinando o Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal6.htm
Generalização
Generalização
Os conceitos PagamentoDinheiro, PagamentoCC e PagamentoCheque são semelhantes de podem ser organizados num hierarquia de tipos chamada Generalização-Especialização
Temos um supertipo (Pagamento) que representa um conceito mais genérico e subtipos mais especializados
A generalização é útil pois: Permite identificar conceitos em termos mais gerais e abstratos Permite evitar a repetição de informação No momento de implementar, a herança será usada e ela permite polimorfismo, o
que leva a código mais extensível Duas formas de representar generalização em UML
Definição de Supertipos e Subtipos
Uma definição de supertipo é mais geral do que uma definição de subtipo Exemplo:
Page 1 of 5Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal4.htm
Um Pagamento (genérico) envolve um valor transferido entre partes Um PagamentoCC é um Pagamento que deve ser autorizado Portanto, Pagamento é mais geral e PagamentoCC é mais específico
Em termos de teoria dos conjuntos: Todos os membros de um conjunto de subtipo pertence ao conjunto do supertipo
Duas regras úteis para verificar se subtipos são de fato subtipos de um supertipo Regra 100%: 100% da definição do supertipo deve ser aplicáveis ao subtipo,
incluindo atributos e associações Exemplo: Os subtipos de Pagamento devem:
Ter um atributo "valor" Ter uma associação com Venda (Pagamento Paga-uma Venda)
Isso é verdade para os subtipos acima Regra É-um: Todos os membros de um conjunto de subtipo pertence ao conjunto do
supertipo Em linguagem natural, pode-se dizer Subtipo É-um Supertipo
Quando definir um subtipo
O particionamento nem sempre é útil Exemplo: Supertipo Cliente e subtipos ClienteMasculino e ClienteFeminino pode não
ser útil Para criar um subtipo, uma das 4 regras abaixo deve se aplicar:
O subtipo tem atributos adicionais O subtipo tem associações adicionais O conceito subtipo é manipulado, recebe operações, reage, ou leva a reações
diferentemente do supertipo ou outros subtipos O conceito subtipo representa uma coisa animada (animal, robô, ...) que se comporta
de forma diferente comparado ao subtipo ou outros subtipos Pelas regras, os subtipos ClienteMasculino e ClienteFeminino não parecem úteis (mas
podem ser em algumas aplicações estranhas) Exemplos concretos seguem:
Motivação para ter um subtipo Exemplos
O subtipo tem atributos adicionaisPagamentos - não aplicável
Biblioteca - Livro, subtipo de RecursoEmprestável tem um ISBN
O subtipo tem associações adicionais
Pagamentos - PagamentoCC, subtipo de Pagamento, está associado a um CC
Biblioteca - Vídeo, subtipo de RecursoEmprestável, está associado a um Diretor
O conceito subtipo é manipulado, recebe operações, reage, ou leva a reações diferentemente do supertipo ou outros subtipos
Pagamentos - PagamentoCC, subtipo de Pagamento, é manipulado de forma diferente no que diz respeito a autorização
Biblioteca - Software, subtipo de RecursoEmprestável, requer um depósito antes de ser emprestado
O conceito subtipo representa uma coisa animada (animal, robô, ...)
Pagamentos - não aplicável
Biblioteca - não aplicável
Page 2 of 5Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal4.htm
Quando definir um supertipo
A generalização de tipos existentes é motivada pela identificação de fatores comuns entre subtipos potenciais
Algumas regras: Os subtipos potenciais representam variações de um conceito similar Os subtipos obedecerão as regras 100% e É-um Todos os subtipos possuem um determinado atributo que pode ser fatorado e
colocado no supertipo Todos os subtipos possuem uma determinada associação que pode ser fatorada e
colocada no supertipo
Estudo de caso: Terminal ponto-de-venda
Tipos de Pagamentos Ver a motivação da criação da hierarquia na figura abaixo
Tipos de Serviços de Autorização Ver a motivação da criação da hierarquia na figura abaixo
que se comporta de forma diferente comparado ao subtipo ou outros subtipos
Pesquisa de mercado - PessoaMasculina, subtipo de Pessoa, tem um comportamento diferente de PessoaFeminina com respeito a hábitos de compras
Page 3 of 5Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal4.htm
Tipos de Transações de Autorização Transações com o mundo externo devem ser mostradas no modelo conceitual porque os
processos utilizam esses conceitos Vários tipos de hierarquias podem ser montadas usando esses conceitos Usar uma hierarquia muito profunda pode ser complexo demais Optamos pela estrutura abaixo que exibe as relações enquanto mantém uma certa
simplicidade
Tipos abstratos
Se um conceito não pode existir como instância concreta, estamos definindo um tipo abstrato
Exemplo: um Pagamento não pode existir, sem que seja um dos subtipos Em UML, um tipo abstrato recebe um nome em itálico
Na implementação, um tipo abstrato pode ser implementado como classe abstrata ou como interface (em Java, por exemplo)
Mutação de tipos
Não modele mudanças de estado de objetos como mudanças de tipos (mutações) Exemplo: um Pagamento pode ser não autorizado (no início) e passar a ser autorizado
Não modele isso como mudança de um tipo PagamentoNãoAutorizado para outro tipo PagamentoAutorizado
Falaremos mais sobre mutações quando elaborarmos sobre herança num capítulo futuro
Generalização e herança
Não falamos de herança aqui porque estamos no mundo conceitual e não estamos falando de classes de software
Em linguagens OO, uma subclasse de uma superclasse herda atributos e métodos A herança é portanto uma forma de implementar a regra 100%
Page 4 of 5Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal4.htm
Ao passar para a fase de projeto, poderemos ou não usar herança para as hierarquias de tipo
Exemplo, em C++, poderíamos usar uma única classe com templates em vez de uma hierarquia de classes
anal2-4 programa anterior próxima
Page 5 of 5Extensão do Modelo Conceitual
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal4.htm
Modelo Conceitual no Estudo de Caso
O Package Conceitos De Domínio
O Package Elementos Básicos
O Package Pagamentos
Page 1 of 3Modelo Conceitual no Estudo de Caso
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal7.htm
O Package Produtos
O Package Vendas
Page 2 of 3Modelo Conceitual no Estudo de Caso
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal7.htm
O Package Transações De Autorização
anal2-7 programa anterior próxima
Page 3 of 3Modelo Conceitual no Estudo de Caso
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal7.htm
Comportamento do Sistema: Diagramas de Sequência e Contratos na Segunda Iteração
Diagramas de Sequência do Sistema
Para esta iteração, os diagramas de sequência do sistema devem representar o processo de escolher e tratar o método de pagamento
O início comum para o Use Case Comprar Itens O início não depende do método de pagamento
Pagamento com cartão de crédito Após o início comum, a seguinte sequência é usada:
Page 1 of 2Comportamento do Sistema: Diagramas de Sequência e Contratos na Segunda Iteração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal8.htm
Pagamento com cheque Após o início comum, a seguinte sequência é usada:
Contratos
Os contratos podem ser elaborados para cada evento do sistema
Os detalhes podem ser vistos no livro texto (Larman)
anal2-8 programa anterior próxima
Page 2 of 2Comportamento do Sistema: Diagramas de Sequência e Contratos na Segunda Iteração
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal8.htm
Comportamento do Sistema: Diagramas de Estado
Eventos, estados e transições
Um evento é uma "ocorrência interessante" Exemplo: os eventos do sistema discutidos anteriormente (entraItem, ...)
Um estado é a condição de um objeto entre dois eventos Exemplo: no estudo de caso, o sistema está no estado "Entrando itens" enquanto
itens estão sendo informados
Diagramas de estado
Diagramas de estado podem ser usados para Use Cases complexos Quando a ordem legal de eventos do sistema não é óbvia
Não Use Case complexo no estudo de caso, mas podemos mostrar um diagrama de estado nesse contexto (Use Case Comprar Itens)
anal2-9 programa anterior
Page 1 of 1Comportamento do Sistema: Diagramas de Estado
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\anal2\anal9.htm
7. Fase de Projeto 2 Padrões adicionais para atribuir responsabilidades Interfaces Composição versus herança Padrões de Projeto (Design Patterns)
O que são Design Patterns? Elementos essenciais de um Design Pattern Design Pattern: Factory Method Design Pattern: Iterator Design Pattern: Composite Design Pattern: Strategy Design Pattern: Decorator Design Pattern: Template Method Design Pattern: Observer
proj2 programa
Page 1 of 17. Fase de Projeto 2
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\index.htm
Polimorfismo
O padrão de projeto Polimorfismo
Problema Como tratar alternativas baseadas no tipo de objeto?
Se usar if-then-else ou switch-case, temos que mudar o código sempre que uma nova alternativa surge
A modificação tem que ser feita em todo lugar onde a alternativa deve ser tratada
O resultado é um código pouco extensível Como criar componentes plugáveis?
Como trocar um componente por outro sem afetar os clientes do componente? Há uma discussão mais detalhada de componentes em outro capítulo
Solução Usar operações polimórficas ao comportamento que varia entre os tipos Resultado: não se testa o tipo do objeto, chama-se a operação polimórfica,
simplesmente
Exemplo No estudo de caso, quem deveria ser responsável pela autorização de diferentes tipos
de pagamentos? Como a forma de obter autorização depende do tipo de pagamento (dinheiro, CC ou
cheque), podemos usar uma operação polimórfica autorize() A implementação da operação será diferente em cada subtipo
Discussão A idéia é semelhante ao padrão Expert ("eu mesmo faço") Polimorfismo é um dos padrões mais importantes no projeto de software Extensões são simples
Exemplo: como adicionar um método de pagamento com débito direto em conta corrente?
Consequências Adições futuras e não antecipadas têm pouco efeito no código existente
proj2-1 programa próxima
Page 1 of 1Padrões Adicionais para Atribuir Responsablidades
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj1.htm
Interfaces
Herança de classe versus herança de interface
Há uma diferença grande entre uma classe e seu tipo A classe define uma implementação O tipo define apenas a interface oferecida para acessar objetos da classe Um objeto pode ter muitos tipos Classes diferentes podem ter o mesmo tipo
Herança de classe significa herança de implementação A sub-classe herda a implementação da super-classe É um mecanismo para compartilhar código e representação
Herança de interface (ou sub-tipos) descreve quando um objeto pode ser usado em vez de outro Ao fazer herança de classe, automaticamente faz também herança de interface Algumas linguagens não permitem definir tipos separadamente de classes
Mas, neste caso, a classe puramente abstrata serve
"Program to an interface, not an implementation"
O fato de que a herança de implementação permite facilmente reusar a funcionalidade de uma classe é interessante mas não é o aspecto mais importante a ser considerado
Herança oferece a habilidade de definir famílias de objetos com interfaces idênticas Isso é extremamente importante pois permite desacoplar um objeto de seus clientes através do polimorfismo A herança de interface corretamente usada (sem eliminar partes da interface nas sub-classes) acaba criando sub-tipos,
permitindo o polimorfismo Programar em função de uma interface e não em função de uma implementação (uma classe particular) permite o
polimorfismo e fornece as seguintes vantagens: Clientes permanecem sem conhecimento do tipo de objetos que eles usam, desde que os objetos obedeçam a
interface Clientes permanecem sem conhecimento das classes que implementam tais objetos
A interface é o que há de comum A flexibilidade vem da possibilidade de mudar a implementação da interface, até em tempo de execução, já que o
polimorfismo é implementado com "late binding" feito em tempo de execução Em java, uma classe pode implementar várias interfaces
Isso permite ter mais polimorfismo mesmo sem que as classes pertençam a uma mesma hierarquia
Exemplo no uso de interfaces
Temos vários tipos de composites (coleções) que não pertencem a uma mesma hierarquia ColeçãoDeAlunos ColeçãoDeProfessores ColeçãoDeDisciplinas
Temos um cliente comum dessas coleções Digamos um selecionador de objetos usado numa interface gráfica para abrir uma list box para selecionar objetos
com um determinado nome Exemplo:
Quero listar todos os alunos com nome "João" e exibí-los numa list box para escolha pelo usuário Idem para listar professores com nome "Alfredo" Idem para listar disciplinas com nome "Programação"
Queremos fazer um único cliente para qualquer uma das coleções O exemplo abaixo tem polimorfismo em dois lugares
interface SelecionávelPorNome { Iterator getIteradorPorNome(String nome); } interface Nomeável { String getNome(); } classe ColeçãoDeAlunos implements SelecionávelPorNome { // ... Iterator getIteradorPorNome(String nome) { // ... } } classe Aluno implements Nomeável { // ...
Page 1 of 3Interfaces
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj2.htm
String getNome() { ... } } classe ColeçãoDeProfessores implements SelecionávelPorNome { // ... Iterator getIteradorPorNome(String nome) { // ... } } classe Professor implements Nomeável { // ... String getNome() { ... } } classe ColeçãoDeDisciplinas implements SelecionávelPorNome { // ... Iterator getIteradorPorNome(String nome) { // ... } } classe Disciplina implements Nomeável { // ... String getNome() { ... } } classe ComponenteDeSeleção { Iterator it; // observe o tipo do parâmetro (uma interface) public ComponenteDeSeleção(SelecionávelPorNome coleção, String nome) { it = coleção.getIteradorPorNome(nome); // chamada polimórfica } // ... void geraListBox() { response.out.println("<select name=\"nome\" size=\"1\">"); while(it.hasNext()) { int i = 1; // observe o tipo do objeto Nomeável obj = (Nomeável)it.next(); response.out.println("<option value=\"escolha" + i + "\">" + obj.getNome() + // chamada polimórfica "</option>"); } response.out.println("</select>"); } } // Como usar o código acima num servlet: // supõe que as coleções usam o padrão Singleton ComponenteDeSeleção cds = new ComponenteDeSeleção(ColeçãoDeAlunos.getInstance(), "João"); cds.geraListBox(); cds = new ComponenteDeSeleção(ColeçãoDeDisciplinas.getInstance(), "Programação"); cds.geraListBox();
Como achar interfaces
Procure assinaturas repetidas Exemplo: várias classes que representam coisas que podem ser vendidas indicam o uso de uma interface
VendávelIF Onde há delegação, um objeto se esconde atrás de outro: deve haver uma interface comum Procure métodos que poderiam ser usadas em aplicações semelhantes e use interfaces para que a reusabilidade das
classes clientes seja maior Exemplo: muitas coisas poderiam ser reserváveis, não só passagens de avião
Page 2 of 3Interfaces
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj2.htm
Exemplo: muitas coisas pode ser alugadas, não só fitas de vídeo Exemplo: muitos objetos são clonáveis
Procure mudanças futuras (novos objetos que poderiam aparecer) e coloque as semelhanças sob controle de interfaces Há, entretanto, pessoas que não concordam em "pensar muito na frente"
Vide "Extreme Programming" adiante ...
proj2-2 programa próxima
Page 3 of 3Interfaces
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj2.htm
Composição versus Herança
Composição e Herança
Composição e herança são dois mecanismos para reutilizar funcionalidade Alguns anos atrás (e na cabeça de alguns programadores ainda!), a herança era
considerada a ferramenta básica de extensão e reutilização de funcionalidade A composição estende uma classe pela delegação de trabalho para outro objeto
a herança estende atributos e métodos de uma classe Hoje, considera-se que a composição é muito superior à herança na maioria dos
casos A herança deve ser utilizada em alguns (relativamente poucos) contextos
Um exemplo de composição
Use composição para estender as responsabilidades pela delegação de trabalho a outros objetos
Um exemplo no domínio de endereços Uma empresa tem um endereço (digamos só um) Uma empresa "tem" um endereço Podemos deixar o objeto empresa responsável pelo objeto endereço e temos
agregação composta (composição)
Um exemplo de herança
Atributos, conexões a objetos e métodos comuns vão na superclasse (classe de generalização)
Adicionamos mais dessas coisas nas subclasses (classes de especialização) Três situações comuns para a herança (figura abaixo)
Uma transação é um momento notável ou intervalo de tempo
Exemplo no domínio de reserva e compra de passagens de avião
Page 1 of 5Composição versus Herança
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj3.htm
Benefícios da herança
Captura o que é comum e o isola daquilo que é diferente A herança é vista diretamente no código
Problemas da herança
O encapsulamento entre classes e subclasses é fraco (acoplamento é forte) Mudar uma superclasse pode afetar todas as subclasses Isso viola um dos princípios básicos de projeto O-O (fraco acoplamento)
Às vezes um objeto precisa ser de uma classe diferente em momentos diferentes Com herança, a estrutura está parafusada no código e não pode sofrer
alterações facilmente em tempo de execução A herança é um relacionamento estático que não muda com tempo Cenário: pessoas envolvidas na aviação (fugira abaixo)
Page 2 of 5Composição versus Herança
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj3.htm
Problema: uma pessoa pode mudar de papel a assumir combinações de papeis Fazer papeis múltiplos requer 7 combinações (subclasses)
Solucionando o problema com composição: uma pessoa e vários papeis possíveis
Observe que também podemos inverter a composição (uma pessoa tem um ou mais papeis)
Pense na implicação par a interface de "pessoa" Aqui, estamos usando delegação: dois objetos estão envolvidos em atender um
pedido (digamos setNome) O objeto tripulação (digamos) delega setNome para o objeto pessoa que ele
tem por composição Técnica também chamada de forwarding É semelhante a uma subclasse delegar uma operação para a superclasse
(herdando a operação) Delegação sempre pode ser usada para substituir a herança
Se usássemos herança, o objeto tripulação poderia referenciar a pessoa com this
Com o uso de delegação, tripulação pode passar this para pessoa e o objeto pessoa pode referenciar o objeto original se quiser
Em vez de tripulação ser uma pessoa, ele tem uma pessoa A grande vantagem da delegação é que o comportamento pode ser escolhido
em tempo de execução e vez de estar amarrado em tempo de compilação A grande desvantagem é que um software muito dinâmico e parametrizado é
mais difícil de entender do que software mais estático
O resultado de usar composição
Em vez de codificar um comportamento estaticamente, definimos pequenos comportamentos padrão e usamos composição para definir comportamentos mais complexos
5 regras para o uso de herança (Coad)
Page 3 of 5Composição versus Herança
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj3.htm
O objeto "é um tipo especial de" e não "um papel assumido por" O objeto nunca tem que mudar para outra classe A subclasse estende a superclasse mas não faz override ou anulação de variáveis
e/ou métodos Não é uma subclasse de uma classe "utilitária"
Não é uma boa idéia fazer isso porque herdar de, digamos, HashMap deixa a classe vulnerável a mudanças futuras à classe HashMap
O objeto original não "é" uma HashMap (mas pode usá-la) Não é uma boa idéia porque enfraquece a encapsulação
Clientes poderão supor que a classe é uma subclasse da classe utilitária e não funcionarão se a classe eventualmente mudar sua superclasse
Exemplo: x usa y que é subclasse de vector x usa y sabendo que é um Vector Amanhã, y acaba sendo mudada para ser subclasse de HashMap x se lasca!
Para classes do domínio do problema, a subclasse expressa tipos especiais de papeis, transações ou dispositivos
Exemplo da aplicação das regras Considere Agente, Tripulação e Passageiro como subclasses de Pessoa
Regra 1 (tipo especial): não passa. Um Passageiro não é um tipo especial de Pessoa: é um papel assumido por uma Pessoa
Regra 2 (mutação): não passa. Um Agente pode se transformar em Passageiro com tempo
Regra 3 (só estende): ok. Regra 4: ok. Regra 5: não passa. Passageiro está sendo modelado como tipo especial de
Pessoa e não como tipo especial de papel
Outro exemplo: transações
Reserva e Compra podem herdar de Transação?
Regra 1 (tipo especial): ok. Uma Reserva é um tipo especial de Transação e não um papel assumido por uma Transação
Page 4 of 5Composição versus Herança
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj3.htm
Regra 2 (mutação): ok. Uma reserva sempre será uma Reserva, e nunca se transforma em Compra (se houver uma compra da passagem, será outra transação). Idem para Compra: sempre será uma Compra
Regra 3 (só estende): ok. Ambas as subclasses estendem Transação com novas variáveis e métodos e não fazem override ou anulam coisas de Transação
Regra 4 (não estende classe utilitária): ok. Regra 5 (tipo especial de papel/transação/dispositivo): ok. São tipos especiais de
Transação
proj2-3 programa
Page 5 of 5Composição versus Herança
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\proj2\proj3.htm
Design Patterns
O que são Design Patterns? Uma definição informal:
"Cada padrão descreve um problema que ocorre frequentemente e então descreve o cerne da solução ao problema de forma a poder reusar a solução milhões de vezes em situações diferentes"
Observe que o que é reutilizado são as classes e suas colaborações Reuso de idéias, não código Consistem de micro-arquiteturas de classes, objetos, seus papeis e suas
colaborações Contêm o somatório da experiência dos melhores projetistas O-O! Estão revolucionando o projeto de software desde 1995 quando o famoso livro da
"Gang of Four" (GoF) apareceu com o primeiro catálogo de 23 padrões Ver bibliografia Tem muito mais padrões aparecendo sempre OOPSLA é uma grande fonte de padrões
Ficará mais claro com alguns exemplos Design Patterns iniciaram a febre de padrões
Analysis Patterns Testing Patterns Business Patterns Pedagogical Patterns e mais ...
Há um meta-padrão envolvido: Entre várias situações, isolar o que muda do que é igual.
Uma sinopse dos Design Patterns da GoF está aqui.
pat-1 programa próxima
Page 1 of 1O que são Design Patterns?
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\oque.htm
Elementos essenciais de um Design Pattern
Um Nome
Descreve o problema de projeto, suas soluções e consequências em poucas palavras
Permite projetar num nível mais alto de abstração Permite falar com outros sobre soluções e documentar código, já que os nomes de
padrões estão ficando padronizados "Todo mundo" conhece os 23 padrões da GoF É equivalente a padronizar "lista encadeada", "pilha", etc. no mundo das
estruturas de dados
O Problema
Descreve quando aplicar o padrão Descreve o problema e o contexto Pode descrever problemas específicos de projeto
Exemplo: como representar algoritmos como objetos? Pode descrever estruturas de objetos ou de classes que são sintomas de um
projeto inflexível Às vezes, o padrão lista condições que devem se aplicar para usar o padrão
A Solução
Descreve os elementos constituintes do projeto, seus relacionamentos, responsabilidades e colaborações
A solução não descreve um projeto ou implementação concretos porque um padrão é um gabarito de solução para várias situações
As Consequências
Os resultados e trade-offs da aplicação do padrão Diz respeito a trade-offs de espaço, tempo, flexibilidade, extensibilidade,
portabilidade
pat-2 programa anterior próxima
Page 1 of 1Elementos essenciais de um Design Pattern
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\elem.htm
Factory Method
Introdução aos Padrões de Criação: Construindo Labirintos
GoF classifica os padrões em Padrões de Criação, Estruturais e de Comportamento Padrões de criação abstraem o processo de instanciação de objetos Usaremos a construção de labirintos para um jogo via computador para mostrar
alguns padrões de criação Ignoraremos muitos detalhes do labirinto (o que pode estar no labirinto, os
jogadores, etc.) Foco na criação dos labirintos
Um labirinto é um conjunto de salas Uma sala conhece seus quatro vizinhos Vizinhos podem ser outra sala, uma parede ou uma porta para outra sala
As classes importantes são Sala, Porta e Parede Só trataremos as partes das classes que interessam para a criação do labirinto
O diagrama de classes segue abaixo (em UML) Se precisar de um resumo de UML, ver aqui
Um diagrama de objetos segue para um pequeno labirinto
Page 1 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
Cada sala tem quatro vizinhos Usamos norte, sul, leste, oeste para referenciá-los
A interface ElementoDeLabirinto é implementada por todos os componentes de um labirinto
Tem um método entra() cujo significado depende onde se está entrando Se for uma sala, a localização do jogador muda Se for uma porta aberta, você vai para outra sala, caso contrário se
machuca Se for uma parede, você se machuca
public interface ElementoDeLabirinto { public void entra(); }
Exemplo: se você estiver numa sala e quiser implementar a operação "vá para o leste", o jogo determina qual ElementoDeLabirinto está do lado leste e chama entra() deste objeto
O método entra() da subclasse específica determina o que ocorre Num jogo real, entra() poderia aceitar o objeto jogador como parâmetro
Sala é a classe que implementa ElementoDeLabirinto e define as relações-chave entre objetos
Mantém referências para 4 outros ElementoDeLabirinto Armazena um número de sala para indentificar as salas do labirinto
class Sala implements ElementoDeLabirinto { private ElementoDeLabirinto[] vizinhos =
Page 2 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
new ElementoDeLabirinto[4]; private int númeroDaSala; public Sala(int númeroDaSala) { ... } public void entra() { ... } public ElementoDeLabirinto getVizinho(int direção) { ... } public void setVizinho(int direção, ElementoDeLabirinto vizinho) { ... } } class Parede implements ElementoDeLabirinto { public Parede() { ... } public void entra() { ... } } class Porta implements ElementoDeLabirinto { private Sala sala1, sala2; private boolean estáAberta; public Porta(ElementoDeLabirinto sala1, ElementoDeLabirinto sala2) { ... } public void entra() { ... } public Sala salaDoOutroLado(Sala sala) { ... } }
Também precisamos de uma classe Labirinto para representar uma coleção de salas
A classe Labirinto pode localizar uma sala dado seu número com o método getSala()
class Labirinto { private Vector salas = new Vector(); public Labirinto() { ... } public void adicionaSala(Sala sala) { ... } public sala getSala(int númeroDaSala) { ... } }
Também definimos uma classe Jogo que cria o labirinto Uma forma simples de criar um labirinto é de criar os componentes, adicioná-
los ao labirinto e interconectá-los Exemplo da criação de um labirinto com 2 salas e uma porta entre elas
Page 3 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
class Jogo { ... public Labirinto criaLabirinto() { Labirinto umLabirinto = new Labirinto(); Sala sala1 = new Sala(1); Sala sala2 = new Sala(2); Porta aporta = new Porta(sala1,sala2); umLabirinto.adicionaSala(sala1); umLabirinto.adicionaSala(sala2); sala1.setVizinho(norte, new Parede()); sala1.setVizinho(leste, aporta); sala1.setVizinho(sul, new Parede()); sala1.setVizinho(oeste, new Parede()); sala2.setVizinho(norte, new Parede()); sala2.setVizinho(leste, new Parede()); sala2.setVizinho(sul, new Parede()); sala2.setVizinho(oeste, aporta); return umLabirinto; } ... }
O problema desta solução é sua inflexibilidade O método criaLabirinto() não é reutilizável em outras situações Motivo: criaLabirinto() mistura a questão da estrutura do labirinto com a
questão dos tipos exatos de elementos que compõem o labirinto New cria um forte acoplamento entre a classe Jogo e as classes dos objetos
criados porque implica num compromisso (amarração) com uma determinada implementação
Veremos agora como mudar o projeto para criar diferentes tipos de labirintos Labirintos encantados
Com portas travadas que precisam de um encantamento para abrir Salas contendo encantamentos que podem ser apanhados
Page 4 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
Labirintos perigosos Salas com bombas que podem ser explodidas para danificar as paredes (e
talvez o jogador!) Como mudar criaLabirinto() para facilmente criar estes novos tipos de labirintos?
O maior problema é que a solução atual nos força a colocar em código as classes concretas que serão instanciadas
Usaremos padrões de criação para tornar o projeto mais flexível (mais reusável)
O padrão Factory Method
Objetivo
Definir uma interface para criar objetos de forma a deixar subclasses decidirem qual classe instanciar
Factory Method deixa que subclasses façam a instanciação
Também conhecido como
Construtor Virtual
Resumo
A idéia é simples: em vez de um cliente que precisa de um objeto chamar new e assim especificar a classe concreta que ele instancia, o cliente chama um método abstrato (Factory Method) especificado em alguma classe abstrata (ou interface) e a subclasse concreta vai decidir que tipo exato de objeto criar e retornar
Mudar a subclasse concreta que cria o objeto permite mudar a classe do objeto criado sem que cliente saiba
Permite estender a funcionalidade através da construção de subclasses sem afetar os clientes
Resumindo: "Crie objetos numa operação separada de forma que subclasses possam fazer
override da forma de criação"
Quando usar o padrão Factory Method?
Quando uma classe (o criador) não pode antecipar a classe dos objetos que deve criar
Quando uma classe quer que suas subclasses especifiquem os objetos criados Quando classes delegam responsabilidade para uma entre várias subclasses de
apoio e queremos localizar num ponto único a conhecimento de qual subclasse está sendo usada
Estrutura genérica
Page 5 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
Participantes
Produto: define a interface dos objetos criados pelo Factory Method ProdutoConcreto: implementa a interface Produto Criador: declara o Factory Method que retorna um objeto do tipo Produto
Às vezes, o Criador não é apenas uma interface mas pode envolver uma classe concretaque tenha tem uma implementação default para o Factory Method para retornar um objeto com algum tipo ProdutoConcreto default
Pode chamar o Factory Method para criar um produto do tipo Produto CriadorConcreto: faz override do Factory Method para retornar uma instância de
ProdutoConcreto
Colaborações
Criador depende de suas subclasses para definir o Factory Method para que ele retorne uma instância do ProdutoConcreto apropriado
Consequências do uso do padrão Factory Method
Factory Methods eliminam a necessidade de colocar classes específicas da aplicaçãono código
O código só lida com a interface Produto O código pode portanto funcionar com qualquer classe ProdutoConcreto
Provê ganchos para subclasses Criar objetos dentro de uma classe com um Factory Method é sempre mais
flexível do que criar objetos diretamente O Factory Method provê um gancho para que subclasses forneçam uma versão
estendida de um objeto Exemplo num editor de documentos
Uma classe Documento poderia ter um Factory Method criaFileDialog para criar um objeto file dialog default para abrir um documento existente
Uma subclasse de Documento poderia criar um file dialog especial através do override do Factory Method default
Neste caso, o Factory Method não é abstrato mas fornece um default razoável
Exercício: como estruturar o código de uma aplicação bancária para que você não fique maluco quando seu gerente pedir que todas as novas contas de poupança criadas a partir de segunda-feira tenham algo novo implementado nelas mas sem afetar código antigo que trata das contas antigas?
Considerações de implementação
É boa prática usar uma convenção de nomes para alertar para o fato de que está
Page 6 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
usando Factory Methods Exemplo: makeAbc(), makeXyz() Exemplo: criaAbc(), criaXyz()
Exemplo de código: criação de labirintos
A criação de labirintos já vista não ficou flexível pois criamos (com new) os objetos especificando as classes concretas na função criaLabirinto()
Usaremos Factory Methods para deixar que subclasses escolham que objetos criar Usaremos o seguinte projeto
Produto: Sala, Parede, Porta ProdutoConcreto: Sala, SalaEncantada, SalaPerigosa, Parede,
ParedeComBomba, Porta, PortaComChave Ccriador: Jogo
Seu método criaLabirinto cria o labirinto chamando Factory Methods Ele também é um CriadorConcreto pois oferece uma implementação default
para os Factory Methods (para criar um labirinto simples) CriadorConcreto: Jogo, JogoEncantado, JogoPerigoso que serão subclasses de
jogo Iniciamos com o criador Jogo que contém os Factory Methods
class Jogo { // Factory Methods com default public Labirinto criaLabirinto() { return new Labirinto(); } public Sala criaSala(int númeroDaSala) { return new Sala(númeroDaSala); } public Parede criaParede() { return new Parede(); } public Porta criaPorta(Sala sala1, Sala sala2) { return new Porta(sala1, sala2); } // Observe que essa função não tem new: // ela usa Factory Methods // Esta é a *única* diferença com relação // à versão original // Observe como o método só trata da estrutura do labirinto // e não do tipo de elemento que o compõe public Labirinto criaLabirinto() { Labirinto umLabirinto = criaLabirinto(); Sala sala1 = criaSala(1); Sala sala2 = criaSala(2); Porta aPorta = criaPorta(sala1, sala2); umLabirinto.adicionaSala(sala1); umLabirinto.adicionaSala(sala2); sala1.setVizinho(norte, criaParede()); sala1.setVizinho(leste, aporta); sala1.setVizinho(sul, criaParede()); sala1.setVizinho(oeste, criaParede()); sala2.setVizinho(norte, criaParede()); sala2.setVizinho(leste, criaParede()); sala2.setVizinho(sul, criaParede()); sala2.setVizinho(oeste, aporta); return umLabirinto; }
Page 7 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
}
Para criar um jogo perigoso, criamos uma subclasse de Jogo e redefinimos alguns Factory Methods
// um novo CriadorConcreto class JogoPerigoso extends Jogo { public Parede criaParede() { return new ParedeDestrutível(); } public Sala criaSala(int númeroDaSala) { return new SalaComBomba(númeroDaSala); } }
Comparando o diagrama de objetos com a versão inicial, não há objeto adicional Só há uma mudança do objeto umJogo para um umJogoPerigoso
Para criar um jogo encantado, procedemos de forma análoga
// um novo CriadorConcreto class JogoEncantado extends Jogo { public sala criaSala(int númeroDaSala) { return new salaEncantada(númeroDaSala, jogaEncantamento()); } public Porta criaPorta(Sala sala1, Sala sala2) { return new portaPrecisandoDeEncantamento(sala1, sala2); } protected Encantamento jogaEncantamento() { ... }
Page 8 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
}
O acoplamento depois do Factory Method
Discussão geral de padrões de criação
Ajudam a deixar o sistema independente de como seus objetos são criados, compostos e representados
São dois tipos: Padrões de criação via classes
Usam herança para variar a classe que é instanciada Exemplo: Factory Method
Padrões de criação via objetos Delegam a instanciação para outro objeto Exemplo: Abstract Factory
Composição é usada mais que herança para estender funcionalidade e padrões de criação ajudam a lidar com a complexidade de criar comportamentos
Em vez de codificar um comportamento estaticamente, definimos pequenos comportamentos padrão e usamos composição para definir comportamentos mais complexos
Isso significa que instanciar um objeto com um comportamento particular requer mais do que simplesmente instanciar uma classe.
Eles escondem como instâncias das classes concretas são criadas e juntadas para gerar "comportamentos" (que podem envolver vários objetos compostos)
Os padrões mostrados aqui mostram como encapsular as coisas de forma a simplificar o problema de instanciação.
Os padrões de criação discutem temas recorrentes: Eles encapsulam o conhecimento das classes concretas que são instanciadas
Lembre que preferimos nos "amarrar" a interfaces (via interface ou classes abstratas) do que a classes concretas
Isso promove a flexibilidade de mudança (das classes concretas que são instanciadas)
Page 9 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
Pergunta final para discussão
De que forma a Factory Method ajuda a produzir código fracamente acoplado?
pat-3 programa anterior próxima
Page 10 of 10Factory Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\factory.htm
Iterator
Objetivo
Prover uma forma de sequencialmente acessar os elementos de um objeto agragado sem expor sua representação interna
Também conhecido como
Cursor
Motivação
Queremos isolar o uso de uma estrutura de dados de sua representação interna de forma a poder mudar a estrutura sem afetar quem a usa
Para determinadas estruturas, pode haver formas diferentes de caminhamento ("traversal") e queremos encapsular a forma exata de caminhamento
Exemplo: árvore pode ser varrida "em ordem", "em pós-ordem", em "pré-ordem"
Exemplo: podemos ter um "iterador com filtro" que só retorna certos elementos da coleção
Exemplo: num editor de documentos, poderíamos ter os elementos do documento organizados em árvores (documento consiste de páginas qe consistem de parágrafos, ...) e ter um iterador especial para elementos não gráficos (que podem ter sua grafia verificada, por exemplo)
A idéia do iterador é de retirar da coleção a responsabilidade de acessar e caminhar na estrutura e colocar a responsabilidade num novo objeto separado chamado um iterador
A interface Iterador: Define uma interface para acessar os elementos da coleção
A classe Iterador Implementa a interface Iterador Mantém qualquer informação de estado necessária para saber até onde a
iteração (caminhamento) já foi Como criar um iterador?
Não podemos usar new de uma classe concreta diretamente pois o iterador a ser criado depende da coleção a ser varrids
Solução: a coleção tem um factory method para criar um iterador Exemplo em java: Vector.iterator()
Aplicabilidade: use o padrão iterador
Para acessar o conteúdo de uma coleção sem expor suas representação interna Para suportar múltiplas formas de caminhamento Para prover uma interface única para varrer estruturas agregadas diferentes
Isto é, para suportar iteração polimórfica
Estrutura
Page 1 of 4Iterator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\iterator.htm
Exemplo de uso: um impressor genérico em Java
class Printer { static void printAll(Iterator it) { while(it.hasNext()) { System.out.println(it.next().toString()); } } } class LabirintoDeRatos { public static void main(String[] args) { Vector ratos = new Vector(); for(int i = 0; i < 3; i++ ) { ratos.add(new Rato(i)); } // iterador criado aqui Printer.printAll(ratos.iterator()); } }
Participantes
Iterador (Enumeration no Java original) Define a interface para acessar e caminhar nos elementos
IteradorConcreto (elements() no Java original, iterator() no Java recente) Implemementa a interface Iterator Mantém estado para saber o elemento corrente na coleção
Coleção (não tem isso no Java antigo; no Java recente, chama-se Collection) Define uma interface para criar um objeto iterador
ColeçãoConcreta (Vector, ArrayList, LinkedList, ... em Java) Implementa a interface de criação do iterador e retorna uma instância do
IteradorConcreto
Consequências
Page 2 of 4Iterator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\iterator.htm
A mera substituição de um iterador permite caminhar numa coleção de várias formas
Juntar a interface de caminhamento num iterador permite retirar esta interface da coleção, simplificando assim a interface desta coleção
Várias iterações podem estar ocorrendo ao mesmo tempo, já que o estado de uma iteração é mantido no iterador e não na coleção
Detalhes de implementação
Iteradores internos versus iteradores externos Com iterador interno, o cliente passa uma operação a ser desempenhada pelo
iterador e este o aplica a cada elemento Com iterador externo (mais flexíveis), o cliente usa a interface do iterador para
caminhar mas ele mesmo (o cliente) processa os elementos da coleção Um iterador interno só é usado quando um iterador externo seria difícil de
implementar Exemplo: para coleções complexas, manter o estado da iteração pode ser
difícil (teria que armazenar o caminho inteiro dentro de uma coleção recursiva multi-nível). Neste caso, usar um iterador interno recursivo e armazenar o estado na propria pilha de execução pode ser mais simples.
Tratamento de concorrência O que ocorre se houver mudanças à coleção (novos objetos ou objetos
removidos) durante uma iteração (devido a um thread)? Um "iterador fail-fast" indica imediatamente que está havendo acesso
concorrente (via exceção) Alguns iteradores podem clonar a coleção para caminhar, mas isto é caro em
geral Um "iterador robusto" permite fazer iterações e mudar a coleção sem se perder
Operadores do iterador Pode permitir ou não andar para trás, pular posições, etc.
Iteradores nulos são interessantes para prover condições limites Um iterador nulo sempre diz que a iteração acabou Eexemplo: se todo objeto de um Composite (ver à frente) tiver um iterador,
uma folha poderia ter um iterador nulo
Exemplo de código
O iterador do Vector em Java seria semelhante ao que segue abaixo
public Iterator iterator() { return new Iterator() { // classe interna anônima int cursor = 0; public boolean hasNext() { return cursor < size(); } public Object next() { try { Object next = get(cursor); cursor++; return next; } catch(IndexOutOfBoundsException e) { throw new NoSuchElementException(); } } };
Page 3 of 4Iterator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\iterator.htm
}
Pergunta final para discussão
Considere uma coleção (objeto composto) que contenha objetos representando empréstimos. A interface do objeto Empréstimo contém um método chamado ValorDoEmpréstimo() que retorna o valor corrente do empréstimo. Dado um requisito para extrair todos os empréstimos da coleção com valor menor que um limite (ou maior que um limite ou entre dois limites), você usaria ou escreveria um iterador para resolver o problema?
pat-4 programa anterior próxima
Page 4 of 4Iterator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\iterator.htm
Composite
Um problema a resolver: editor de documentos
Para introduzir este padrão (e alguns outros), usaremos o exemplo do projeto de um editor de documentos WYSIWYG (What You See Is What You Get)
Semelhante a Word, por exemplo Outros exemplos do padrão Composite no Swing de Java
O editor pode misturar texto e gráficos usando várias opções de formatação A redor da área de edição estão os menus, scroll bars, barras de ferramentas, etc. O primeiro problema de design que queremos atacar é como representar a
estrutura do documento Essa estrutura afeta o resto da aplicação já que a edição, formatação, análise
textual, etc. deverão acessar a representação do documento Um documento é um arranjo de elementos gráficos básicos
Caracteres, linhas, polígonos e outras figuras O usuário normalmente não pensa em termos desses elementos gráficos mas em
termos de estruturas físicas Linhas, colunas, figuras, tabelas e outras sub-estruturas As sub-estruturas podem ser compostas de outras sub-estruturas, etc.
O usuário também pode pensar na estrutura lógica (frase, parágrafos, seções, etc.) Não vamos considerar isso aqui mas a solução que usaremos se aplica a esta
situação também A interface do usuário (UI) do editor deve permitir que o usuário manipule tais sub-
estruturas diretamente Por exemplo, o usuário pode tratar um diagrama como uma unidade em vez de
uma coleção de elementos gráficos primitivos O usuário deve manipular uma tabela como uma unidade e não como um
amontoado de texto e gráficos Para permitir tal manipulação, usaremos uma representação interna que case com
a estrutura física do documento Portanto, a representação interna deve suportar:
A manutenção da estrutura física do documento (o arranjo de texto e gráficos em linhas, colunas, tabelas, ...)
A geração e apresentação visual do documento Mapear posições da tela para elementos da representação interna. O editor vai
saber para o que o usuário está apontando Tem algumas outras restrições no projeto
Texto e gráficos devem ser tratados uniformemente A interface deve permitir embutir texto em gráficos e vice versa Um gráfico não deve ser tratado como caso especial de texto, nem texto
como caso especial de gráfico, senão teremos mecanismos redundantes de manipulação, formatação, etc.
A implementação não deve ter que diferenciar entre elementos únicos e grupos de elementos na representação interna
O editor deve tratar elementos simples e complexos de forma uniforme permitindo assim documentos arbitrariamente complexos
O décimo elemento da linha 5, coluna 2 pode ser um caractere único ou um diagrama complexo com muitos elementos
Page 1 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
Basta que o elemento saiba se desenhar, possa dar suas dimensões: ele pode ter qualquer complexidade
Por outro lado, queremos analisar o texto para verificar a grafia, hifenizar, etc. e não podemos verificar a grafia de gráficos ou hifenizá-las
Composição recursiva
Uma forma comum de representar informação estruturada hierarquicamente é através da Composição Recursiva
Permite construir elementos complexos a partir de elementos simples Aqui, a composição recursiva vai permitir compor um documento a partir de
elementos gráficos simples Começamos formando linhas a partir de elementos gráficos simples (caracteres
e gráficos) Múltiplas linhas formam colunas Múltiplas colunas formam páginas Múltiplas páginas formam documentos etc.
Podemos representar essa estrutura física usando um objeto para cada elemento Isso inclui elementos visíveis e elementos estruturais (linhas, colunas) A estrutura de objetos seria como abaixo
Page 2 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
Na prática, talvez um objeto não fosse usado para cada caractere por razões de eficiência
Podemos agora tratar texto e gráficos de forma uniforme Podemos ainda tratar elementos simples e compostos de forma uniforme Teremos que ter uma classe para cada tipo de objeto e essas classes terão que ter
a mesma interface (para ter uniformidade de tratamento) Uma forma de ter interfaces compatíveis é de usar herança
Definimos uma interface "ElementoDeDocumentoIF" e uma classe abstrata "ElementoDeDocumento" para todos os elementos que aparecem na estrutura de objetos
Suas subclasses definem elementos gráficos primitivos (caracteres e gráficos) e elementos estruturais (linhas, colunas, frames, páginas, documentos, ...)
Parte da hierarquia de classes segue abaixo
Page 3 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
Elementos de documentos têm três responsabilidades Sabem se desenhar (draw) Sabem o espaço que ocupam (limites) Conhecem seus filhos e pai
Subclasses de ElementoDeDocumento devem redefinir certas operações tais como draw()
Um ElementoDeDocumentoIF pai deve freqüentemente saber quanto espaço seus filhos ocupam para posicioná-los de forma a não haver sobreposição
Isso é feito com o método limites() que retorna o retângulo que contém o elemento
A operação intersecta() serve para saber se um ponto intersecta o elemento Usado quando o usuário clica com o mouse
A classe abstrata ElementoCompostoDeDocumento implementa certos métodos comuns através da aplicação sucessiva do método aos filhos
É o caso de intersecta()
Page 4 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
Todos os elementos têm uma mesma interface para gerenciar os filhos (inserir, remover, etc.)
Este padrão de projeto chama-se Composite e será discutido mais detalhadamente agora
O Padrão Composite
Objetivo
Compor objetos em estruturas em árvore para representar hierárquias Parte-Todo Composite permite que clientes tratem objetos individuais e composições
uniformemente
Participantes
Os nomes genéricos dados às classes abstratas são Component e Composite Os nomes genéricos dados às classes concretas são Leaf e ConcreteComposite
Page 5 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
Consequências do uso de Composite
Objetos complexos podem ser compostos de objetos mais simples recursivamente O cliente pode tratar objetos simples ou compostos da mesma forma: simplifica
o cliente Facilita a adição de novos componentes: o cliente não tem que mudar com a
adição de novos objetos (simples ou compostos) Do lado negativo, o projeto fica geral demais
É mais difícil restringir os componentes de um objeto composto Por exemplo, acima, podemos compor linhas com linhas ou com documentos,
etc. o que não faz sentido O sistema de tipagem da linguagem não ajuda a detectar composições erradas
Page 6 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
A solução é verificar em tempo de execução
Considerações de implementação
Adicionar referência ao pai de um objeto pode simplificar o caminhamento na estrutura
Onde adicionar a referência ao pai? Normalmente é colocada na classe abstrata Component
Exercício: colocar esta referência na figura acima As subclasses herdam a referência e os métodos que a gerenciam
Compartilhamento de componentes Útil para reduzir as necessidades de espaço Por exemplo, caracteres iguais poderiam compartilhar objetos Fazer isso complica se os componentes só puderem ter um único pai O padrão "flyweight" mostra como resolver a questão
Maximização da interface de Component Exercício para casa: certos livros colocam os métodos de gerenciamento de
filhos apenas na classe Composite porque uma folha não tem filhos! Você concorda ou discorda com a maximização da interface de Component? Por
quê? Em outras palavras, é melhor ter uma interface idêntica para folhas e Composite (transparência para o cliente) ou interfaces diferentes (segurança de não fazer besteiras como adicionar um filho a uma folha, o que seria capturado pelo compilador)?
Se mantivermos as interfaces de Component e Composite diferentes, como o cliente pode testar se um objeto é folha ou composto?
Onde são armazenados os filhos? Nós os colocamos em Composite mas eles poderiam ser colocados em
Component A desvantagem é a perda de espaço para essa referência para folhas
Quando os filhos devem ter um ordem especial, deve-se cuidar deste aspecto Usar um iterator é uma boa idéia
Cache de informação As classes Composite podem manter em cache informação sobre seus filhos de
forma a eliminar (curto-circuitar) o caminhamento ou pesquisa nos filhos Um exemplo: um Composite poderia manter em cache os limites do conjunto
de filhos de forma a não ter que recalcular isso sempre Quando um filho muda, a cache deve ser invalidada Neste caso, os filhos devem conhecer o pai para avisar da mudança
Como armazenar os filhos? Vector, LinkedList, HashMap (qualquer coleção razoável)
Uso do padrão na API Java: O pacote java.awt.swing
Usa o padrão Composite com a classe abstrata "Component" e o Composite sendo a classe "Container"
Folhas podem ser Label, TextField, Button Composites concretos são Panel, Frame, Dialog
Exemplo de código: um editor de documentos
Page 7 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
O diagrama de classes segue
interface ElementoDeDocumentoIF { ElementoDeDocumentoIF getPai(); /** * Retorna o font associado a este objeto. * Se não houver font, retorna o font do pai. * Se não houver pai, retorna null. */ Font getFont(); /** * Associa um font a este objeto. */ void setFont(Font font); /** * Retorna o número de glyphs que este objeto contém. */
Page 8 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
int getNumGlyph(); /** * Retorna o filho deste objeto na posição dada. */ ElementoDeDocumentoIF getFilho(int índice) throws ÉFolhaException; /** * Faça o ElementoDeDocumentoIF dado um filho deste objeto. */ void insereFilho(ElementoDeDocumentoIF filho) throws ÉFolhaException; /** * remove o ElementoDeDocumentoIF dado * da lista de filhos deste objeto. */ void removeFilho(ElementoDeDocumentoIF filho) throws ÉFolhaException; } // interface ElementoDeDocumentoIF abstract Class ElementoDeDocumento implements ElementoDeDocumentoIF { // Este é o font associado ao objeto // Se for nulo, o font é herdado do pai private Font font; // o container deste objeto ElementoDeDocumentoIF pai; ... public ElementoDeDocumentoIF getPai() { return pai; } public Font getFont() { if(font != null) { return font; } else if(pai != null) { return pai.getFont(); } else { return null; } } // getFont() public void setFont(Font font) { this.font = font; } // setFont() public abstract int getNumGlyph(); public ElementoDeDocumentoIF getFilho(int índice) throws ÉFolhaException { throw new ÉFolhaException("Folha não tem filhos"); } /** * Faça o ElementoDeDocumentoIF dado * um filho deste objeto. */ public void insereFilho(ElementoDeDocumentoIF filho) throws ÉFolhaException { throw new ÉFolhaException("Folha não tem filhos"); } /** * Remove o ElementoDeDocumentoIF dado * da lista de filhos deste objeto. */ public void removeFilho(ElementoDeDocumentoIF filho) {
Page 9 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
throws ÉFolhaException { throw new ÉFolhaException("Folha não tem filhos"); } } // class ElementoDeDocumento abstract class ElementoCompostoDeDocumento extends ElementoDeDocumento implements ElementoDeDocumentoIF { // Os filhos deste objeto private Collection filhos = new Vector(); // Valor em cache de getNumGlyph private int cacheNumGlyph; // Validade de cacheNumGlyph private boolean cacheValida = false; /** * Retorna o filho deste objeto na posição dada. */ public ElementoDeDocumentoIF getFilho(int índice) { return (ElementoDeDocumentoIF)filhos.get(índice); } // getFilho() /** * Faça o ElementoDeDocumentoIF dado * um filho deste objeto. */ public synchronized void insereFilho(ElementoDeDocumentoIF filho) { synchronized(filho) { filhos.add(filho); filho.pai = this; avisoDeMudança(); } // synchronized } // insereFilho() /** * Remove o ElementoDeDocumentoIF dado * da lista de filhos deste objeto. */ public synchronized void removefilho(ElementoDeDocumentoIF filho) { synchronized(filho) { if(this == filho.pai) { filho.pai = null; } filhos.remove(filho); avisoDeMudança(); } // synchronized } // removeFilho() ... /** * Uma chamada a esta função significa que um filho mudou, * o que invalida a cache de informação que o objeto mantém * sobre seus filhos. */ public void avisoDeMudança() { cacheValida = false; if(pai != null) { pai.avisoDeMudança(); } } // avisoDeMudança() /** * Retorna o número de glyphs que este objeto contém. */ public int getNumGlyph() { if(cacheValida) { return cacheNumGlyph; } cacheNumGlyph = 0; for(int i = 0; i < filhos.size(); i++) {
Page 10 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
ElementoDeDocumentoIF filho; filho = (ElementoDeDocumentoIF)filhos.get(i); cacheNumGlyph += filho.getNumGlyph(); } // for cacheValida = true; return cacheNumGlyph; } // getNumGlyph() } // class ElementoCompostoDeDocumento class Caractere extends ElementoDeDocumento implements ElementoDeDocumentoIF { ... /** * Retorna o número de glyphs que este objeto contém. */ public int getNumGlyph() { return 1; } // getNumGlyph() } // class Caractere class Imagem extends ElementoDeDocumento implements ElementoDeDocumentoIF { ... /** * Retorna o número de glyphs que este objeto contém. */ public int getNumGlyph() { return 1; } // getNumGlyph() } // class Imagem class Página extends ElementoCompostoDeDocumento { implements ElementoDeDocumentoIF { ... } // Página
Alguns comentários getFont() usa a informação de seu pai Um objeto composto usa uma cache para saber quantos glyphs compõem o
objeto synchronized é usado ao mexer com dados que podem ser compartilhados para
possibilitar uma implementação multi-threaded
Perguntas finais para discussão
De que forma o padrão Composite ajuda a consolidar lógica condicional espalhada no sistema (system-wide conditional logic)?
Você usaria o padrão Composite se não tivesse uma hierarquia parte-todo? Em outras palavras, se apenas alguns objetos têm filhos e quase todos os outros objetos de uma coleção são folhas (uma folha não tem filho), você ainda usaria o padrão Composite para modelar tais objetos?
pat-5 programa anterior próxima
Page 11 of 11Composite
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\composite.htm
Strategy
Introdução
Vamos considerar o problema de formatação no editor de documentos WYSIWYG Já sabemos como é a representação da informação Mas ainda não sabemos como gerar um estrutura particular de linhas, colunas e
objetos simples para um documento particular Isso é resultado da formatação do documento
Para simplificar, formatação significa apenas quebra em linhas O resto da formatação pode ser tratado de forma análoga
Automatizar a formatação não é simples Há um trade-off entre velocidade de formatação e a qualidade resultante Muitas coisas devem ser consideradas tais como a "cor" de um documento (o
espalhamento uniforme de espaços em branco) Muitos algoritmos têm sido propostos e podem ser usados no editor
O algoritmo pode até mudar em tempo de execução Considere a formatação em word com "layout normal" (simples) e
"layout da página" (mais demorado mas mais WYSIWYG) Ponto importante: queremos manter o algoritmo de formatação isolado da
estrutura do documento Podemos adicionar elementos gráficos sem afetar o algoritmo de formatação Podemos mudar o algoritmo de formatação sem afetar o tratamento de
elementos de documento Isolaremos o algoritmo de formatação através de sua encapsulação num objeto Usaremos uma hierarquia de classes para objetos que encapsulam algoritmos de
formatação A raiz da hierarquia será uma classe com interface suficientemente genérica
para suportar uma larga gama de algoritmos Cada subclasse implementa a interface para um algoritmo particular
As classes Formatador e ElementosAFormatar
A classe Formatador é usada para objetos que encapsulam um algoritmo de formatação
As subclasses de Formatador implementam algoritmos de formatação específicos Os elementos a formatar são filhos de uma subclasse especial de
ElementoDeDocumento (ElementosAFormatar) Tem um único objeto da classe ElementosAFormatar ElementosAFormatar existe por dois motivos:
Para ser pai dos elementos básicos quando não tem formatação feita ainda Para manter referência ao formatador
Quando um objeto ElementosAFormatar é criado, ele cria uma instância de uma subclasse de Formatador, especializada em formatar de alguma forma
O objeto ElementosAFormatar pede ao formatador para formatar seus elementos quando necessário
Por exemplo, quando há uma mudança ao documento Ver a estrutura de classes abaixo
Page 1 of 6Strategy
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\strategy.htm
Um objeto ElementosAFormatar não formatado contém apenas os elementos básicos visíveis (sem Composites linha, coluna, etc.)
Quando os ElementosAFormatar precisam de formatação, o objeto chama o formatador
O formatador varre os filhos de ElementosAFormatar e insere os elementos linha, coluna, etc. de acordo com o algoritmo de formatação
Ver resultado dos objetos abaixo
Page 2 of 6Strategy
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\strategy.htm
Formatadores diferentes implementam algoritmos diferentes FormatadorSimples é o mais simples e rápido (não trata de "cor") e trata
apenas uma linha de cada vez FormatadorTeX é mais complexo pois considera o parágrafo inteiro para
distribuir os espaços em branco FormatadorArray coloca um número igual de elementos em cada linha (para
alinhar imagens, por exemplo) Resultado: a separação Formatador-ElementosAFormatar assegura uma separação
forte entre o código que suporta a estrutura do documento e o código de formatação
Podemos adicionar novos formatadores sem tocar nas classes de elementos e vice-versa
Podemos até mudar de formatador em tempo de execução com uma função setFormatador na classe ElementosAFormatar
O padrão que usamos chama-se Strategy
O padrão Strategy
Objetivo
Definir uma família de algoritmos, encapsular cada um, e torná-los intercambiáveis Strategy permite mudar os algoritmos independentemente dos clientes que os
usam
Também conhecido como
Policy
Quando usar o padrão Strategy?
Page 3 of 6Strategy
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\strategy.htm
Várias classes relacionadas têm apenas comportamento diferente Você precisa de variantes de um algoritmo
Exemplo: com trade-offs diferentes de espaço-tempo Para esconder dos clientes os dados complexos que um algoritmo usa Uma classe tem vários comportamentos escolhidos com muitas decisões
Em vez de usar decisões, mova os trechos apropriados para sua própria classe Strategy
Estrutura genérica
Participantes
EstratégiaIF (exemplo: FormatadorIF) Declara a interface comum a todos os algoritmos O contexto usa essa interface para chamar o algoritmo definido em
EstratégiaConcreta Estratégia (exemplo: Formatador)
Possível classe abstrata para fatorar código comum entre os algoritmos EstratégiaConcreta (exemplo: FormatadorSimples)
Implementa o algoritmo usando a interface EstratégiaIF Contexto (exemplo: ElementosAFormatar)
É configurado com um objeto EstratégiaConcreta Mantém uma referência para um objeto EstratégiaIF Pode definir uma interface para que a estratégia acesse seus dados
Colaborações entre objetos
Page 4 of 6Strategy
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\strategy.htm
O Contexto pode chamar a Estratégia passando a si mesmo para que a estratégia acesse os dados
O Contexto encaminha pedidos dos seus clientes para a Estratégia Clientes normalmente criam uma EstratégiaConcreta e a passam para o contexto
A partir daí, os clientes interagem apenas com o Contexto
Consequências do uso do padrão Strategy
Uma alternativa à herança Poder-se-ia usar herança (subclasses de Contexto) para fazer a mesma coisa
Teríamos uma hierarquia de ElementosAFormatar, cada um com um método formatar() diferente
Em tempo de execução, faríamos um new de alguma subclasse de ElementoAFormatar
Qual subclasse dependeria do algoritmo específico de formatação que se quer
O problema: como mudar o algoritmo formatar() em tempo de execução?? Teria que fazer "mutação" do objeto ElementoAFormatar1 para um novo
tipo ElementoAFormatar2 Mas a "mutação de tipo" é sinal de que o código fede!
As linguagens não dão suporte para isso Solução melhor: retirar o método formatar e criar um objeto a parte só para
ele Portanto, isso seria um mau exemplo do uso de herança
Acopla o Contexto com os algoritmos (parafusa o comportamento no Contexto)
Deixa o Contexto mais difícil de entender, manter e estender O algoritmo não poderia variar dinamicamente
Exemplo clássico de herança versus composição Estratégias eliminam statements condicionais
Quando vários comportamentos estão agrupados na mesma classe Código que tem muitas condições assim é candidato para o padrão Strategy
Ponto negativo: transparência incompleta dos 2 objetos Depois que o contexto é criado, os clientes enxergam apenas um objeto (o
contexto) e não dois (contexto e estratégia) Porém, no momento da criação do contexto, alguma estratégia deve ser
escolhida Os clientes devem portanto conhecer as estratégias antes de escolher uma Isso expõe os clientes a considerações de implementação Só usa Strategy quando a diferença de comportamento for relevante aos
clientes Ponto negativo: mais objetos no projeto
O padrão flyweight mostra como lidar com isso
Exemplo na API Java
Os Layout Managers de AWT são exemplos de classes que representam uma estratégia de layout para containers
A EstratégiaIF é LayoutManager
Page 5 of 6Strategy
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\strategy.htm
também tem LayoutManager2 que é uma extensão de LayoutManager Não tem classe abstrata Estratégia Tem muitas classes concretas (GridLayout, FlowLayout, BorderLayout, ...) O Contexto pode ser qualquer Container (Panel, ScrollPane, Window, ...)
Perguntas finais para discussão
O que ocorre quando um sistema tem uma explosão de objetos de estratégia? Tem uma forma melhor de gerenciar essas estratégias?
Em Gamma, os autores descrevem duas formas pelas quais um objeto de estratégia pode obter a informação de que precisa para fazer seu trabalho. Uma forma descreve como um objeto de estratégia poderia receber uma referência a um objeto de contexto, permitindo assim o acesso aos dados de contexto. Mas não poderia ocorrer que os dados necessários à estratégia não estivessem disponíveis através da interface do objeto de contexto? Como remediar este possível problema?
pat-6 programa anterior próxima
Page 6 of 6Strategy
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\strategy.htm
Decorator
Introdução
No editor de documentos WYSIWYG, vamos embelezar a interface do usuário (UI) Vamos adicionar uma borda à área de edição Vamos adicionar barras de rolagem (scroll bars)
Não vamos usar herança para adicionar este embelezamento Não poderíamos mudar o embelezamento em tempo de execução Para n tipos de embelezamento, precisaríamos de 2n-1 subclasses para ter todas as combinações
Teremos mais flexibilidade se outros objetos da UI não souberem que está havendo embelezamento!
Inclusão transparente
Usaremos composição em vez de herança evita os problemas mencionados, mas quais objetos devem participar da composição?
O embelezamento em si será um objeto (digamos uma instância da classe Borda) Isso nos dá dois objetos para fazer a composição: ElementoDeDocumento e Borda Devemos decidir agora quem vai compor quem A Borda pode conter o ElementoDeDocumento
Faz sentido já que a Borda engloba o ElementoDeDocumento na tela O ElementoDeDocumento pode conter a Borda
Isso implica em mudar a classe ElementoDeDocumento para que ela conheça a Borda
Usaremos a primeira escolha de forma a manter o código que trata bordas inteiramente na classe Borda sem mexer nas outras classes
Como construir a classe Borda? O fato da borda ter uma aparência na tela sugere que ela deveria ser uma
subclasse de ElementoDeDocumento Tem um outro motivo mais forte ainda de fazer isso: clientes tratam objetos
ElementoDeDocumento e não deveriam saber se um ElementoDeDocumento tem uma Borda ou não!
Clientes devem tratar ElementoDeDocumento uniformemente Se um cliente manda um ElementoDeDocumento sem Borda se desenhar
não vai aparecer borda, caso contrário, vai aparecer borda, mas o cliente não sabe
Isso implica que a Borda tem a mesma interface que ElementoDeDocumento Fazemos Borda uma subclasse de ElementoDeDocumento para garantir este
relacionamento Este conceito chama-se "Inclusão Transparente"
Composição com um único filho; e Interfaces compatíveis
Clientes não sabem se estão tratando do objeto original (ElementoDeDocumento) ou do seu incluidor (Borda)
O incluidor delega as operações para o objeto incluído, mas aumenta o comportamento fazendo seu trabalho antes ou depois da delegação da operação
A classe MonoElementoDeDocumento
Page 1 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
Definimos uma subclasse de ElementoDeDocumento chamada MonoElementoDeDocumento
MonoElementoDeDocumento é uma classe abstrata para todos os ElementoDeDocumento de embelezamento
MonoElementoDeDocumento armazena uma referência a um único ElementoDeDocumento (daí "mono") e encaminha todos os pedidos para ele
Isso é chamado Forwarding ou Delegação Isso faz com que MonoElementoDeDocumento seja completamente transparente
aos clientes A classe MonoElementoDeDocumento vai reimplementar pelo menos um dos
métodos de ElementoDeDocumento para fazer seu trabalho Exemplo: Borda redefine o método draw():
public class Borda extends MonoElementoDeDocumento { ... public void draw(Component c) { super.draw(c); drawBorda(c); } ...
Page 2 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
}
Observe que Borda estende o método do pai para desenhar a borda Já que chama o método do pai antes de fazer seu trabalho
A classe Rolador também é um embelezamento Ela desenha seu Componente em posições diferentes dependendo de duas
barras de rolagem Ela adiciona as barras de rolagem como embelezamento Ao desenhar seu Componente, Rolador pede ao sistema gráfico para fazer
"clipping" do Componente nos limites apropriados As partes fora dos limites não aparecerão
Agora, como adicionar uma Borda e um Rolador? Compomos os ElementosAFormatar dentro de um Rolador e este dentro de uma
Borda Se compuséssemos a Borda dentro do Rolador, a borda seria rolada
também Se isso for o comportamento desejado, essa ordem deve ser usada
A estrutura de objetos aparece abaixo
Page 3 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
Observe que os embelezadores compõem um único Componente Se tentássemos embelezar mais de uma coisa de cada vez, teríamos que misturar
vários tipos de ElementoDeDocumento com embelezadores Teríamos embelezamento de linha, embelezamento de coluna, etc. O jeito que fizemos parece melhor
Este padrão chama-se Decorator Embelezamento usando inclusão transparente Observe que o embelezamento pode, na realidade, ser qualquer adição de
responsabilidades e não um "embelezamento visual" Ex. embeleza uma árvore de sintaxe com ações semânticas Ex. embeleza uma máquina de estados finitos com novas transições
O padrão Decorator
Objetivo
Adicionar responsabilidades dinamicamente a um objeto Decoradores provêem uma alternativa flexível à herança para estender
funcionalidade
Page 4 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
Permitem adicionar responsabilidades a um objeto e não a uma classe inteira
Também chamado de
Wrapper
Quando usar o padrão Decorator?
Para adicionar responsabilidades dinamicamente a objetos individuais e transparentemente (sem afetar outros objetos)
Quando há responsabilidades que podem ser retiradas Quando herança geraria uma explosão de subclasses Quando a herança seria uma boa alternativa mas a definição da classe está
escondida ou não disponível para herança
Estrutura genérica
Participantes
ComponenteIF (ex. ElementoDeDocumentoIF)
Page 5 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
Define a interface de objetos que podem ter responsabilidades adicionadas dinamicamente
Componente (ex. ElementoDeDocumento) Possível classe abstrata para fatorar o código comum dos ComponenteConcreto
ComponenteConcreto (ex. ElementosAFormatar) Define um objeto ao qual se pode adicionar responsabilidades adicionais
Decorador (ex. MonoElementoDeDocumento) Mantém uma referência a um objeto ComponenteIF e define uma interface igual
à do Componente DecoradorConcreto (ex. Borda, Rolador)
Adiciona responsabilidades ao Componente
Colaborações entre objetos
O Decorador encaminha pedidos ao Componente Pode opcionalmente adicionar operações antes ou depois deste encaminhamento
Consequências do uso do padrão Decorator
Mais flexível do que herança estática Pode adicionar responsabilidades dinamicamente Pode até adicionar responsabilidades duas vezes! (ex. borda dupla)
Evita classes com features demais no topo da hierarquia Em vez de tentar prever todos os features numa classe complexa e
customizável, permite definir classes simples e adicionar funcionalidade de forma incremental com objetos decoradores
Desta forma, as aplicações não têm que pagar pelos features que não usam Ponto negativo: o Decorador e o objeto incluso não têm a mesma identidade
Portanto, cuidado com a identidade de objetos: um Decorador adiconado a um objeto vai mudar o objeto com o qual o cliente lida (em termos de identidade)
Ponto negativo: muitos pequenos objetos Fácil de customizar por programadores que entendem o projeto mas pode ser
difícil entender e depurar
Considerações de implementação
A interface do decorador deve ser igual à interface do objeto sendo decorado Se tiver que adicionar uma única responsabilidade, pode remover o decorador
abstrato Neste caso, o decorador concreto pode tratar do forwarding para o Componente
incluso Mantendo Componentes enxutos
A classe Componente deve ser mantida enxuta e os dados ser definidos nos Componentes concretos
Caso contrário, os decoradores (que herdam de Componente) ficam "pesados"
Decorator versus Strategy
Page 6 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
Decorator muda a "pele" de um objeto enquanto Strategy muda as "entranhas" Strategy é melhor quando a classe Componente é pesada
Neste caso, o decorador seria pesado demais Com Strategy, parte do comportamento de Componente é repassado para outro
objeto (que implementa um algoritmo) O Componente "sabe" da existência do(s) objeto(s) de estratégia mas não sabe
da existência de decoradores Exemplo: bordas com Strategy
O Componente pode mandar um objeto Borda (que ele conhece) desenhar a borda
O Componente pode manter uma lista de objetos de estratégia para fazer várias coisas, o que é equivalente a ter decoradores recursivos
Neste caso, o objeto Borda encapsula a estratégia de desenhar uma borda Ver a figura abaixo
Exemplo de código na API Java
Uso de scroll bars ScrollPane() é um decorador que contém um Component e adiciona barras de
rolagem Não usei Swing para poder mostrar o resultado num applet e vários browsers
ainda não suportam Swing Para Swing, a classe é um JScrollPane.
Exemplo de código segue:
import java.awt.*; import java.applet.*; public class Scroll extends Applet { public void init() { ScrollPane spane = new ScrollPane(); Button botaoGrande1 = new Button("Eu adoro Metodos Avançados de Programação!"); botaoGrande1.setFont(new Font("Serif", Font.ITALIC, 80)); Button botaoGrande2 = new Button("Eu adoro Metodos Avançados de Programação!"); botaoGrande2.setFont(new Font("Serif", Font.ITALIC, 80)); spane.add(botaoGrande1); add(botaoGrande2); // sem scroll bars add(spane); // com scroll bars }
Page 7 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
}
Applet roda aqui
Pergunta final para discussão
Na seção de implementação do Decorator Pattern, os autores (Gamma et al.) escrevem: A interface de um objeto decorador deve estar de acordo com a interface do Componente que ele decora. Agora, considere um objeto A decorado pelo objeto B. Haja vista que o objeto B decora o objeto A, o objeto B compartilha uma interface com o objeto A. Se algum cliente recebe uma instância do objeto decorado (B) e tenta chamar um método em B que não faça parte da interface de A, isto significa que o objeto B não é mais um decorador, no sentido estrito do padrão? Além do mais, porque é importante que a interface de um objeto decorador esteja de acordo com a interface do objeto que ele decora?
pat-7 programa anterior próxima
Page 8 of 8Decorator
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\decorator.htm
Template Method
Um problema a resolver: login
Sua tarefa é de escrever uma classe para controlar o login de usuários numa aplicação
Tem dois caminhos básicos para resolver o problema: Escrever uma classe estanque para a aplicação sob consideração Escrever uma solução genérica para qualquer aplicação
Para promover o reuso A solução genérica seria um framework de login
Um esqueleto de login que seja comum a qualquer tarefa de login Ganchos para permitir que cada aplicação customize o processo de login
Quais são os passos genéricos de login? Prompt para o usuário fornecer sua identificação (ID) e senha Autenticação da ID e senha
O resultado da autenticação deve ser um objeto Este objeto pode encapsular qualquer informação que possa ser usada
adiante pela aplicação para comprovar a autenticação Aviso visual de progresso indicando que a autenticação está sendo realizada Um aviso de sucesso ao resto da aplicação que o login foi realizado e para
disponibilizar o objeto produzido pela autenticação A lógica das etapas 1 e 3 não muda A lógica das etapas 2 e 4 pode variar muito entre aplicações
Cada aplicação deverá prover seu próprio código Solução
Criar uma classe abstrata Login contendo: Um método principal (chamado Template Method) que capture a lógica
comum de login Métodos abstratos para representar as etapas do algoritmo que devem ser
fornecidas pela aplicação particular Estender a classe Login para prover implementações dos métodos abstratos
para uma aplicação particular (digamos para uma aplicação de DecisionSupportSystem)
Page 1 of 4Template Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\template.htm
Chama-se o método login() de Template Method
O padrão Template Method
Objetivo
Define o esqueleto de um algoritmo numa operação, deixando que subclasses completem algumas das etapas.
O padrão Template Method permite que subclasses redefinem determinadas etapas de um algoritmo sem alterar a estrutura do algoritmo.
Resumo
Um Template Method define um algoritmo usando operações abstratas Subclasses fazem override das operações para prover um comportamento concreto Este padrão é a base para a construção de frameworks
Quando usar o padrão Template Method?
Para implementar partes invariantes de um algoritmo uma única vez e deixar subclasses implementarem o comportamento variável
Quando comportamento comum entre subclasses deveria ser fatorado e localizado numa classe comum para evitar duplicação
É um passo frequente de "refactoring" de código Primeiro identifique as diferenças Coloque as diferenças em novos métodos Substitua o código das diferenças por uma chamada a um dos novos
métodos Para controlar extensões de subclasses
Você pode definir um Template Method que chame operações-gancho (hook) e pontos específicos, permitindo extensões apenas nestes pontos
Faça com que apenas os métodos-gancho possam sofrer override, usando adjetivos de visibilidade
Page 2 of 4Template Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\template.htm
"public final" para o Template Method "protected" para métodos que devem/podem sofrer override
Estrutura genérica
Participantes
ClasseAbstrata (Login) Define operações abstratas que subclasses concretas definem para implementar
certas etapas do algoritmo Implementa um Template Method definindo o esqueleto de um algoritmo
O Template Method chama várias operações, entre as quais as operações abstratas da classe
ClasseConcreta (LoginDecisionSupportSystem) Implementa as operações abstratas para desempenhar as etapas do algoritmo
que tenham comportamento específico a esta subclasse
Colaborações
ClasseConcreta depende de ClasseAbstrata para implementar as partes invariantes do algoritmo
Consequências do padrão Template Method
Template Methods constituem uma das técnicas básicas de reuso de código São particularmente importantes em frameworks e bibliotecas de classes para o
fatoramento de comportamento comum Template Methods levam a uma inversão de controle
O código particular de uma aplicação é chamado pelo resto do código Normalmente, escrevemos o código "de cima" e chamamos partes comuns "em
baixo" Aqui, é o contrário
Page 3 of 4Template Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\template.htm
Também chamado de "Hollywood Principle" "Don't call us, we'll call you"
O Template Method pode chamar vários tipos de operações Operações concretas (da ClasseConcreta ou de outras classes) Operações concretas de ClasseAbstrata (operações comuns úteis às subclasses) Operações abstratas (onde o comportamento varia)
Devem sofrer override Factory Methods Operações-gancho
Podem sofrer override Uma operação-gancho tem implementação nula (fazendo nada) na
ClasseAbstrata A subclasse pode fazer override para inserir algo neste ponto (daí,
"gancho") É uma forma limpa de estender o comportamento de uma classe de forma
controlada Isto é, apenas nos pontos onde há ganchos
Considerações de implementação
É importante minimizar o número de operações abstratas que devem sofrer override para completar o algoritmo
Motivo: simplificação para não chatear o programador Convenções de nome
Métodos abstratos que devem sofrer override deveriam ter algo de comum no nome
Exemplo: doXpto() // começa com "do" Métodos-gancho que podem sofrer override deveriam ter algo de comum no
nome Exemplo: logHook() // termina com "Hook"
Pergunta final para discussão
O Template Method funciona com herança. Seria possível obter a mesma funcionalidade da Template Method usando composição de objetos? Quais seriam alguns dos tradeoffs?
Suponha que um framework tenha uma classe X contendo um ou mais template methods. Os criadores de objetos da classe X são objetos da classe C. O framework é completado com subclasses de X, digamos X'. De que forma seria possível que objetos da classe X' fossem criados pelo framework, sem que o programador tenha o código fonte do framework (isto é, sem o código fonte da classe C)?
pat-8 programa anterior próxima
Page 4 of 4Template Method
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\template.htm
Observer Não vamos seguir a apresentação do livro GoF aqui, pois há críticas sobre a
solução dada Falaremos das críticas à frente
Seguiremos a apresentação dada por Bill Venners em http://www.javaworld.com/topicalindex/jw-ti-techniques.html (The 'event generator' idiom)
Em particular, apresentaremos como este padrão é implementado em Java Portanto, além de um Design Pattern (que não depende de linguagem),
apresentaremos um "Idioma Java" que mostra como implementar um Design Pattern numa linguagem particular
Objetivo
O padrão Observer permite que objetos interessados sejam avisados da mudança de estado ou outros eventos ocorrendo num outro objeto
O objeto sendo observado é chamado de: "Subject" (GoF) "Observable" (java.util) "Source" ou "Event Source" (java.swing e java.beans) Provedor de informação (Bill Venners) Gerador de eventos (Bill Venners)
O objeto que observa é chamado de Observer (GoF e java.util) Listener (java.swing)
Java usa este padrão em 2 lugares mas de formas diferentes! A forma java.util não é boa (ver críticas adiante)
Usaremos as palavras Source e Listener
Também chamado de
Event Generator, Dependents, Publisher-Subscriber
Exemplo
Como projetar um sistema que modele um telefone e todos os objetos que poderiam estar interessados quando ele toca?
Os objetos interessados poderiam ser: Pessoas que estejam perto (na mesma sala) Uma secretária eletrônica Um FAX Até um dispositivo de escuta clandestina :-)
Os objetos interessados podem mudar dinamicamente Pessoas entram e saem da sala onde o telefone está Secretárias eletrônicas, FAX, etc. podem ser adicionados ou removidos durante
a execução do programa Novos dispositivos poderão ser inventados e adicionados em versões futuras do
programa Qual é a solução básica de projeto?
Faça do telefone um Event Source
Page 1 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
O problema
Em Java, um objeto (o Source) envia informação para outro objeto (o Listener) pela chamada de um método do Listener
Mas, para que isso seja possível: O Source deve ter uma referência ao Listener O tipo desta referência deve ser uma classe ou interface que declare ou herde o
método a chamar Fazer com que o tipo da referência seja a classe (concreta) do Listener não
funciona bem, porque: O número e tipos dos Listeners não é conhecido em tempo de compilação Os vários listeners poderão não fazer parte de uma mesma hierarquia de
objetos Não queremos criar um acoplamento forte entre Source e Listeners
A solução vai se basear primordialmente em interfaces para resolver o problema Aliás, este é um excelente exemplo do poder de interfaces para prover
polimorfismo envolvendo classes não relacionadas por herança (de implementação)
A solução idiomática em Java
Etapa 1: Definir classes de categorias de eventos Defina uma classe separada de evento para cada categoria principal de eventos
que poderão ser gerados pelo Source Faça com que cada classe de eventos estenda java.util.EventObject Faça com que cada classe encapsule a informação a ser propagada para os
Listeners Use nomes de classe que terminem em Event (exemplo: TelefoneEvent)
Etapa 2: Define interfaces de Listener Para cada categoria de eventos, defina uma interface que estenda
java.util.EventListener e que contenha um método para cada evento (da categoria) que vai gatilhar a propagação de informação do Source para os Listeners
Chame a interface como chamou a classe de eventos, substituindo Event por Listener
Exemplo: Para a classe TelefoneEvent, a interface de Listener seria TelefoneListener
Dê nomes aos métodos da interface para descrever a situação que causou o evento. Use um verbo no pretérito
Exemplo: método TelefoneTocou Cada método deve retornar void e aceitar um parâmetro, uma referência a uma
instância da classe de eventos apropriada Exemplo de uma assinatura completa:
void telefoneTocou(TelefoneEvent e);
Etapa 3: Define classes de adaptação (opcional) Observação:
É muito comum querer uma classe que implemente uma interface fazendo nada para a maioria dos métodos e fazendo algo útil apenas para alguns poucos métodos
Page 2 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
Para ajudar o programador, é comum, em Java, criar uma classe "adapter" que implemente todos os métodos de uma interface com métodos que nada fazem
As classes que devem implementar a interface podem herdar do adapter e fazer override de alguns poucos métodos
Para cada interface de Listener que contenha mais do que um método, defina uma classe adapter que implemente a interface por inteiro com métodos que nada fazem
Dê um nome à classe substituindo Listener com Adapter Exemplo, para a interface TelefoneListener, a classe seria TelefoneAdapter
Etapa 4: Defina a classe observável Source Para cada categoria de eventos que serão propagados a partir de instâncias desta
classe, define um par de métodos para adicionar/remover Listeners Chame os métodos add<nome-da-interface-listener> e remove<nome-da-
interface-listener> Exemplo: addTelefoneListener() e removeTelefoneListener()
Para cada método em cada interface de Listener, define um método privado de propagação de eventos. O método não aceita parâmetros e retorna void. Este método propaga o evento para os Listeners
Chame o método dispara<nome-do-método-listener> Exemplo: disparaTelefoneTocou()
Chamadas ao método de disparo de eventos devem ser adicionas em lugares apropriados da classe Source
Nos lugares onde há mudança de estado ou ocorrência de outros eventos interessantes
Etapa 5: Defina objetos Listener Para ser um Listener de uma certa categoria de eventos, basta implementar a
interface de Listener da categoria de eventos Isso é normalmente feito estendendo a classe Adapter
Estrutura
Page 3 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
Exemplo de código
No arquivo TelefoneEvent.java:
public class TelefoneEvent extends java.util.EventObject { public TelefoneEvent(Telefone source) { super(source); } }
Observe que source é passado como parâmetro e armazenado no objeto (super(source) faz isso)
Isso permite que quem recebe o evento faça java.util.EventObject.getSource() para saber qual objeto gerou o evento
Permite que um mesmo objeto seja Listener de vários objetos Source Também permite que, com esta referência ao Source, o Listener acione outros
métodos do objeto para obter informação Chama-se este modelo de "Pull model" No "Push model", toda a informação necessária está presente dentro do
evento Por simplicidade, não se está encapsulando dados no evento aqui mas seria
possível incluir: O número de telefone que está chamando A data e as horas
No arquivo TelefoneListener.java (interface de Listener):
Page 4 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
public interface TelefoneListener extends java.util.EventListener { void telefoneTocou(TelefoneEvent e); void telefoneAtendido(TelefoneEvent e); }
No arquivo TelefoneAdapter.java (classe Adapter):
public class TelefoneAdapter implements TelefoneListener { void telefoneTocou(TelefoneEvent e) { } void telefoneAtendido(TelefoneEvent e) { } }
A definição do source fica no arquivo Telefone.java:
import java.util.*; public class Telefone { private Collection telefoneListeners = new Vector(); public void tocaFone() { disparaTelefoneTocou(); } public void atendeFone() { disparaTelefoneAtendido(); } public synchronized void addTelefoneListener( TelefoneListener l) { if (telefoneListeners.contains(l)) { return; } telefoneListeners.add(l); } public synchronized void removeTelefoneListener(TelefoneListener l) { telefoneListeners.remove(l); } private void disparaTelefoneTocou() { Collection tl; synchronized (this) { // A interface Collection não tem clone() // mas a classe AbstractCollection tem. // Clonar para evitar problemas de sincronização // durante a propagação tl = ((AbstractCollection)telefoneListeners).clone(); } Iterator it = tl.iterator(); if(!it.hasNext()) { return; } TelefoneEvent evento = new TelefoneEvent(this); while(it.hasNext()) { ((TelefoneListener)(it.next())).telefoneTocou(evento); } }
Page 5 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
// disparaTelefoneAtendido() é semelhante a disparaTelefoneTocou() // Exercício: Que design pattern poderia ser usado para fatorar // o código comum? private void disparaTelefoneAtendido() { Collection tl; synchronized (this) { tl = ((AbstractCollection)telefoneListeners).clone(); } Iterator it = tl.iterator(); if(!it.hasNext()) { return; } TelefoneEvent evento = new TelefoneEvent(this); while(it.hasNext()) { ((TelefoneListener)(it.next())).telefoneAtendido(evento); } } }
Também seria possível usar o Infobus de Java para propagar os eventos Agora, precisamos de classes para usar o esquema acima Primeiro, os Listeners No arquivo SecretariaEletronica.java, temos:
public class SecretariaEletronica implements TelefoneListener { public void telefoneTocou(TelefoneEvent e) { System.out.println("Secretaria escuta o telefone tocando."); } public void telefoneAtendido(TelefoneEvent e) { System.out.println("Secretaria sabe que o telefone foi atendido."); } }
No arquivo Pessoa.java
public class Pessoa { public void escutaTelefone(Telefone t) { t.addTelefoneListener( new TelefoneAdapter() { public void telefoneTocou(TelefoneEvent e) { System.out.println("Eu pego!"); ((Telefone)(e.getSource())).atendeFone(); } } ); } }
Observe que a SecretariaEletronica implementa a interface TelefoneListener diretamente, sem usar TelefoneAdapter
Por outro lado, o objeto Pessoa instancia uma "inner class" anônima que estende TelefoneAdapter e faz override apenas do método que interessa (TelefoneTocou())
Quisemos apenas mostrar formas diferentes de implementar a interface TelefoneListener
Finalmente, precisamos de uma aplicação (arquivo ExemploFone.java)
public class ExemploFone { public static void main(String[] args) { Telefone fone = new Telefone(); Pessoa fulano = new Pessoa(); SecretariaEletronica se = new SecretariaEletronica();
Page 6 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
fone.addTelefoneListener(se); fulano.escutaTelefone(fone); fone.tocaFone(); // começa a brincadeira } }
A execução de ExemploFone imprime:
Secretaria escuta o telefone tocando. Eu pego! Secretaria sabe que o telefone foi atendido.
Quando usar o padrão Observer?
Quando uma abstração tem dois aspectos, um dependente do outro. Encapsular tais aspectos em objetos separados permite que variem e sejam reusados separadamente
Quando uma mudança a um objeto requer mudanças a outros e você não sabe quantos outros objetos devem mudar
Quando um objeto deve ser capaz de avisar outros sem fazer suposições sobre quem são os objetos. Em outras palavras, sem criar um acoplamento forte entre os objetos
Consequências do uso do padrão
Permite que se varie objetos Source e Listeners independentemente Pode-se reusar objetos Source sem reusar seus Listeners e vice-versa Pode-se adicionar Listeners sem modificar o Source ou os outros Listeners
O acoplamento entre Source e Listeners é mínimo Basta que os Listeners implementem uma interface simples Os objetos involvidos poderiam até pertencer a camadas diferentes de software
Suporte para comunicação em broadcast O Source faz broadcast do aviso. Os Listeners podem fazer o que quiserem com
o aviso, incluindo ignorá-lo Do lado negativo: o custo de uma mudança ao estado de um Source pode ser
grande se houver muitos Listeners
Considerações de implementação
Um Listener pode estar cadastrado junto a vários objetos Source Ele pode descobrir quem o esta notificando se o objeto evento contiver uma
referência ao source (como temos no idioma Java) Quem dispara o evento original?
Se cada método que muda o estado do Source disparar um evento, pode haver eventos demais se houver mudanças de estado demais
Neste caso, pode-se deixar um método público do Source que clientes ativam para disparar um evento depois que todas as mudanças ao estado forem feitas
O problema é que o cliente pode "esquecer" de chamar este método Assegurar a consistência do estado do objeto antes de disparar o evento
Particularmente perigoso se um método do Source fizer:
super(novoValor); // Pai dispara o evento
Page 7 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
var = novoValor; // atualiza estado do objeto (é tarde!)
Diferenças entre modelos Push e Pull O modelo Pull acopla os objetos menos pois o modelo Push supõe que o Source
sabe das necessidades de informação dos Listeners O modelo Push pode ser mais eficiente pois o Source pode indicar o que mudou
dentro do evento, facilitando a vida para que os listeners saibam o que mudou Usar eventos diferentes para cada situação pode resolver o problema
Cadastro de interesses Pode-se mudar o protocolo de cadastro (Subscribe) para que o Listener indique
as coisas que o interessam
Críticas sobre outras soluções do mesmo padrão
Gamma apresenta este padrão de uma forma um pouco diferente e menos interessante
Esta forma (fraca) do padrão Observer também é usada nas classes Observer/Observable de java.util
Esses dois exemplos são mais fracos do que o apresentado aqui (baseado no Java Swing) pelos seguintes motivos:
Observable é uma classe da qual você deve herdar para fazer seu objeto um Source
Java não tem herança múltipla e isso queima o (único) cartucho de herança Usar interfaces (herança de tipo) em vez de herança de implementação é
melhor Para implementar um Observer (equivalente a Listener), você tem que
implementar a interface Observer que tem um único método update(Observable, Object)
A solução acima é muito melhor pois podemos ter vários eventos, e vários métodos associados, o que torna o código mais claro
Você prefere entrar no código do método para descobrir que ele tratar de um telefone que está tocando ou é melhor chamar o método telefoneTocou() como fizemos??
A solução acima permite descobrir mais facilmente o que mudou no estado do Source pois podemos usar vários eventos.
De forma geral, o Observer/Observable do Java não é bem visto hoje
Perguntas finais para discussão
O design clássico Model-View-Controller é explicado na nota de implementação #8: Encapsulamento de semântica complexa de de atualização. Poderia fazer sentido às vezes um Observer (ou View) falar diretamente com o Subject (ou Model)?
Quais são as propriedades de um sistema que usa o padrão Observer muito? Como fazer para depurar código em tal sistema?
Como tratar o problema de concorrência com este padrão? Considere, por exemplo, uma mensagem Unregister() sendo enviada para um objeto antes que este envie uma mensagem Notify() para o Gerente de Mudança (ou Controlador).
Examine a tecnologia Infobus do Java e relacione-a com o padrão Observer.
pat-10 programa anterior próxima
Page 8 of 8Observer
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\observer.htm
Comentários finais sobre Design Patterns
Como selecionar um Design Pattern?
Considerando como Design Patterns resolvem Problemas de Design
Vimos aqui uma lista de situações que forçam um redesign Listamos novamente os problemas juntamente com os Design Patterns que ajudam
a resolvê-los Criar um objeto especificando sua classe explicitamente
Abstract Factory, Factory Method, Prototype Dependência de operações específicas
Chain of Responsibility, Command Dependência de plataformas de hardware ou software específicas
Abstract Factory, Bridge Dependência da representação ou implementação de objetos
Abstract Factory, Bridge, Memento, Proxy Dependências algorítmicas
Builder, Iterator, Strategy, Template Method, Visitor Acoplamento forte
Abstract Factory, Bridge, Chain of Responsibility, Command, Façade, Mediator, Observer
Extensão de funcionalidade através da herança Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy
Dificuldade de alterar classes convenientemente Adapter, Decorator, Visitor
Examinando os Objetivos de cada Pattern
Veja a lista de todos os objetivos aqui
Estudando o relacionamento entre Design Patterns
Ver figura abaixo
Page 1 of 3Comentários finais sobre Design Patterns
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\comentarios.htm
Examinando no livro da GoF as semelhanças e diferenças entre padrões
Ver o final da apresentação de cada padrão Ver a introdução aos 3 capítulos do catálogo
Há uma discussão das semelhanças
Considerando o que deve ser variável do Design
Em vez de verificar as causas de redesign, podemos fazer o contrário e verificar o que gostaríamos que fosse modificável sem redesign
O importante aqui é Encapsular o conceito que varia
Page 2 of 3Comentários finais sobre Design Patterns
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\comentarios.htm
Ver tabela abaixo
Finalmente ... O que esperar de Design Patterns Um vocabulário comum de Design
"Vamos usar um Observer aqui ..." Ajuda no entendimento de software existente
Desde que se especifique os Design Patterns usados Patterns farão de você um projetista melhor Um alvo para Refactoring
Mais sobre isso aqui Consiste na reorganização de software existente para melhorar sua qualidade
pat-11 programa anterior
Propósito Design PatternAspecto(s) que varia(m)
(O que pode mudar sem redesign)
Criação
Abstract Factory Famílias de objetos-produto
Builder Como um objeto composto é criado
Factory Method Subclasse do objeto que é instanciado
Prototype A classe do objeto que é instanciado
Singleton A única instância de uma classe
Estrutura
Adapter A interface para acessar um objeto
Bridge A implementação de um objeto
Composite A estrutura e composição de um objeto
Decorator As responsabilidades de um objeto (sem uso de herança)
Façade A interface de um subsistema
Flyweight O custo de armazenamento de objetos
Proxy Como um objeto é acessado; sua localização
Comportamento
Chain of Responsibility O objeto que pode atender a um pedido
Command Quando e como um pedido é atendido
Interpreter Gramática e interpretação de uma linguagem
Iterator Como os elementos de uma coleção são acessados, varridos
Mediator Como e quais objetos interagem uns com os outros
Memento Qual informação privada é armazenada fora de um objeto, e quando
Observer O número de objetos que dependem de um outro objeto; como os objetos dependentes ficam atualizados
State Os estados de um objeto
Strategy Um algoritmo
Template Method Certas etapas de um algoritmo
Visitor Operações que podem ser aplicadas a objetos sem mudar suas classes
Page 3 of 3Comentários finais sobre Design Patterns
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\pat\comentarios.htm
8. Tópicos Avançados Refactoring Extreme Programming Frameworks Componentes
etc programa
Page 1 of 18. Tópicos Avançados
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\etc\index.htm
Refactoring
Introdução
Entropia de software Programas começam num estado bonito, bem projetados mas, com tempo, as
sucessivas adições e mudanças fazem o programa perder sua estrutura Resultado final: espaguete
Motivos Programa muda em formas não previstas Programa não é perfeitamente entendido (mesmo sendo nosso!) e o enxerto é
menos perfeito do que poderia ser Pressões de tempo Seria melhor reprojetar o sistema para limpá-lo, mas preferimos empurrar com
a barriga Tem um excelente livro de Fowler sobre Refactoring
Refactoring
Refactoring é um termo usado para descrever técnicas que diminuem a dor de reprojetar
Mudanças feitas a um programa que alteram apenas sua organização, não sua funcionalidade
Transformações que preservam o comportamento
Por que refactoring é importante?
A única defesa contra a entropia de software Para consertar "bugs" de reusabilidade Permite adicionar padrões de projeto após escrever o programa Permite transformar um programa num framework Deixa você pensar na generalidade amanhã!
Hoje: basta deixar funcionando Parece algo estranho a dizer, mas veremos que a turma do extreme
programming acredita nisso piamente! Necessário para software bonito
Problemas que refactoring pode resolver
Código duplicado Elimina duplicação com novos métodos, novos objetos, movendo coisas comuns
numa superclasse Métodos longos
Métodos devem ser coesos (ser longo é dica de que não está coeso) Métodos devem caber numa tela Métodos devem ser do mesmo nível de abstração Métodos devem estar na classe correta
Acoplamento forte demais Longas listas de parâmetros
Encapsula num objeto Muda o método para acessar o objeto
Page 1 of 2Refactoring
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\etc\refactoring.htm
Vê o que mais deveria estar no objeto switch e variáveis "tipo-de-objeto"
Mudar para polimorfismo Introduzir interfaces e aumentar o polimorfismo
Como fazer refactoring?
Não faça refactoring e adição de funcionalidade ao mesmo tempo Tenha testes automáticos prontos antes de fazer refactoring Faça mudanças muito pequenas de cada vez e teste, teste, teste
Quando fazer refactoring?
Quando parece difícil de enxertar nova funcionalidade Se uma nova funcionalidade adicionou código feio Quando você não aguenta olhar para seu próprio código!
etc-1 programa próxima
Page 2 of 2Refactoring
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\etc\refactoring.htm
Extreme Programming (XP)
Introdução
Alguns super-programadores (e irreverentes!) de smalltalk decidiram criar um processo simples de desenvolvimento de software
Talvez achando que os outros processos eram complexos?!? Ward Cunningham, Ron Jeffries, Martin Fowler, Kent Beck
Cunningham e Beck são a turma do cartão CRC Cuidado! XP foi testado para times pequenos e talvez requeira excelentes
programadores. Não se sabe a aplicabilidade geral da técnica Não é para qualquer um, mas pode ter resultado impressionantes
Muita informação aqui sobre isso. Vale a pena conferir. Também tem um excelente livro de Beck
Extreme Programming
Alegação básica: software é difícil demais para gastar tempo com coisas que não são importantes
Então, o que é importante? Codificar: se, no final do dia, o programa não funciona e não ajuda o cliente a
ganhar dinheiro, você não fez nada Testar: você tem que saber quando terminou. Os testes dizem isso. Se você for
inteligente, vai escrevê-los primeiro para saber instantaneamente quando você terminou
Escutar: tem que saber qual é o problema a resolver. Escute clientes, gerentes e pessoas do negócio
Refatorar: você tem que escutar o que o programa está dizendo para você sobre sua própria estrutura e colocar este conhecimento de volta no programa
Se alguém falar para você que fazer software é outra coisa (além de codificar, testar, escutar, refatorar), ele está tentando lhe vender algo
Não falei que eram irreverentes?! Por isso, inventaram uma disciplina de desenvolvimento de software (xp) baseada
nos seguintes valores: Simplicidade Comunicação Feedback Agressividade
As práticas de XP foram definidas para balancear as forças agindo no projeto
Resumo do processo (com links para o wiki)
Planejamento feito com o PlanningGame Autoridade é delegada para os clientes definirem os requisitos usando
UserStories (parecem Use Cases) Autoridade é delegada para os clientes estabelecerem as prioridades de
desenvolvimento das estórias Desta forma, o cliente pode maximizar o business value
(BusinessValueFirst) Autoridade é delegada para os desenvolvedores estimarem quanto tempo cada
estória levará para ser desenvolvida
Page 1 of 3Extreme Programming
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\etc\xp.htm
Esta delegação de autoridade (que é rara!) provê um ambiente de desenvolvimento livre de estresse
Os clientes possuem boa informação sobre quanto tempo as coisas levam e podem portanto maximizar o custo-benefício das estórias que são desenvolvidas primeiro
Os desenvolvedores pouco se importam com as funcionalidades pedidas (o que também é raro!), porque eles estimam quanto tempo as coisas levam
Já que delegar as prioridades para o cliente pode ser perigoso em alguns casos (pedir algo fundamental mas difícil no fim do projeto é perigoso!), há uma regra que balanceia as coisas: as piores coisas são atacadas primeiro (WorstThingsFirst)
Semelhante ao processo unificado "risk-confronting" O trabalho é acompanhado através de um cronograma (CommitmentSchedule)
revisado a cada poucas iterações Para avaliar novos riscos e oportunidades
As iterações são planejadas (IterationPlanning) entre desenvolvedores e clientes Nada é feito que não seja imediatamente útil e necessário para não impactar os
prazos de desenvolvimento (YouArentGonnaNeedIt) Eles não acreditam em pensar muito no futuro para se preparar para o que vem
depois Faça funcionar o UserStory de hoje!
A simplicidade sempre reina: só se usa a solução mais simples que satisfaça os requisitos do problema (DoTheSimplestThingThatCouldPossiblyWork)
As duas regras acima (YouArentGonnaNeedIt e DoTheSimplestThingThatCouldPossiblyWork) acabam gerando código que precisa ser alterado às vezes. Para simplificar a manutenção/evolução, o código tem que estar sempre limpo e não duplicado. A regra é refatorar impiedosamente (RefactorMercilessly).
Práticas de XP
Para terminar esta introdução, eis a lista de práticas de XP (leia cada uma dessas práticas no wiki e resuma cada uma em uma frase nas suas próprias palavras)
DoTheSimplestThingThatCouldPossiblyWork encoraja não sobre-projetar (nem sub-projetar)
AskTheCode porque ele sabe (... dizer que precisa ser refatorado, ... dizer onde está o bug, ...)
UnitTests: essa turma testa, testa, testa ... para não quebrar o código um do outro. Unit testes são escritos para cada classe e testados usando o TestingFramework. Testes de unidade pertencem ao desenvolvedor.
FunctionalTests para testar as estórias e saber se as necessidades do usuário estão sendo atingidas. Os usuários forneceram os dados usados nestes testes. Testes funcionais pertencem ao cliente.
ContinuousIntegration gerando um processo iterativo para evitar IntegrationHell. A integração de uma nova versão de algo (mesmo pequeno) é quase instantânea, logo depois dos testes.
ContinuousIntegrationRelentlessTesting (como acima, mas lembrando que tem que testar, testar e testar)
RefactorMercilessly para manter o código limpo e o progresso rápido (ver também WikiPagesAboutRefactoring). Só funciona bem se tiver muitos testes para se assegurar de que não quebrou nada.
Recomenda-se chegar à ExtremeNormalForm "Your classes are small and your methods are small; you've said everything
OnceAndOnlyOnce and you've removed the last piece of unnecessary code. Somewhere far away an aikido master stands in a quiet room. he is centered.. aware.. ready for anything.
Page 2 of 3Extreme Programming
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\etc\xp.htm
Outside a sprinter shakes out her legs and settles into the block, waiting for the crack of the gun while a cool wind arches across the track. Ssoftly, a bell sounds.. all of your tests have passed. Your code is in ExtremeNormalForm... tuned to today and poised to strike at tomorrow."
ProgrammingInPairs provê qualidade mais alta, treinamento mútuo e velocidade mais alta. Use uma pessoa menos experiente no teclado e uma mais experiente junto.
SpikeSolution soluções exploratórias rápidas para certos problemas ModelFirst mais SpartanUserInterface ajudam a manter o foco nas necessidades do
usuário. SpartanUserInterface significa fazer uma interface simples e deixar o usuário usar, melhorar o que atrapalha, jogar fora o que não é usado até que o resultado satisfaça.
ExtremePlanning bolar um mapa rápido da solução global com refinamentos incrementais
PlanningGame para formalizar os papeis e responsabilidades no planejamento CountDownToRelease discute como usar ExtremePlanning quando a data de
release final se aproxima. As regras: Deixa o cliente decidir o que falta até soltar o produto Reunião semanal para tratar de IterationPlan StandupMeeting diário rápido
ExtremeReuse adotando software de terceiros e adequando-o a XP pela construção de testes
TossIt para fazer e manter projetos magros, jogue o que não parece útil pela janela. Não precisa ser mantido, documentado, etc.
SystemMetaphor formas de comunicar o sistema para outros e os próprios desenvolvedores. Outras palavras para arquitetura
Pouca coisa: algumas classes, alguns padrões, ... XpDesign quem projeta em XP e quando?
Solução: o time (pequeno) inteiro usando CRC ExtremeDocuments documentação faz parte, embora ela seja diferente às vezes
Para requisitos: UserStories e FunctionalTests (Sim! testes funcionais são requisitos que devem ser satisfeitos! Pense sobre isso ...)
Para análise e design: nenhum documento, só cartões CRC Para codificação: um comentário por classe, se necessário Se o usuário quiser um documento, manual, etc. é só fazer um UserStory
pedindo! SupportCrisis o que fazer quando a m..... bate no ventilador?
Regra 1: pareça calmo (não precisa sê-lo, só parecer) Regra 2: escreva cada problema num cartão Regra 3: atribua um fator de urgência a cada cartão Regra 4: trate de um cartão de cada vez. faça o primeiro. faça o segundo, ...
até que a crise vá embora.
etc-2 programa anterior próxima
Page 3 of 3Extreme Programming
04/02/2012file://C:\_SYNC\_DISCIPLINAS\APOO\APOO Jacques UFCG\etc\xp.htm
Recommended