• Nenhum resultado encontrado

Técnicas de Projeto e Implementação de Sistemas I

N/A
N/A
Protected

Academic year: 2023

Share "Técnicas de Projeto e Implementação de Sistemas I"

Copied!
94
0
0

Texto

(1)

Técnicas de Projeto e

Implementação de Sistemas I

Prof.: Diego Passos

dpassos@ic.uff.br

Conteúdo: Introdução aos Padrões de Projeto

Slides baseados no material cedido pelo Prof.

Anselmo Montenegro.

Documento baseado no material preparado pelo Prof. Luiz André (http://www.ic.uff.br/~lapaesleme/)

(2)

Introdução

Padrões de Projeto

Engenharias desenvolvem sistemas baseados em

Composição de componentes existente

Componentes usados em outros sistemas

(3)

Engenharia de Software

Padrões de Projeto

Antes: Focada no desenvolvimento original

Atualmente : Processo de desenvolvimento baseado em um reuso de software sistematizado, trazendo:

• Software de melhor qualidade

• Desenvolvimento mais rápido

• Menor custo

(4)

Benefícios de Reuso

Padrões de Projeto

Confiabilidade Crescente

Toda vez que um software é utilizado, ele é novamente testado

Componentes já utilizados e testados em outros sistemas são mais confiáveis que novos componentes

Risco de Processo Reduzido

Margem de erro dos custos de reuso menor que dos custos de desenvolvimento

Uso Efetivo de Especialistas

Especialista desenvolve software reutilizável encapsulando seu conhecimento, ao invés de desenvolver as mesmas funcionalidades repetidas vezes em

diferentes projetos

(5)

Experiência

Padrões de Projeto

Outro fator importante no desenvolvimento de software é a experiência do desenvolvedor

Desenvolvedores experientes, em geral, são capazes de analisar um sistema e propor projetos que são flexíveis e de fácil manutenção

Por que esta tarefa é mais fácil para eles em comparação com desenvolvedores mais jovens?

Porque os desenvolvedores mais experientes provavelmente já enfrentaram os mesmos problemas antes

Eles já encontraram estas soluções antes e agora são capazes de reaproveitá- las.

(6)

Padrões de Projeto

Em projeto de software muitos problemas ocorrem de forma repetida

Um padrão de projeto é uma solução geral reutilizável para problemas recorrentes em projeto de software

Não é uma solução fechada e sim uma descrição de como um problema pode ser resolvido em diferentes situações

Formaliza boas praticas de programação para um determinado contexto Representa a experiência que desenvolvedores já tiveram em sistemas anteriores

(7)

Padrões de Projeto

Conceito de padrões de projeto não é original da Computação.

Conceito surgiu no contexto da arquitetura, com Christopher Alexander.

Ele notou a existência de problemas recorrentes nos projetos de edifícios e cidades.

Propôs e validou uma “linguagem de padrões” que permite que soluções consagradas para estes problemas recorrentes sejam descritas e

posteriormente consultadas.

(8)

Padrões de Projeto

“Cada padrão descreve um problema que ocorre repetidas vezes em nosso ambiente, e então descreve o núcleo da sua solução para aquele problema, de tal maneira que seja possível usar essa solução milhões de vezes sem nunca fazê-la da mesma forma duas vezes.”

Christopher Alexander sobre padrões em arquitetura de construções

(9)

Padrões de Projeto

“Os padrões de projeto são descrições de objetos que se comunicam e classes que são customizadas para resolver um problema de projeto genérico em um contexto específico.”

Gamma, Helm, Vlissides & Johnson, sobre padrões de projeto em software

(10)

26/09/2014 Técnicas de Programação Avançada 10

Padrões de Projeto Vs Princípios de OO

Padrões de Projeto

Padrões de projeto não são simplesmente o uso de princípios de projeto orientado a objetos

Padrões são formas não triviais de se resolver problemas de projeto O.O que foram colecionados ao longo do

tempo

Por se tratarem de soluções consagradas, são bem

testadas e avaliadas

(11)

26/09/2014 Técnicas de Programação Avançada 11

Padrões de Projeto

Padrões de projeto também são vantajosos por estabelecerem um vocabulário compartilhado entre desenvolvedores

Quando você usa um nome de um padrão, você menciona um conjunto de qualidades, características e restrições do padrão

Usar padrões permitem manter a discussão no nível do projeto sem se ater a detalhes de implementação

Outros desenvolvedores automaticamente entendem as referências

(12)

26/09/2014 Técnicas de Programação Avançada 12

Padrões de Projeto Vs Frameworks Vs Bibliotecas

Padrões de Projeto

Padrões de projeto também não devem ser confundidos com bibliotecas e frameworks

Bibliotecas e frameworks nos ajudam a escrever nosso código usando suas APIs

Elas fornecem implementações específicas e concretas

que vinculamos ao código

(13)

26/09/2014 Técnicas de Programação Avançada 13

Padrões de Projeto Vs Frameworks Vs Bibliotecas

Padrões de Projeto

Logo, elas não nos ajudam a estruturar nossos próprios aplicativos de forma flexível, estender e manter

Os padrões de projeto nos ajudam a repensar nosso modo de implementar soluções para problemas de projeto

Eles estão em um nível de abstração acima do de

bibliotecas

(14)

26/09/2014 Técnicas de Programação Avançada 14

Padrões de Projeto Vs Outros Padrões

Padrões de Projeto

O termo “padrão” é muito usado em Engenharia de Software

Além dos padrões de projeto, há também os padrões arquiteturais e os padrões de codificação (idiomas), por exemplo

Os padrões de projeto não devem, portanto, ser

confundidos com outros padrões em ES.

(15)

Catálogos

Padrões de Projeto

Hoje padrões de projeto são técnicas consagradas dentro da Engenharia de Software

Há conferências na área de computação especificamente

dedicadas a proposta e documentação destes padrões: Pattern Languages of Programming

Há também catálogos de padrões:

Repositórios contendo padrões que podem ser

consultados em busca de uma solução adequada para um projeto

(16)

Catálogos

Padrões de Projeto

Um destes “repositórios” é o livro “Padrões de Projeto: Soluções Reutilizáveis de software orientado a objetos” (Gamma, Helm, Johnson, Vlissides)

Livro apresenta 23 padrões de projeto divididos em:

Padrões de criação Padrões estruturais

Padrões comportamentais

Estes 23 padrões são conhecidos como padrões GoF (Gang of Four) ou padrões Gamma

(17)

Formato

Padrões de Projeto

Dentro de um repositório, padrões são descritos através de um formato bem definido

Este formato pode variar, dependendo do repositório, mas em geral contém os seguintes campos:

Nome: geralmente bastante descritivo, idealmente faz parte do jargão do desenvolvedor de software

Problema: descreve o contexto que justifica a utilização do padrão

Solução: descreve os elementos da solução

Consequências: descreve vantagens e desvantagens do uso do padrão

(18)

Formato

Padrões de Projeto

Outras informações também são comumente encontradas nos catálogos. Exemplo dos campos usados por Gamma et al.:

Nome e classificação

Intenção e objetivo

Também conhecido como

Motivação

Aplicabilidade

Estrutura

Participantes

Colaborações

Implementação

Exemplo de código

Usos conhecidos

Padrões relacionados

(19)

Consequências e Aplicabilidade

Padrões de Projeto

Dentre as informações contidas na descrição de um padrão, as consequências e a aplicabilidade são de especial importância Padrões não devem ser forçados em um projeto

Eles devem ser aplicados quando necessário, quando seu uso traz benefícios e as vantagens superam as desvantagens.

Do contrário, eles somente aumentam a complexidade do projeto

(20)

Objetivos Desta Disciplina

Padrões de Projeto

Em relação aos padrões de projeto, são dois os objetos desta disciplina:

1. Conhecer e saber aplicar um subconjunto dos padrões GoF (cerca de 10).

2. Ser capaz de entender a descrição, as restrições, objetivos e consequências de um novo padrão.

Espera-se que o aluno saiba avaliar quando e como um determinado padrão deve ser empregado e quais as suas consequências

(21)

Como Entender e Aplicar Padrões

Padrões de Projeto

Gamma et al. provê algumas diretrizes para compreender e aplicarmos padrões de projeto. Em suma:

1. Deve-se ler o padrão por inteiro inicialmente (visão geral)

2. Deve-se estudar atentamente as seções Estrutura, Participantes e Colaborações

3. Deve-se estudar a seção de exemplo de código

4. Deve-se definir as classes da sua aplicação de acordo com a solução do padrão

5. Deve-se definir nomes dos componentes do projeto relacionados aos usados no padrão

6. Finalmente, deve-se implementar as operações e colaborações do padrão

(22)

Os Anti-Padrões

Padrões de Projeto

Da mesma forma que soluções genéricas bem sucedidas para

projetos de software (padrões de projeto) são documentadas, há também na literatura a documentação do oposto

Anti-padrão é o nome dado a uma solução nos mesmos moldes dos padrões de projeto, mas que leva a resultados indesejados.

Por “resultados indesejados”, pode-se entender:

• Aumento da complexidade do projeto.

• Não eficácia da solução (solução não resolve de fato o problema).

• Etc.

(23)

Os Anti-Padrões

Padrões de Projeto

Anti-padrões são, portanto, exemplos do que não se deve fazer no desenvolvimento de um software

Eles proveem exemplos de estruturas e metodologias que devemos evitar durante um projeto de software

(24)

Exemplo: A Inversão da Pizza

Padrões de Projeto

Exemplo abstrato de “padrão de projeto” provido por Brad Appleton: http://www.bradapp.com/docs/pizza-inv.html

Embora uma brincadeira, exemplifica a descrição de um padrão do projeto

Propõe uma solução para um “problema de fundamental

importância para a maioria dos desenvolvedores de software”.

Utiliza a notação (formato) encontrado no catálogo de Gamma et al.

(25)

Exemplo: A Inversão da Pizza

Padrões de Projeto

Documento começa especificando um nome e uma classificação para o padrão: “Pizza Inversion”, classe “Object Consumptional”

Descreve também o objetivo: consumir pizzas quentes sem se queimar e rapidamente.

Finalmente, provê outros nomes: “Pizza Sandwich”

(26)

Exemplo: A Inversão da Pizza

Padrões de Projeto

Em seguida, temos a motivação para uso do padrão:

“Um dos problemas mais comuns encarados por engenheiros de software envolve a necessidade de sustentação nutricional ao mesmo tempo em que se mantém a produtividade pessoal.”

...

“O consumo de pizza é uma solução comumente utilizada para resolver este problema importante.”

...

“Dado que eficiência e escalonamento de tarefas são

preocupações importantes, desenvolvedores frequentemente

precisam consumir múltiplas fatias de pizza redonda em períodos curtos de tempo.”

(27)

Exemplo: A Inversão da Pizza

Padrões de Projeto

“O molho de tomate é geralmente muito quente, e o queijo da

cobertura compõe o problema formando uma camada de isolação térmica.”

...

“Ao tentar comer pizza rapidamente, a gordura do queijo e o

molho de tomate quente podem causar queimaduras severas no céu da boca.”

...

“A abordagem ingênua de esperar que a pizza esfrie parece

razoável a princípio. Mas o aumento resultante na latência entre a chegada da pizza e seu consumo impõe uma penalidade de

desempenho inaceitável que impede a produtividade do programador.”

(28)

Exemplo: A Inversão da Pizza

Padrões de Projeto

“Um método envolve inverter uma fatia de pizza sobre outra.”

“Ao inverter um dos pedaços de pizza como mostrado acima, o projeto estrutural resultante forma uma hierarquia em camadas na qual a massa encapsula o queijo, o molho e a cobertura do céu da boca e da língua. Isto isola a boca do queijo quente e do molho, ao mesmo tempo em que permite que a pizza seja consumida a aproximadamente o dobro da taxa normal.”

(29)

Exemplo: A Inversão da Pizza

Padrões de Projeto

Em seguida, são listadas as condições de aplicabilidade:

• “Há múltiplas fatias de pizza saborosa e quente que você deseja consumir”.

• “Você deseja consumir a pizza rapidamente e de forma limpa, sem queimar o céu da boca.”

• “Você se encontrar em um ambiente bastante informal.”

(30)

Exemplo: A Inversão da Pizza

Padrões de Projeto

O próximo campo do padrão mostra a estrutura da solução, isto é, lista as classes e relacionamentos envolvidos na solução:

(31)

Exemplo: A Inversão da Pizza

Padrões de Projeto

A próxima seção é a de Participantes, explicando quais são as classes envolvidas na estrutura e o que elas representam no sistema:

(32)

Exemplo: A Inversão da Pizza

Padrões de Projeto

Em seguida, são descritas as Colaborações, isto é, como as classes participantes interagem na solução:

(33)

Exemplo: A Inversão da Pizza

Padrões de Projeto

São também listadas as consequências (positivas e negativas) do uso do padrão:

“As porções consumidas de PizzaSlices tem a massa em cima e embaixo, formando uma camada de isolamento efetivo...”

“A vazão é aumentada em um fator de 2...”

“Tempo de latência é reduzido...”

“Pizzas com massa muito grossa resultam em uma hierarquia muito alta/profunda que pode ser inviável para consumo.”

“O resultante consumo de altas doses de colesterol pode resultar em bloqueio das artérias e causar riscos à saúde...”

(34)

26/09/2014 Técnicas de Programação Avançada 34

Exemplo: A Inversão da Pizza

Padrões de Projeto

Na seção posterior, são listados comentários sobre possíveis implementações do padrão:

“Se você tem uma única fatia de pizza, você pode visualizar uma linha imaginária passando do centro da fatia, dividindo-a em duas metades simétricas. Dobre uma das metades sobre a outra...”

“Um dos aspectos desejáveis de uma pizza é o aroma (...) O uso do padrão pode reduzir o efeito desta sensação prazerosa de olfato.

Um compromisso geralmente empregado consiste em tirar um breve momento no início para aproveitar totalmente a visão e o cheiro da pizza...”

(35)

Exemplo: A Inversão da Pizza

Padrões de Projeto

Finalmente, são listados “Usos Conhecidos” do padrão:

“Usado frequentemente na Domino’s, Little Ceasar’s, Pizza Hut e Papa John’s Pizza”

....

“Um ‘calzone’ é basicamente uma instância pré-fabricada do padrão”.

(36)

Um exemplo de problema

Padrões de Projeto

Para introduzir o conceito de Padrões de Projeto utilizaremos exemplos expostos no livro Padrões de Projeto (Use a Cabeça) além de outros encontrados nas Bibliografia do curso

(37)

Bibliografia

Padrões de Projeto

Use a Cabeça ! Padrões de Projetos (design Patterns) - 2ª Ed. Elisabeth Freeman e Eric Freeman. Editora: Alta Books

Padrões de Projeto – Soluções reutilizáveis de software orientado a objetos. Erich Gamma, Richard Helm, Ralph Johnson. Editora Bookman

(38)

Técnicas de Projeto e

Implementação de Sistemas I

Prof.: Diego Passos

dpassos@ic.uff.br

Conteúdo: Padrão Singleton

Material baseados nos slides cedidos pelo Professor Anselmo Montenegro.

Documento baseado no material preparado pelo Prof. Luiz André (http://www.ic.uff.br/~lapaesleme/)

(39)

Introdução e Motivação

Padrão Singleton

Suponha o seguinte cenário:

Um software de controle comercial contém diversos módulos que geram documentos a serem

impressos (faturas, notas fiscais, folha de pagamento, orçamentos,...)

No entanto, há apenas uma impressora para servir

todos os módulos

(40)

Introdução e Motivação

Padrão Singleton

Note que os módulos não têm necessariamente relação uns com os outros.

Alguns são (logicamente) bem distantes: qual a relação entre folha de pagamento dos funcionários e a fatura de um cliente?

Em muitos casos, a única relação entre eles é

compartilhar uma mesma impressora

(41)

Introdução e Motivação

Padrão Singleton

Suponha que no sistema haja uma classe “Impressora”

que fornece acesso à impressora física

A classe pode implementar, por exemplo, métodos para requisitar a impressão de um documento, solicitar o

status da fila de impressão, etc.

(42)

Introdução e Motivação

Padrão Singleton

Como há uma única impressora física, não podemos instanciar a classe “Impressora” múltiplas vezes:

Causaria múltiplas filas de impressão, tentativas de acesso simultâneo à impressora física, etc.

Temos, portanto, que garantir que todos os módulos que

precisam da impressora tenham acesso a ela, mas que

ela seja instanciada uma única vez em todo o sistema.

(43)

Introdução e Motivação

Padrão Singleton

Primeira tentativa: declarar uma instância global da classe

“Impressora”.

Declaramos uma variável global acessível para todos os módulos.

Quando o sistema é inicializado, instanciamos a classe

“Impressora” e armazenamos a referência na variável global.

Módulos que precisam de acesso simplesmente acessam a variável.

(44)

Introdução e Motivação

Padrão Singleton

Problemas com esta solução? Vários.

Principal razão é que ela não impede possíveis erros de

programadores em diferentes pontos do código. Exemplos:

1. Nada impede que um determinado módulo destrua a instância global.

2. Nada impede que um determinado módulo crie uma nova instância local da classe “Impressora”.

3. Se método de inicialização é mudado e, por um erro, desenvolvedor remove a instanciação do objeto global, erros ocorrerão em outras partes do código.

(45)

Introdução e Motivação

Padrão Singleton

Este tipo de situação, na qual uma determinada classe só pode ser instanciada uma única vez, é o cenário que motiva o uso do

Padrão Singleton.

Há muitos exemplos de classes com esta característica na modelagem de componentes de hardware:

Impressora, porta serial, ...

Mas também pode ocorrer em outros contextos, dependendo das regras de negócio do sistema.

(46)

Introdução e Motivação

Padrão Singleton

Outra característica da classe a ser instanciada que motiva o padrão Singleton é a necessidade de fácil acesso por diversos módulos não relacionados no sistema.

A solução baseada em variáveis globais torna o acesso fácil, mas não impede a instanciação de múltiplos objetos.

A solução proposta pelo padrão Singleton é que a própria classe a ser instanciada seja responsável pelo controle da única instância.

Ela impede a criação de múltiplas instâncias e disponibiliza um mecanismo para que outras classes acessam a instância única.

(47)

Aplicabilidade

Padrão Singleton

Segundo Gamma et al., o Padrão Singleton é aplicável quando:

1. É necessário garantir a existência de uma única instância de uma determinada classe no sistema.

2. A instância deve ser acessível de um ponto conhecido por outras classes espalhadas pelo sistema.

3. A classe a ser instanciada deve ser extensível através de subclasses, permitindo que os clientes (classes que a usam) possam utilizar instâncias da subclasse de forma transparente.

(48)

Estrutura, Participantes e Colaborações

Padrão Singleton

Em termos de estrutura:

Participantes:

• Classe Singleton: classe do sistema que só pode ser instanciada uma única vez. Atributo instance guarda a referência para a única instância.

Além do método getInstance() e do atributo instance, a classe terá todos os métodos e atributos “normais” (i.e., que modelam o

conceito que a classe representa).

(49)

Estrutura, Participantes e Colaborações

Padrão Singleton

Em termos de estrutura:

Colaborações:

• Os clientes da classe Singleton (i.e., classes que precisam acessar a classe Singleton): obtém referência para a

instância através do método getInstance().

• O método getInstance() garante que sempre a mesma instância é retornada.

(50)

Estrutura, Participantes e Colaborações

Padrão Singleton

Em termos de estrutura:

Note que ambos o método getInstance() e o atributo instance são estáticos.

Isto significa que ambos podem ser acessados sem que o chamador necessite de uma instância da classe.

(51)

Implementação

Padrão Singleton

Como o padrão Singleton é implementado?

public class Singleton {

private static Singleton instance = null;

// Outros atributos…

public static Singleton getInstance() {

if(instance == null) instance = new Singleton();

return instance;

}

private Singleton() {}

// Outros métodos…

}

(52)

Implementação

Padrão Singleton

Declaramos um atributo estático do mesmo tipo da classe que estamos implementando.

Por garantia, inicializamos com null.

public class Singleton {

private static Singleton instance = null;

// Outros atributos…

public static Singleton getInstance() {

if(instance == null) instance = new Singleton();

return instance;

}

private Singleton() {}

// Outros métodos…

}

(53)

Implementação

Padrão Singleton

Declaramos o método estático getInstance() retornando o mesmo tipo da classe que estamos implementando.

Método verifica se instância já foi criada. Caso contrário, a cria.

Atributo instance é sempre retornado.

public class Singleton {

private static Singleton instance = null;

// Outros atributos…

public static Singleton getInstance() {

if(instance == null) instance = new Singleton();

return instance;

}

private Singleton() {}

// Outros métodos…

}

(54)

Implementação

Padrão Singleton

A implementação provê um mecanismo acessível a partir de qualquer outra classe do sistema (método estático e público getInstance()) para acesso à instância única da classe.

Supondo que todos os clientes utilizem o método getInstance() para obter a instância, o problema de múltiplas instâncias é

resolvido.

Mas o que garante que determinados clientes não tentarão simplesmente criar uma nova instância usando new?

(55)

Implementação

Padrão Singleton

Detalhe importante do código:

Construtor da classe Singleton é declarado como private.

Significa que ele só pode ser acessado por métodos da própria classe Singleton.

public class Singleton {

private static Singleton instance = null;

// Outros atributos…

public static Singleton getInstance() {

if(instance == null) instance = new Singleton();

return instance;

}

private Singleton() {}

// Outros métodos…

}

(56)

Implementação

Padrão Singleton

Consequência: objetos da classe Singleton só podem ser instanciados dentro da própria classe.

public class Singleton {

private static Singleton instance = null;

// Outros atributos…

public static Singleton getInstance() {

if(instance == null) instance = new Singleton();

return instance;

}

private Singleton() {}

// Outros métodos…

}

(57)

Implementação

Padrão Singleton

Note que a instância de fato da classe Singleton só é criada na primeira vez que o método getInstance() é chamado.

Isto é chamado de lazy instantiation.

A instanciação lazy pode ser vantajosa: instância só é criada quando e se necessária.

Se não é necessária, ela não ocupa memória (ou qualquer outro recurso do sistema).

(58)

Implementação

Padrão Singleton

Suponha, no entanto, que as duas primeiras chamadas ao método getInstance() sejam concorrentes.

Algum problema?

(59)

10/5/2014 Técnicas de Programação Avançada 22

Implementação

Padrão Singleton

Suponha, no entanto, que as duas primeiras chamadas ao método getInstance() sejam concorrentes.

Algum problema?

Sim, pode ocorrer uma condição de corrida:

• Primeira chamada é preemptada imediatamente antes de criar a instância.

• Segunda chamada começa a ser executada, vê que não há instância e a cria.

• Thread da primeira chamada volta a executar, e cria outra instância (teste já havia sido feito antes).

(60)

Implementação

Padrão Singleton

Soluções?

1. Transformar o método getInstance() em um método sincronizado (synchronized).

• Adiciona um overhead.

• Só faz diferença nas primeiras chamadas.

2. Utilizar uma eager instantiation.

(61)

Consequências

Padrão Singleton

Uma consequência imediata do Padrão Singleton é a proteção contra múltiplas instanciações da classe Singleton.

• Não há como uma outra classe do sistema erroneamente criar uma segunda instância da classe.

Uma consequência mais sutil é a possibilidade de manipular um número fixo de instâncias, ao invés de uma única.

• Conceito de pool de recursos.

(62)

Consequências

Padrão Singleton

No pool de recursos, queremos limitar o número de cópias de um determinado recurso.

Considere, por exemplo, um sistema em que vários módulos acessam um banco de dados (possivelmente de forma

concorrente).

Se deixarmos cada módulo abrir sua própria conexão com o banco de dados, podemos ter um número muito grande de conexões

abertas.

Conexões gastam recursos do sistema. Logo, desejamos limitá-las.

(63)

Consequências

Padrão Singleton

Podemos fazer isso com uma classe do tipo Singleton.

Ao invés do método getInstance() retornar sempre a mesma instância, ele armazena um contador de instâncias criadas.

A cada nova chamada, ele verifica se o limite de instâncias já foi gerado.

• Se não, uma nova instância é criada e retornada.

• Se sim, verifica se alguma das instâncias já criadas está disponível.

(64)

Consequências

Padrão Singleton

Este “Singleton com Contador” garante um número máximo (configurável) de instâncias a serem criadas no sistema.

Se o tempo para instanciação do recurso é alto (por exemplo, depende de troca de mensagens via rede), este padrão reduz o tempo médio de acesso ao recurso

• Após a primeira instanciação, as demais serão “de graça”.

(65)

Subclasses

Padrão Singleton

Suponha a seguinte variação do problema da impressora:

Embora a empresa tenha apenas uma impressora para servir todos os módulos do sistema, o tipo (marca, modelo) de

impressora pode variar.

• Exemplo: a impressora original dá defeito e tem que ser trocada por outra diferente.

O sistema, portanto, tem uma classe “Impressora”, mas tem também subclasses específicas para modelos diferentes de impressora suportadas.

(66)

Subclasses

Padrão Singleton

Quando o sistema é executado no servidor da empresa, o tipo de impressora é informado.

• Parâmetro de linha de comando.

• Arquivo de configuração.

• ...

Com base nesta informação, sistema deve instanciar a subclasse adequada.

Mas note que a restrição da instância única continua valendo.

(67)

Subclasses

Padrão Singleton

Podemos usar o padrão Singleton nesse caso?

(68)

Subclasses

Padrão Singleton

Podemos usar o padrão Singleton nesse caso?

Segundo Gamma et al., sim. Estrutura:

(69)

Subclasses

Padrão Singleton

As subclasses só devem re-implementar (se necessário) os métodos relativos à manipulação da impressora.

(70)

Subclasses

Padrão Singleton

Alguns problemas de implementação desta solução em Java:

Como já visto, o construtor da superclasse “Impressora” deve ser privado, evitando que ela possa ser instanciada externamente.

O problema: em Java, classes que tem (apenas) construtores privados não podem ser estendidas (construtor da subclasse chama o construtor da classe).

Alternativa?

(71)

Subclasses

Padrão Singleton

Se tornarmos o construtor da superclasse “Impressora” protected, ele continua não podendo ser acessado externamente, mas passa a permitir acessos das subclasses.

Neste caso, devemos declarar o construtor de cada subclasse

como public, já que a superclasse precisa instanciar as subclasses.

(72)

Subclasses: Exemplo de Código

Padrão Singleton

public class Impressora {

private static Impressora instance = null;

// Outros atributos…

public static Impressora getInstance(String tipo) { if(instance == null) {

if (tipo.equals(“epson”)) instance = new Epson();

else if (tipo.equals(“canon”)) instance = new Canon();

else if (tipo.equals(“hp”)) instance = new Hp();

}

return instance;

}

protected Impressora() {}

// Outros métodos…

}

(73)

Subclasses: Exemplo de Código

Padrão Singleton

public class Epson extends Impressora{

// Atributos específicos…

public Epson() {}

// Métodos específicos…

}

public class Canon extends Impressora{

// Atributos específicos…

public Canon() {}

// Métodos específicos…

}

public class Hp extends Impressora{

// Atributos específicos…

public Hp() {}

// Métodos específicos…

}

(74)

Subclasses: Exemplo de Código

Padrão Singleton

Algum problema?

(75)

Subclasses: Exemplo de Código

Padrão Singleton

Algum problema?

Sim, os construtores das subclasses são públicos.

Logo, qualquer módulo do sistema pode instanciá-las diretamente, quantas vezes quiser.

(76)

Subclasses: Exemplo de Código

Padrão Singleton

Solução?

(77)

10/5/2014 Técnicas de Programação Avançada 40

Subclasses: Exemplo de Código

Padrão Singleton

Solução?

O primeiro passo é tornar os construtores das subclasses privados (ou protegidos, se elas ainda serão estendidas, como no caso de

“Impressora”).

Mas nesse caso, como o método getInstance() de “Impressora”

tem acesso a instancias das subclasses?

Uma possibilidade: as subclasses devem reimplementar suas próprias versões do método getInstance(). O getInstance() de

“Impressora” apenas delega a funcionalidade à versão adequada.

(78)

Subclasses: Exemplo de Código

Padrão Singleton

public class Impressora {

protected static Impressora instance = null;

// Outros atributos…

public static Impressora getInstance(String tipo) { if(instance == null) {

if (tipo.equals(“epson”)) Epson.getInstance();

else if (tipo.equals(“canon”)) Canon.getInstance();

else if (tipo.equals(“hp”)) Hp.getInstance();

}

return instance;

}

protected Impressora() {}

// Outros métodos…

}

(79)

Subclasses: Exemplo de Código

Padrão Singleton

public class Epson extends Impressora{

// Atributos específicos…

private Epson() {}

public static Epson getInstance() { if(instance == null) {

instance = new Epson();

}

return instance;

}

// Métodos específicos…

}

(80)

Subclasses: Exemplo de Código

Padrão Singleton

Algum problema?

(81)

Subclasses: Exemplo de Código

Padrão Singleton

Algum problema?

Sim, mas bastante sutil.

Um programador suficientemente motivado poderia criar uma subclasse de “Impressora” apenas para poder instanciá-la

externamente.

Se ele criasse tal subclasse com um construtor público e sem nenhum outro método ou atributo, ele poderia instanciar a

subclasse que, implícitamente, seria apenas um nome diferente para a classe “Impressora”.

(82)

Subclasses: Exemplo de Código

Padrão Singleton

Note, no entanto, que esta situação é extrema.

Não se trata de um erro acidental, mas algo feito

intencionalmente para burlar a estrutura do projeto.

Exceto por este caso patológico, esta estrutura mantém as características desejadas:

• Garantir unicidade da instância.

• Garantir acesso de qualquer outro módulo do sistema; e

• Permitir a que a classe seja estendida.

(83)

Anti-padrão?

Padrão Singleton

Padrão Singleton está catalogado como um padrão GoF.

Ele é um dos 23 padrões documentados no livro de Gamma et al.

O livro, no entanto, é de 1994.

Atualmente, há controvérsia em relação à validade do Singleton.

Há pessoas que o consideram até um anti-padrão.

(84)

Anti-padrão?

Padrão Singleton

A motivação para este ponto de vista está no fato do Singleton

“parecer” uma variável global.

Variáveis globais são usualmente consideradas uma prática ruim por várias razões:

• Dificultam o entendimento do código (de onde vem esta variável?).

• Poluem o namespace (congeridade de nome).

• Tem estado imprevisível (podem ser alteradas por diferentes módulos em qualquer ordem).

• Dificultam testes de unidade.

(85)

Anti-padrão?

Padrão Singleton

Outra crítica comum em relação aos Singletons é ilustrada pelo seguinte código:

VerificadorCartao.init();

Cobranca c = new Cobranca();

Cobranca.debitaCartaoCliente();

(86)

Anti-padrão?

Padrão Singleton

Neste exemplo, a classe “Cobrança” utiliza uma classe

“VerificadorCartao” para fazer o débito de um valor.

VerificadorCartao.init();

Cobranca c = new Cobranca();

Cobranca.debitaCartaoCliente();

(87)

Anti-padrão?

Padrão Singleton

Para que o verificador funcione, ele precisa estar inicializado.

Logo, antes de executarmos o método debitaCartaoCliente(), chamamos a inicialização.

VerificadorCartao.init();

Cobranca c = new Cobranca();

Cobranca.debitaCartaoCliente();

(88)

Anti-padrão?

Padrão Singleton

O método debitaoCartaoCliente() assume que a inicialização foi feita anteriormente, e não funcionará caso contrário.

VerificadorCartao.init();

Cobranca c = new Cobranca();

Cobranca.debitaCartaoCliente();

(89)

Anti-padrão?

Padrão Singleton

Esta situação é obviamente ruim.

Estamos criando uma solução com alta congeneridade entre módulos.

Se o desenvolvedor esquece a inicialização, o sistema não funciona.

(90)

Anti-padrão?

Padrão Singleton

Perguntas:

No exemplo anterior, a classe “VerificadorCartao” é, de fato, um Singleton?

Os princípios do padrão Singleton, como catalogado por Gamma et al. estão de fato sendo empregados?

(91)

Anti-padrão?

Padrão Singleton

A resposta, em ambos os casos, é não.

O padrão Singleton não propõe este tipo de construção. Ele não diz que determinados métodos (de inicialização, por exemplo) devem ser chamados em um módulo, quando necessários em outro.

Ao contrário, a ideia de um Singleton seria que a própria classe

“Cobranca”, que usa a classe “VerificadorCartao”, obtivesse a

instância utilizada (o que, se necessário, causaria a inicialização do verificador).

(92)

Anti-padrão?

Padrão Singleton

O problema do exemplo anterior, portanto, não é a utilização do Singleton.

Mas sim a utilização incorreta do padrão.

De fato, assim como outras construções em programação (como o GOTO), a maioria dos exemplos em que Singletons são ruins

resultam de usos errados ou desnecessários do padrão.

(93)

Conclusão

Padrão Singleton

Assim como todos os padrões de projeto, o uso dos Singletons traz compromissos.

Desenvolvedor deve ser capaz de avaliar os prós e contras e a aplicabilidade do padrão.

Mais que isso, caso o padrão seja aplicável, deve-se efetuar a implementação de maneira correta.

(94)

Padrão Singleton

Bibliografia

Padrões de Projeto – Soluções reutilizáveis de software orientado a objetos. Erich Gamma, Richard Helm, Ralph Johnson. Editora Bookman

Referências

Documentos relacionados

Os interessados em adquirir quaisquer dos animais inscritos nos páreos de claiming deverão comparecer à sala da Diretoria Geral de Turfe, localizada no 4º andar da Arquibancada

Assim, este estudo buscou identificar a adesão terapêutica medicamentosa em pacientes hipertensos na Unidade Básica de Saúde, bem como os fatores diretamente relacionados

libras ou pedagogia com especialização e proficiência em libras 40h 3 Imediato 0821FLET03 FLET Curso de Letras - Língua e Literatura Portuguesa. Estudos literários

Inicialmente, destacamos os principais pontos de convergência: • O papel tático e operacional exercido pela área de TI dos Câmpus é claramente identificável, tanto nos

Antes de caminhar efetivamente ao encontro de métodos e mecanismos que nos levem a solucionar os problemas de ajustamento e inclusão dos jovens oriundos das “tribos” juvenis urbanas

A Lei nº 2/2007 de 15 de janeiro, na alínea c) do Artigo 10º e Artigo 15º consagram que constitui receita do Município o produto da cobrança das taxas

Detectadas as baixas condições socioeconômicas e sanitárias do Município de Cuité, bem como a carência de informação por parte da população de como prevenir

Segundo o mesmo autor, a animação sociocultural, na faixa etária dos adultos, apresenta linhas de intervenção que não se esgotam no tempo livre, devendo-se estender,