• Nenhum resultado encontrado

Desenho de Software. António Rito Silva

N/A
N/A
Protected

Academic year: 2021

Share "Desenho de Software. António Rito Silva"

Copied!
152
0
0

Texto

(1)

Desenho de Software

António Rito Silva

(2)

Sumário



Caracterização

 Objectivos  Problemas  Qualidades



Técnicas

Desenho de Software 2



Técnicas



Avaliação e Validação



Casos Notáveis



Exemplo



Conclusões

(3)

Objectivos



Desenho é o processo da passagem

do espaço do problema para o espaço

da solução. À descrição da solução

também se chama desenho.



O desenho descreve uma solução

para o problema que satisfaz os seus

para o problema que satisfaz os seus

requisitos

 note-se que muitas outras soluções satisfazendo os mesmo requisitos são possíveis

(4)

Arquitectura e Desenho



O processo de desenho deve considerar

dois aspectos:

 Descrever para os clientes o que o sistema faz - Arquitectura de Software

 Descreve as funções do sistema

 Está relacionado com os documentos de requisitos

Desenho de Software 4

 Descrever para a equipa de

desenvolvimento como o sistema faz -Desenho de Programas

 Uma descrição dos principais algoritmos

(5)

Decomposição

 O processo de desenho usa sempre alguma forma de decomposição. Existem duas

estratégias de decomposição:

 Desenho Funcional em que o estado do

sistema está centralizado e é partilhado pelas funções que manipulam esse estado

 Desenho com Objectos em que o sistema é

 Desenho com Objectos em que o sistema é visto como um conjunto de objectos que

encapsulam a informação que manipulam.

 Os clientes têm usualmente uma visão mais funcional do sistema...

(6)

Problemas



Porquê este desenho?

 Dado um conjunto de requisitos vários desenhos são possíveis



Abordagens top-down versus

bottom-up

Desenho de Software 6



Propagação de alterações

 A evolução do software pode obrigar a um re-desenho



Não existe uma única decomposição

(7)

Qualidades



Independência

 Coesão  Ligação



Inteligibilidade



Integridade



Integridade



Adaptabilidade

(8)

Componentes Independentes

 Um desenho de qualidade facilita o

entendimento, a implementação, os testes, as alterações e as adaptações do desenho. Mais ainda, facilita o seguimento dos

requisitos no desenho

 A independência entre componentes é uma qualidade do desenho que permite algumas

Desenho de Software 8

qualidade do desenho que permite algumas das propriedades acima

 Para medir a independência entre

componentes usam-se duas medidas:

 Coesão intra-componente

(9)

Coesão Intra-Componente



Um componente é coeso se todos os

seus elementos estão envolvidos na

satisfação dos objectivos do

componente



Quando não existe coesão, ao

modificar uma determinada função é

modificar uma determinada função é

necessário procurar em todos os

componentes as partes relativas à

função



O tipo de coesão determina a

localidade das alterações

(10)

Coesão de Objecto



Cada operação fornece a

funcionalidade que permite que os

atributos do objecto sejam

modificados, inspeccionados e

usados, numa base de

disponibilização de serviços

Desenho de Software 10

(11)

Ligação Inter-Componentes

 Dois componentes dizem-se fortemente ligados quando existe uma grande

dependência entre eles

 Dois componentes dizem-se fracamente ligados quando existe uma fraca

dependência entre eles

 Dois componentes dizem-se desligados

 Dois componentes dizem-se desligados quando são completamente independentes

 A ligação entre componentes depende de:  As referências entre componentes

 Os dados passados entre componentes

 O controlo entre componentes

(12)

Níveis de Ligação



Ligação de Conteúdo – verifica-se

quando um componente conhece a

estrutura interna de outro

componente

 Qualquer alteração interna pode ter

repercussões nos restantes componentes

Desenho de Software 12

repercussões nos restantes componentes



Ligação de Partilha – verifica-se

quando vários componentes

partilham um conjunto de dados

 Todos os componentes dependem da estrutura dos dados partilhados, por exemplo, variáveis globais

(13)

Níveis de Ligação

 Ligação de Controlo – verifica-se quando um componente passa parâmetros que

controlam a lógica de outro componente

 O componente controlado não pode funcionar independentemente do componente controlador

 Ligação de Estrutura – verifica-se quando uma estrutura de dados é usada para

uma estrutura de dados é usada para passar informação entre componentes

 A formatação e organização dos dados gera uma dependência entre os componentes

 Ligação de Dados – verifica-se quando dados são passados entre componentes

(14)

Inteligibilidade



Influência a inteligibilidade:

 Coesão e Ligação – o componente pode ser entendido sem referir outros

componentes

 Nomes – os nomes têm significado e reflectem entidades do espaço do

problema e do espaço da solução

Desenho de Software 14

problema e do espaço da solução

 Documentação – a documentação

justifica e relaciona o desenho com o espaço do problema

 Complexidade – grau de encapsulamento dos algoritmos complexos

(15)

Adaptabilidade



A qualidade que determina a

facilidade de adaptação a novos

requisitos



Requer:

 Ligação fraca

 Abstracções estáveis

 Self-contained – um componente

constituído por interfaces fornecidas e interfaces requeridas

(16)

Técnicas



Estilos arquitecturais



Desenho funcional



Desenho com objectos



Padrões de desenho



Refactorização do desenho

Desenho de Software 16



Refactorização do desenho



Técnicas de aperfeiçoamento do

desenho

(17)

Arquitecturas de Software

 A arquitectura associa os requisitos

identificados no sistema com os

componentes que os vão implementar

 Uma arquitectura de software é constituída por dois elementos básicos:

 Componentes que definem as computações

 Conectores que descrevem as interacções entre

 Conectores que descrevem as interacções entre componentes

 Um estilo arquitectural define uma família de sistemas com o mesmo padrão de

organização estrutural:

 Vocabulário de tipos componente e conector

(18)

Estilos Arquitecturais



Camadas



Repositórios



...

(19)

Camadas

Criptografia

Interface ficheiros

Interface ficheiros

Gestão de chaves

Autenticação

(20)

Camadas: Propriedades

 Vantagens

 Desenvolvimento incremental pois o desenho possui vários níveis de abstracção

 Evolução pois a alteração de uma camada

apenas vai afectar as camadas imediatamente acima e abaixo

 Reutilização pois permitem diferentes implementações de uma camada

Desenho de Software 20

implementações de uma camada

 Desvantagens

 Por vezes é difícil estruturar o problema em níveis de abstracção

 Problemas de desempenho devido à coordenação entre as camadas

(21)

Repositórios

Repositório Aplicação 1 Aplicação 2 Aplicação 3 Repositório (dados partilhados) Aplicação 6 Aplicação 5 Aplicação 4

(22)

Repositórios: Propriedades

 Exemplos  Base de dados  Ambientes de desenvolvimento  Blackboard  Vantagem

 Constitui uma arquitectura aberta uma vez que

Desenho de Software 22

 Constitui uma arquitectura aberta uma vez que a representação dos dados está acessível a

diversos fabricantes de componentes

 Desvantagem

 Dependência dos dados partilhados pois estes devem estar numa representação aceitável para a todos os componentes

(23)

Desenho Funcional



Baseado na decomposição do sistema

num conjunto de funções



As funções partilham o estado global

do sistema que se encontra

centralizado



As funções podem possuir estado

local, mas apenas durante a duração

da sua execução

(24)

Desenho Funcional



Os detalhes dos algoritmos estão nas

funções mas o estado não está

escondido pelo que:

 A alteração do estado global por uma função pode ter efeitos colaterais com um impacto indesejável noutras funções

Desenho de Software 24

um impacto indesejável noutras funções

 As funções têm mais tendência a serem alteradas que os dados

(25)

Desenho com Objectos



Princípios

 Encapsulação – restrição no acesso à representação interna

 Abstracção – eliminação do irrelevante e amplificação do essencial

 Modularidade – construção à custa de

 Modularidade – construção à custa de elementos de menor granularidade

(26)

Desenho com Objectos



Primitivas

 Objecto – agrega os dados e as operações que os manipulam

 Classe – especifica um conjunto de objectos, a sua interface, estrutura e implementação

Desenho de Software 26

implementação

 Herança – uma classe pode ser definida como extensão ou restrição de outra

 Polimorfismo – uma variável pode, em tempo de execução, referir objectos de classes diferentes

(27)

Desenho com Objectos



Objectivos – o resultado final do

desenvolvimento deve ter as

seguintes qualidades:

 Reutilização – capacidade de ser

reutilizado parcialmente ou como um todo noutros programas

todo noutros programas

 Extensibilidade – facilidade de adaptação às alterações de especificação

de modo a se alcançar o princípio do

Aberto/Fechado

(28)

Desenho com Objectos



Herança versus Delegação

 reutilização white-box versus black-box

 estática (tempo de compilação) versus dinâmica (tempo de execução)

 encapsulação

 número de objectos

Desenho de Software 28

(29)

Padrões de Desenho



Verifica-se que:

 Existem problemas que ocorrem recorrentemente

 É possível identificar classes de soluções

 As soluções reflectem as forças em conflito

conflito

(30)

Padrões de Desenho



Considere-se o jogo de xadrez. Para

se ser um bom jogador de xadrez é

necessário:

 Aprender os movimentos permitidos, como termina o jogo,... (primitivas)

 Saber que se deve ocupar centro do

Desenho de Software 30

 Saber que se deve ocupar centro do tabuleiro (princípios)

 Estudar os jogos dos grandes mestres (padrões)

(31)

Padrões de Desenho



Os padrões descrevem uma cultura

de desenvolvimento de programas,

permitindo desta forma a reutilização

de conhecimento



Descrevem soluções que evoluíram

ao longo do tempo

ao longo do tempo



Têm como motivação inicial o

trabalho do arquitecto Christopher

Alexander

(32)

Padrões de Desenho



Os padrões capturam a essência das

soluções bem sucedidas aos

problemas que recorrentemente

surgem quando se desenvolvem

programas

Para além da solução, os padrões

Desenho de Software 32



Para além da solução, os padrões

descrevem o problema e o contexto

em que o problema surge

(33)

Padrões de Desenho

 Propriedades

 capturam o conhecimento da experiência

 fornecem um vocabulário e conhecimento comuns

 estimulam a reutilização de conhecimento

 são os blocos de construção de uma arquitectura

 fornecem um esquema pré-definido para

implementação, descrevendo as suas partes, as suas colaborações e responsabilidades

 identificam e dão nome a abstracções que estão acima das classes e das instâncias

(34)

Padrão de Desenho Proxy



Fornecer um representante ou

substituto (Proxy) para um objecto

 com vista a controlar o acesso ao objecto

 quando o objecto não pode ser acedido pelos meios normais

Desenho de Software 34



O objecto real:

 realiza o trabalho

(35)

Motivação



Uma razão para controlar o acesso a

um objecto é adiar o custo total de

criação e inicialização, até ao

momento em que é realmente

necessário utilizar esse objecto

(36)

Exemplo

 Editor de documentos que permite ter objectos gráficos embebidos nos

documentos

 Restrições:

 objectos gráficos podem ser imagens grandes dispendiosas de criar

Desenho de Software 36

 a abertura de um documento deve ser rápida

 deve-se evitar criar todos os objectos na abertura

 Solução: criar os objectos dispendiosos apenas por pedido (on demand), ou seja, apenas quando a imagem se torna visível

(37)

Problemas da Solução



O que colocar no documento em

substituição da imagem real?



Como esconder o facto da imagem

ser criada por pedido para não

(38)

Solução:

Proxy de Imagem



Usar outro objecto: um Proxy de

imagem



O Proxy actua como substituto da

imagem real

(39)

Proxy de Imagem



O Proxy de imagem é responsável por:

 criar a imagem real quando o editor pede para a exibir, invocando a operação de desenho (Draw)

 enviar pedidos subsequentes directamente para a imagem. Para tal, mantém uma referência para a imagem real

referência para a imagem real

 responder a pedidos relativos ao tamanho, sem ter que instanciar a imagem. Por esse motivo, guarda o tamanho da imagem

(40)

Diagrama de Classes

(41)

Aplicabilidade

 Sempre que houver necessidade de ter uma referência mais versátil e sofisticada para um objecto do que um simples

ponteiro

 Situações comuns:

 Proxy remoto - providencia um representante

 Proxy remoto - providencia um representante local de um objecto que se encontra num espaço de endereçamento diferente

 Proxy virtual - cria objectos dispendiosos apenas por pedido

 Proxy de protecção - controla o acesso ao objecto original

(42)

Forças



Substituir um objecto por um Proxy,

ou vice-versa, deve ser transparente

(43)
(44)

Participações

 Subject (Graphic)

 define uma interface comum para o RealSubject e o Proxy. Desta forma, o Proxy pode ser usado sempre que é esperado o RealSubject

 Proxy (ImageProxy)

 mantém uma referência que lhe permite aceder ao objecto real (RealSubject)

Desenho de Software 44

ao objecto real (RealSubject)

 fornece uma interface idêntica ao Subject, para que o Proxy possa ser substituído pelo

RealSubject

 controla o acesso ao objecto real e pode ser responsável pela sua criação e destruição

(45)

Participações/Colaborações



RealSubject (Image)

 define o objecto real que o Proxy representa



Colaborações

 Proxy envia pedidos ao RealSubject quando apropriado

(46)

Consequências

 Introduz um nível de indirecção no acesso a um objecto

 A indirecção tem muitas utilizações:

 Proxy remoto – permite esconder o facto do objecto residir num espaço de endereçamento distinto

Desenho de Software 46

 Proxy virtual – permite executar optimizações como a criação de um objecto por pedido

 Proxy de protecção – permite a execução de tarefas adicionais de arrumação (housekeeping), quando o objecto é acedido

(47)

Consequências



Geralmente, os objectos reais não

acedem aos seus Proxies



Como o Proxy e o objecto têm a

mesma interface, podem ser

(48)

Refactorização do Desenho



Desenvolver programas úteis hoje e

reutilizáveis amanhã

 Prototipar na primeira passagem

 Expandir o protótipo inicial

 Consolidar estrutura

Desenho de Software 48

 Construir agregações a partir de herança

(49)

Prototipar na Primeira Passagem

 Contexto

 Resolver inicialmente o problema

 Obter resultados, ainda que parciais, rapidamente

 Problema

 Não se constróem programas a partir do “zero”

 Não se constróem programas a partir do “zero”

 É difícil saber com exactidão quais são os requisitos

 É difícil desenhar imediatamente um programa que resolve os requisitos e está preparado para resistir à mudança

(50)

Prototipar na Primeira Passagem

 Solução

 O desenho inicial deve resolver os requisitos conhecidos

 Os programas devem “crescer” e não serem “construídos”

 Utilizar programas existentes

 Programar por diferença

Desenho de Software 50

 Programar por diferença

 Estratégias

 Substantivos implicam objectos, verbos implicam operações

 Reutilizar objectos existentes por herança

 Correr agora, e melhorar mais tarde

(51)

Expandir o Protótipo Inicial



Contexto

 Programas bem sucedidos raramente são estáticos mas terão que evoluir



Problema

 O programa é aplicado em novas situações, pelo que é necessário situações, pelo que é necessário proceder a alterações

 As alterações levam à diminuição da qualidade do programa: estrutura e inteligibilidade.

(52)

Expandir o Protótipo Inicial



Solução

 Localizar as alterações em novas subclasses

 Resulta uma hierarquia que modela uma história de alterações



Estratégias

Desenho de Software 52



Estratégias

 Derivar de código existente em vez de o modificar

 Reutilizar objectos existentes por herança

 Correr agora, e melhorar mais tarde

(53)

Consolidar

 Contexto

 À medida que os objectos evoluem começa-se a esclarecer como é que se pode melhorar o desenho

 Problema

 Programas reutilizáveis raramente surgem após uma primeira etapa de análise

 Objectos têm a capacidade de se alterar de forma

 Objectos têm a capacidade de se alterar de forma controlada: novas funcionalidades e melhorar a qualidade

 Variações encontram-se nas folhas da hierarquia

 Solução

 Refactorizar o programa

(54)

Agregações a Partir de Herança



Contexto

 A hierarquia de classes que surge após a prototipagem e expansão possui as

funcionalidades necessárias mas não é elegante nem reutilizável

 Devem ser seguidos os seguintes princípios de desenho:

Desenho de Software 54

princípios de desenho:

 Factorizar diferentes implementações em

sub-componentes

 Separar métodos que não comunicam

 Enviar mensagens para componentes em

(55)

Agregações a Partir de Herança



Problema

 A herança é utilizada extensivamente nas fases de prototipagem e expansão pois:

 A herança é suportada ao nível da

linguagem linguagem

 Não é claro se um relacionamento é is-a ou

has-a até que as subclasses se tornem mais estáveis

 A herança facilita a partilha de operações e

variáveis, white box, possibilitando obter rapidamente resultados

(56)

Agregações a Partir de Herança



Solução

 Factorizar parte de uma classe numa nova classe. Suponha-se que A é uma subclasse de C:

 Adicionar uma instância de C como variável

de instância de A

Desenho de Software 56

de instância de A

 Mudar as referências para as variáveis e

funções herdadas de C por referências para a variável de instância

(57)

Agregações a Partir de Herança



Consequências

 A transformação de herança em agregação tem alguns benefícios:

 A coesão e a capsulação podem ser

melhoradas por se dividir uma classe em duas

duas

 Agregados podem mudar as sua

componentes em tempo de execução explorando o polimorfismo

 Classes separadas podem ser reutilizadas e

evoluir de forma independente

(58)

Criar Super-Classes Abstractas



Contexto

 A hierarquia de classes que surge após a prototipagem e expansão possui as

funcionalidades necessárias mas não é elegante nem reutilizável

 Devem ser seguidos os seguintes

Desenho de Software 58

 Devem ser seguidos os seguintes princípios de desenho:

 Hierarquias de classes devem ser profundas

 O topo da hierarquia de classes deve

abstracto

(59)

Criar Super-Classes Abstractas



Problema

 A mesma abstracção pode surgir em diferentes partes do programa pois:  Uma prática comum é estender um

programa por cópia e alteração

 Diferentes membros da equipa podem implementar a mesma funcionalidade implementar a mesma funcionalidade

(60)

Criar Super-Classes Abstractas



Solução

 Suponha-se que as classes C1 e C2 partilham uma abstracção:

 Adicionar uma nova classe A1

 Fazer A1 super-classe de C1 e C2

 Determinar o comportamento comum a

Desenho de Software 60

 Determinar o comportamento comum a C1 e C2

 Alterar C1 e C2 de modo a que a

implementação da sua parte comum seja a mesma

 Mover as funções comuns para A1 e apagar de C1 e C2

(61)

Criar Super-Classes Abstractas



Consequências

 A consolidação de abstracções tem os seguintes benefícios:

 Reduz o tamanho do programa

 A separação de abstracções melhora a

inteligibilidade e a reutilização inteligibilidade e a reutilização

 Limita a propagação de erros no código,

(62)

Introduzir Objecto Null



Técnica de re-factorização para

substituir muitas ocorrências de

if (customer == null) plan = BillingPan.basic(); else Desenho de Software 62 plan = customer.getPlan();

por

plan = customer.getPlan();

(63)
(64)

Procedimento

1. Criar uma subclasse da classe original e introduzir o comportamento nulo

1. Criar a operação isNull() em ambas as classes (retorna true apenas na subclasse)

2. Compilar

3. Em todos os locais onde se retorna um null

Desenho de Software 64

3. Em todos os locais onde se retorna um null deve-se passar a retornar o objecto null

4. Em todos os locais que comparam uma variável da classe original com null

substituir com uma invocação a isNull()

(65)

Procedimento

6. Identificar todos os casos em que se invoca uma operação se o objecto for diferente de null e se executa um

comportamento alternativo se for null

7. Para cada um dos casos identificados acima redefine-se a operação da classe acima redefine-se a operação da classe null com o comportamento alternativo

8. Remover a condição de verificação para cada caso em que se usa o

comportamento

(66)

Exemplo

class Site... Customer getCustomer() { return customer; } Customer customer; class Customer...

public String getName() {...}

public BillingPan getPlan() {...}

Desenho de Software 66

public BillingPan getPlan() {...}

public PaymentHistory getHistory() {...}

public class PaymentHistory...

int getWeeksDelinquentInLastYear()

String customerName;

if (customer == null) customerName = “occupant”; else customerName = customer.getName();

(67)

Exemplo

class NullCustomer extend Customer { public boolean isNull() {

return true; }

}

class Customer...

public boolean isNull() { return false;

return false; }

protected Customer() {}

// clients do need to not know about null class static Customer newNull() {

return new NullCustomer(); }

(68)

Exemplo

class Site...

Customer getCustomer() {

return (customer == null) ? Customer.newNull(): customer;

}

Customer customer = site.getCustomer(); BillingPlan plan;

Desenho de Software 68

BillingPlan plan;

if (customer.isNull()) plan = BillingPlan.basic(); else plan = customer.getPlan();

String customerName;

if (customer.isNull()) customerName = “occupant”; else customerName = customer.getName();

(69)

Exemplo

class NullCustomer...

public String getName() { return “occupant”;

}

public Plan getPlan() {

return BillingPlan.basic(); }

String customerName = customer.getName(); String customerName = customer.getName();

Plan customerPlan() = customer.getPlan();

(70)

Aperfeiçoamento do Desenho



Desenho por contrato



Protótipos de desenho

(71)

Desenho por Contrato

 Utiliza-se a técnica de desenho por contrato para

assegurar que o desenho satisfaz a sua especificação

 Um componente, dito cliente, que necessita dos

serviços de outro componente, dito fornecedor, pelo qual celebram um contrato que especifica:

 as obrigações mútuas, chamados de pré-condições

 os benefícios, chamados de pós-condições

 as restrições de coerência, chamadas de invariantes

 Facilitam o desenvolvimento separado, a reutilização, os testes, a verificação da coerência entre as

cláusulas, a verificação da correcção da

(72)

Desenho por Contrato

fill is require in_valve.open out_valve.closed ... code ... ensure in_valve.closed out_valve.closed is_full Desenho de Software 72 is_full end invariant

(73)

Protótipos de Desenho



Permitem verificar se a solução de

desenho vai de facto resolver o

problema



O protótipo deve focar apenas no

aspecto de desenho sobre o qual

existem dúvidas

existem dúvidas

(74)

Validação e Verificação

 Validação – certificar se o desenho

satisfaz todos os requisitos do utilizador

 Verificação – certificar se a solução incorpora as qualidades de desenho requeridas

 Existem várias técnicas:

 Validação Matemática pode ser difícil mas muito

Desenho de Software 74

 Validação Matemática pode ser difícil mas muito útil para alguns aspectos críticos

 Métricas de Desenho permitem quantificar a qualidade

 Comparação de Desenhos para avaliar os compromissos

(75)

Métricas de Desenho

 Não se pode gerir aquilo que não se controla e não se pode controlar aquilo que não se consegue

medir. Tom DeMarco

 As seguintes métricas propostas por Robert Martin medem a qualidade do desenho com objectos.

Considera módulos reutilizáveis de componentes:

 Ligação de Fora/Dentro (LFD): número de classes de fora

 Ligação de Fora/Dentro (LFD): número de classes de fora do módulo que dependem de classes de dentro do módulo

 Ligação de Dentro/Fora (LDF): número de classes de dentro do módulo que dependem de classes fora do módulo

 Instabilidade (I): I = LDF / (LFD + LDF), I=0 indica estabilidade e I=1 indica instabilidade do módulo

(76)

Métricas de Desenho

 Princípio do Aberto/Fechado

 Um sistema não pode ter todos os módulos estáveis

 Um módulo deve ser aberto à extensão e fechado à modificação

 Desta forma, os módulos estáveis devem ser muito abstractos enquanto que os módulos instáveis devem ser muito concretos

Desenho de Software 76

instáveis devem ser muito concretos

 Uma medida de abstracção:

 Abstracção (A): A = número de classes

abstractas do módulo / número total de classes do módulo, A=0 significa que é concreto e A=1 que é abstracto

(77)

Métricas de Desenho

 É desejável que os módulos estejam próximos da sequência principal  Distância (D): D = |(A+I-1) / 2| 1 (0,1) instabilidade 1 (1,0)

(78)

Comparação de Desenhos

 Uma especificação possibilita muitos

desenhos

 Deve-se construir diversas soluções para o problema usando diferentes estilos

arquitecturais

 Decidir qual o melhor desenho para os objectivos do sistema

Tabelas de comparação definem para cada

Desenho de Software 78

 Tabelas de comparação definem para cada atributo de qualidade se um particular

estilo arquitectural o suporta ou não

 Tabela de pesos indica qual a prioridade que cada atributo de qualidade tem para o sistema a desenvolver, permite calcular um valor para cada estilo arquitectural

(79)

Documentação do Desenho



Devem ser apresentadas quais as

razões do desenho que indiquem os

aspectos críticos e os compromissos

da solução



Utilizar as notações necessárias para

exprimir o desenho e as suas

exprimir o desenho e as suas

(80)

Casos Notáveis

 Padrão Data Access Object

 http://java.sun.com/blueprints/corej2eepatterns/Patt erns/DataAccessObject.html

 Padrão Intercepting Filter

 http://java.sun.com/blueprints/corej2eepatterns/Patt erns/InterceptingFilter.html

 Moldura de Objectos JUnit

Desenho de Software 80

 Moldura de Objectos JUnit

 Erich Gamma and Kent Beck

 http://junit.sourceforge.net/doc/cookstour/cookstour .htm

 Padrão Arquitectural Modelo-Vista-Controlador

 In Pattern-Oriented Software Architecture: A System of Patterns. Frank Buschmann et al.

(81)

Padrão Data Access Object



Contexto

 Acesso aos dados depende da fonte dos dados

 tipo de armazenamento

(82)

Problema

 As aplicações podem usar a API JDBC mas mesmo num SGBD relacional a sintaxe e o formato dos comando SQL pode variar

devido ao particular produto

 Existe ainda maior variação quando se usam diferentes tipos de SGBD

Desenho de Software 82

usam diferentes tipos de SGBD

 Cria-se uma dependência entre o código da aplicação e o código de acesso aos dados que dificulta a migração entre diferentes

tipos de SGBD e diferentes produtos de um mesmo tipo

(83)

Forças



Componentes aplicacionais

necessitam de obter/guardar

informação de/para um suporte

persistente



As APIs dos suportes persistentes

variam dependendo do vendedor do

variam dependendo do vendedor do

produto e do tipo do produto



Componentes aplicacionais

usualmente usam APIs proprietárias



A portabilidade dos componentes

aplicacionais é afectada

(84)

Solução



Utilizar um objecto de acesso aos

dados (DAO) para abstrair e

encapsular todos os acessos à fonte

de dados



O DAO gere a ligação à fonte de

dados para obter e guardar dados

Desenho de Software 84

dados para obter e guardar dados



O DAO funciona como um adaptador

entre o componente e a fonte de

(85)
(86)

Participantes e Colaborações

(87)

Estratégia

(88)

Estratégia



Abstract Factory e Factory Method

(89)
(90)

Código: Fábrica Abstracta

package ServidorPersistente;

public interface ISuportePersistente { public void iniciarTransaccao()

throws ExcepcaoPersistencia;

public void confirmarTransaccao() throws ExcepcaoPersistencia;

public void cancelarTransaccao() throws ExcepcaoPersistencia; Desenho de Software 90 throws ExcepcaoPersistencia; public IItemPersistente getIItemPersistente(); public ISeccaoPersistente getISeccaoPersistente(); public ISitioPersistente getISitioPersistente(); }

(91)

Código: Fábrica Concreta

package ServidorPersistente.OJB;

public class SuportePersistenteOJB implements ISuportePersistente {

Implementation _odmg = null; Database _db = null;

...

public IItemPersistente getIItemPersistente() getIItemPersistente()

{ return new ItemOJB(); } public ISeccaoPersistente

getISeccaoPersistente()

{ return new SeccaoOJB(); } public ISitioPersistente

getISitioPersistente()

(92)

Código: Interface DAO

package ServidorPersistente; import Dominio.ISitio;

public interface ISitioPersistente { ISitio readByNome(String nome)

throws ExcepcaoPersistencia;

Desenho de Software 92

void write(ISitio sitio)

throws ExcepcaoPersistencia; void delete(ISitio sitio)

throws ExcepcaoPersistencia; void deleteAll()

throws ExcepcaoPersistencia; }

(93)

Código: Implementação OJB

package ServidorPersistente.OJB; public class SitioOJB

extends ObjectFenixOJB

implements ISitioPersistente { public SitioOJB() { }

...

public void deleteAll()

throws ExcepcaoPersistencia {

String oqlQuery = "select all from " + Sitio.class.getName();

super.deleteAll(oqlQuery); }

(94)

Código: Objecto Valor

package Dominio;

public class Sitio implements ISitio { private String _nome;

private int _anoCurricular; private int _semestre;

private String _departamento; private String _curso;

private List _seccoes;

Desenho de Software 94

private List _seccoes;

// códigos internos da base de dados private int _codigoInterno;

...

// getter e setter methods ...

(95)

Consequências



Permite a transparência



Facilita a migração



Reduz a complexidade do código do

componente aplicacional



Centraliza os acessos a dados numa



Centraliza os acessos a dados numa

camada separada



Acrescenta uma camada adicional



Necessita do desenho de uma

hierarquia de classes

(96)

Padrão Intercepting Filter



O mecanismo de tratamento de

pedidos da camada de apresentação

trata pedidos muito diferentes entre

si, o que implica tratamento

especializado para cada um deles

Alguns pedidos têm tratamento

Desenho de Software 96



Alguns pedidos têm tratamento

imediato, enquanto outros

necessitam de ser modificados ou

verificados antes de serem

(97)

Problema



É necessário haver pré- e

pós-processamento dos pedidos feitos por

um cliente Web e das respectivas

respostas

 O cliente foi autenticado?

A sessão do cliente é válida?

 A sessão do cliente é válida?

 O tipo de browser do cliente é suportado?

(98)

Forças



Deve haver processamento comum a

todos os pedidos e respostas



Centralização da lógica comum



A adição e remoção dos componentes

de processamento deve ser

Desenho de Software 98

de processamento deve ser

independente

(99)

Solução



Criar filtros para processar os

serviços comuns de forma que:



Interceptem os pedidos que

chegam e as respostas que são

enviadas

enviadas



Seja possível adicionar ou remover

os filtros de forma discreta sem ser

necessário modificar o código já

(100)

Estrutura

(101)
(102)

Participantes

 GestorFiltros

 Gere o processamento dos filtros

 Cria a CadeiaFiltros com os filtros apropriados, na ordem correcta, e inicia o processamento

 CadeiaFiltros

 Conjunto ordenado de filtros independentes

 Filtro1, Filtro2, Filtro3

Desenho de Software 102

 Filtro1, Filtro2, Filtro3

 Filtros individuais que são mapeados para um alvo

 A CadeiaFiltros coordena o seu processamento

 Alvo

(103)

Custom Filter (1/3)



Custom Filter

 Definido pelo programador

 Dois exemplos alternativos:

 Utilização do Decorator para encapsular o

processamento dos pedidos dentro dos filtros

filtros

 Utilização de Gestor de Filtros e Cadeia de

Filtros para coordenar o processamento dos filtros

(104)

Custom Filter (2/3)

 Exemplo – Utilização do Decorator

Desenho de Software 104  Problema

 Se alterarmos a forma de tratar o pedido, tem que se alterar também o código dos filtros e do

(105)

Custom Filter (3/3)

 Exemplo – Utilização de Gestor e Cadeia de Filtros

(106)

Standard Filter



Standard Filter

 Os filtros são controlados declarativamente, utilizando um ficheiro de configuração

 Este ficheiro inclui o mapeamento dos filtros para URL’s específicos

 Quando um cliente faz um pedido a que

corresponde aquele URL mapeado, os filtros são

Desenho de Software 106

corresponde aquele URL mapeado, os filtros são processados por ordem antes que o alvo do

pedido seja invocado <filter>

<filter-name> StandardEncodeFilter </filter-name> ...

</filter> ...

<filter-mapping>

<filter-name> StandardEncodeFilter </filter-name> <url-pattern> /EncodeTestServlet </url-pattern> </filter-mapping>

(107)

Outras Estratégias



Base Filter

 Superclasse comum a todos os filtros utilizados

 Partilhada por todos os filtros

 Encapsula funcionalidades comuns

Template Filter



Template Filter

 Base Filter que contém uma estrutura fixa a que todos os filtros têm que

obedecer

(108)

Consequências



Centraliza o controlo com fraca

ligação entre filtros



Promove a reutilização



Configuração independente e

declarativa

Desenho de Software 108

declarativa

(109)

Moldura de Objectos

 Uma moldura de objectos é um desenho

reutilizável que modela parte de um sistema de software e é descrito por um conjunto de classes abstractas e pela forma como as suas instâncias colaboram

 Uma moldura de objectos resulta sempre de uma análise do domínio

 Uma boa moldura de objectos pode reduzir o  Uma boa moldura de objectos pode reduzir o

custo de desenvolvimento de uma ordem magnitude pois permite a reutilização de desenho e código.

 O desenvolvimento de uma boa moldura de

objectos é difícil pois tem de ser simples para ser fácil de aprender e facilmente utilizável, e

(110)

Moldura de Objectos Junit em UML



Um exemplo de utilização do UML

como forma de comunicar desenho



Dá ênfase ao que é relevante



Não substitui o código

(111)
(112)

A Moldura de Testes

(113)
(114)

Moldura de Objectos JUnit



Objectivos

 Simplificar a construção de testes de

modo a que os programadores se sintam motivados a escrever testes

 Escrever testes que sejam perenes e

sejam utilizáveis por outras pessoas para

Desenho de Software 114 sejam utilizáveis por outras pessoas para além do criador

 Seja possível combinar testes feitos por diferentes pessoas

 Utilizar testes para construir novos testes

(115)

Caso de Teste



Tornar cada caso de teste num

objecto de modo a simplificar a sua

manipulação



O padrão Comando “encapsula um

pedido como um objecto permitindo

listar pedidos, guardar pedidos, ...”

listar pedidos, guardar pedidos, ...”

(116)

Caso de Teste

Desenho de Software 116

public abstract class TestCase implements Test { private final String fName;

public TestCase(String name) { fName= name;

}

public abstract void run();

(117)

Parte Fixa



Como separo a parte fixa de um teste

da parte de teste



O padrão Método Matriz “define um

esqueleto de algoritmo permitindo

que algumas das etapas surjam em

subclasses mas preservando-se a

subclasses mas preservando-se a

estrutura do algoritmo”

(118)

Parte Fixa

public void run() {

Desenho de Software 118

public void run() { setUp();

runTest(); tearDown(); }

protected void runTest() { }

protected void setUp() { }

protected void tearDown() { }

(119)

Resultados do Teste



Pretende-se registar o resultado das

falhas e um sumário condensado dos

sucessos

(120)

Resultados do Teste

public class TestResult extends Object { protected int fRunTests;

public TestResult() { fRunTests= 0;

} }

public void run(TestResult result) { result.startTest(this); setUp(); Desenho de Software 120 runTest(); tearDown(); }

public synchronized void startTest(Test test) { fRunTests++;

(121)

Faltas dos Testes



Existem dois tipos de faltas: falhas e

erros. Os primeiros podem ser

antecipados. Em ambos os casos

pretende-se que os testes continuem

a executar

(122)

Faltas dos Testes

public void run(TestResult result) { result.startTest(this); setUp(); try { runTest(); } catch (AssertionFailedError e) { result.addFailure(this, e); } catch (Throwable e) { result.addError(this, e); Desenho de Software 122 result.addError(this, e); } finally { tearDown(); } }

protected void assert(boolean condition) { if (!condition)

throw new AssertionFailedError(); }

(123)

Faltas dos Testes



É necessário registar as faltas em

TestResult

public synchronized void addError(Test test, Throwable t) { fErrors.addElement(new TestFailure(test, t));

}

public synchronized void addFailure(Test test, Throwable t) { fFailures.addElement(new TestFailure(test, t));

}

public class TestFailure extends Object { protected Test fFailedTest;

protected Throwable fThrownException; }

(124)

Proliferação de Classes



A aplicação do padrão Comando a

cada caso de teste leva a uma

proliferação de classes, uma para

cada teste



Como juntar os casos de teste numa

única classe e serem uniformes do

Desenho de Software 124

única classe e serem uniformes do

ponto de vista do invocador dos

testes?



O padrão Adaptador “converte a

interface de uma classe numa outra

que é esperada pelo cliente”

(125)
(126)

Proliferação de Classes

Padrão Adaptador

public class TestMoneyEquals extends MoneyTest {

public TestMoneyEquals() { super("testMoneyEquals"); } protected void runTest () { testMoneyEquals(); }

}

Ou utiliza-se reflexão do JAVA

protected void runTest() throws Throwable {

Desenho de Software 126 protected void runTest() throws Throwable {

Method runMethod= null; try {

runMethod= getClass().getMethod(fName, new Class[0]); } catch (NoSuchMethodException e) {

assert("Method \""+fName+"\" not found", false); }

try {

runMethod.invoke(this, new Class[0]); }

// catch InvocationTargetException and IllegalAccessException }

(127)

Composição de Casos de Teste



Necessita-se executar diversos testes

e de modo a que o resultado é escrito

no mesmo TestResult



O padrão Composição “compõe

objectos em árvores que representam

hierarquias todo-parte permitindo

hierarquias todo-parte permitindo

tratar uniformemente os objectos

individuais e as composições”

(128)

Composição de Casos de Teste

Desenho de Software 128

public interface Test {

public abstract void run(TestResult result); }

public class TestSuite implements Test { private Vector fTests= new Vector(); }

(129)

Composição de Casos de Teste

public void run(TestResult result) {

for (Enumeration e= fTests.elements(); e.hasMoreElements(); ) { Test test= (Test)e.nextElement();

test.run(result); }

}

public void addTest(Test test) { fTests.addElement(test); }

public static Test suite() {

TestSuite suite= new TestSuite();

suite.addTest(new MoneyTest("testMoneyEquals")); suite.addTest(new MoneyTest("testSimpleAdd")); }

public static Test suite() {

return new TestSuite(MoneyTest.class); }

(130)

Moldura de Objectos JUnit

(131)

Padrão Arquitectural MVC

 O padrão arquitectural

Modelo-Vista-Controlador (MVC) divide uma aplicação interactiva em três componentes: modelo, vista e controlador

 O modelo contém o núcleo da funcionalidade e dos dados

 As vistas mostram a informação ao utilizador

 As vistas mostram a informação ao utilizador

 Os controladores tratam das entradas dos utilizadores

As vistas e os controladores formam a

interface. Um mecanismo de propagação

das alterações assegura a coerência entre a interface utilizador e o modelo

(132)

Exemplo

(133)

Problema

 As interfaces utilizador são muito passíveis de sofrerem pedidos de alteração

 Diferentes utilizadores têm requisitos

diferentes, e por vezes conflituosos, sobre como deve ser a interface utilizador

 Um sistema que satisfaça os requisitos acima deve permitir:

acima deve permitir:

 A mesma informação ser apresentada de forma diferente em distintas janelas

 A visualização e comportamento da aplicação reflecte imediatamente as alterações aos dados

 Alterações à interface são fáceis e possíveis em tempo de execução

(134)

Solução

 Existem três tipos de componentes: modelo, vista e controlador

 O modelo encapsula o cerne dos dados e da

funcionalidade, é independente das representações de saída e do comportamento associado às entradas

 A vista mostra os dados ao utilizador, obtém os dados do modelo e permite a existência diferentes

Desenho de Software 134

dados do modelo e permite a existência diferentes vistas do modelo

 O controlador recebe os eventos de entrada que converte para pedidos de serviços ao modelo e às vistas

 A separação entre o modelo a vista e o controlador permite múltiplas vistas do mesmo modelo

(135)

Estrutura

Model coreData : undefined attach() detach() notify() getData() Observer update() update() coreData : undefined attach() detach() notify() getData() 1 * getData() service() View initialize() makeController() activate() display() update() Controller initialize() handleEvent() update() initialize() makeController() activate() display() update() initialize() handleEvent() update() getData() service() 1 0..1

(136)

Dinâmica: Propagação

: C o n t r o l l e r : M o d e l : V i e w h a n d l e E v e n t s e r v i c e n o t i f y u p d a t e g e t D a t a Desenho de Software 136 u p d a t e g e t D a t a

(137)

Dinâmica: Inicialização

: M o d e l : V i e w m a i n p r o g r a m : c r e a t e c r e a t e i n i t i a l i z e a t t a c h m a k e C o n t r o l l e r c r e a t e : C o n t r o l l e r m a k e C o n t r o l l e r c r e a t e i n i t i a l i z e a t t a c h s t a r t E v e n t P r o c e s s i n g

(138)

Consequências

 Vantagens

 Múltiplas vistas do mesmo modelo

 Sincronização das vistas

 Troca dinâmica de vistas e controladores

 Alteração do look and feel

 Potencial para moldura de objectos

 Desvantagens

 Aumento da complexidade

Desenho de Software 138

 Possível excesso do número de propagação de alterações

 Ligação forte entre as vistas e os respectivos controladores

 Ligação forte das vistas e controladores com o modelo

 Ineficiência dos acessos aos modelos por parte dados das vistas

 Alteração da vista e do controlador quando é necessário portar

(139)

Exemplo



Páginas WEB



Baseadas em html



scripts – comandos que interpretam

o pedido e retornam html (mais

usado para os pedidos)

usado para os pedidos)



server pages – o programa está

estruturado no contexto da página

de texto que é retornada (mais

(140)

Exemplo



MVC na WEB

 Combina pedidos como scripts e respostas como server pages

 Modelos separados da apresentação

(141)
(142)

Conclusões



P62 – Relacionar o Desenho com os

Requisitos

 É necessário saber que requisitos são satisfeitos por cada componente



P63 – Avaliar Alternativas

 Enumerar um conjunto de arquitecturas

Desenho de Software 142

 Enumerar um conjunto de arquitecturas e analisar cada uma delas de acordo com os objectivos

 Alguns métodos de desenho têm como resultado arquitecturas específicas,

nessa situação deve-se seleccionar o método mais adequado

(143)



P65 - Encapsular



P66 – Não Reinventar a Roda

 Reutilizar ideias, componentes, técnicas, ...



P67 – Não Complicar

 Existem duas formas de construir um

Conclusões

 Existem duas formas de construir um desenho de software. Uma forma é fazer o desenho tão simples que é

óbvio não ter deficiências. Uma outra

forma é fazer o desenho tão complicado que não tem deficiências óbvias. C. A. R. Hoare

(144)



P68 – Evitar Muitos Casos

Especiais



Se existirem provavelmente foi

porque se definiram as

abstracções ou os algoritmos

errados

Conclusões

Desenho de Software 144

errados

(145)

Conclusões



P69 – Minimizar a Distância

Intelectual



A distância entre o problema e a

solução



Pessoas diferentes percebem



Pessoas diferentes percebem

diferentes estruturas quando

analisam o mesmo problema

(146)

Conclusões



P71 – Manter a Integridade do

Desenho



Usar um número limitado de

“formas” de desenho



Alterar as “formas” estabelecidas

Desenho de Software 146



Alterar as “formas” estabelecidas

apenas para introduzir mais

elegância ou simplicidade



P73 – Usar Ligação Fraca e

(147)



P74 – Desenhar para as

Alterações



O desenho deve ser:



Modular



Portável

Conclusões



Portável



Flexível



Com a menor distância intelectual



Compreensível

(148)

Conclusões



P77 – Introduzir Generalidade no

Software

 Componentes genéricos podem cumprir o seu objectivo em diversas situações sem terem de ser alterados

 Componentes genéricos são mais difíceis de desenhar e normalmente possuem

Desenho de Software 148

 Componentes genéricos são mais difíceis de desenhar e normalmente possuem

um menor desempenho, mas:

 São ideais quando uma função semelhante

tem que ser executada em vários sítios

 Permitem maior reutilização sem

modificação

 Reduzem as despesas de manutenção

devido ao reduzido número de componentes

(149)



P78 – Introduzir Flexibilidade no

Software

 Componentes flexíveis podem ser facilmente modificados para se

adaptarem a uma nova situações

 Componentes flexíveis são mais difíceis

Conclusões

 Componentes flexíveis são mais difíceis de desenhar, mas:

 Possuem um maior desempenho que os

componentes genéricos

 Permitem maior reutilização que os

(150)

Referências

 Pfleeger01, Capítulo 5, excepto 5.2 e 5.4.

 David95, Alguns princípios do Capítulo 4.

 Erich Gamma et al. Bridge Design Pattern. In Gamma95.

 Brian Foote and William Opdyke. Lifecycle and Refactoring Patterns That Support

Desenho de Software 150

and Refactoring Patterns That Support

Evolution and Reuse. In Pattern Languages of Program Design 1995. Capítulo 14.

http://www.laputan.org/pub/foote/evolution. pdf

(151)

Referências

 Martin Fowler. Introduce Null Object. In

Refactoring: Improving the Design of Existing Code 1999.

http://www.refactoring.com/catalog/introduc eNullObject.html

 Robert Martin. OO Design Quality Metrics: An Analysis of Dependencies.

Analysis of Dependencies.

http://www.objectmentor.com/publications/o odmetrc.pdf

 Deepak Alur et al. Data Access Object pattern

http://java.sun.com/blueprints/corej2eepatte rns/Patterns/DataAccessObject.html

(152)

Referências

 Deepak Alur et al. Intercepting Filter pattern

http://java.sun.com/blueprints/corej2eepatte rns/Patterns/InterceptingFilter.html

 Martin Fowler. A UML Testing Framework. Software Development OnLine. April 1999.

http://www.ddj.com/dept/architect/1844156 74

Desenho de Software 152 74

 Erich Gamma and Kent Beck. JUnit A Cook's Tour.

http://junit.sourceforge.net/doc/cookstour/co okstour.htm

 Frank Buschmann et al. Model-View-Controller. In Buschmann96.

Referências

Documentos relacionados

A não uniformização quanto ao método de referência pode promover diferenças entre as curvas de calibração geradas por laboratórios de dosimetria citogenética, que podem

A primeira lei do movimento, de Newton, diz que inércia é a incapacidade de qualquer corpo alterar a sua situação de repouso ou de movimento sem causa exterior. O nadador produz

A evolução técnico-tática de função do goleiro de Handebol, apresentado por Greco, Soares das Neves e Silva Matias, no capítulo seguinte (5), mostra aspectos da importância da

Para o ensino do basquete tendo como proposta pedagógica a Psicomotora os objetivos terão, portanto, que levar em consideração o ser em todos os aspectos já citados, e não apenas

Vantagens. Permitem avaliar melhor as atitudes para análise das questões estruturadas;. São muito úteis como primeira questão de um determinado tema porque deixam o

Estes resultados apontam para melhor capacidade de estabelecimento inicial do siratro, apresentando maior velocidade de emergência e percentual de cobertura do solo até os 60

Entendendo, então, como posto acima, propõe-se, com este trabalho, primeiramente estudar a Lei de Busca e Apreensão para dá-la a conhecer da melhor forma, fazendo o mesmo com o

A variação do pH da fase móvel, utilizando uma coluna C8 e o fluxo de 1,2 mL/min, permitiu o ajuste do tempo de retenção do lupeol em aproximadamente 6,2 minutos contribuindo para