Post on 19-Jun-2015
description
ESTADO DE MATO GROSSO
SECRETARIA DE ESTADO DE CIÊNCIAS, TECNOLOGIA E
EDUCAÇÃO SUPERIOR
UNIVERSIDADE DO ESTADO DE MATO GROSSO
FACULDADE DE CIÊNCIAS EXATAS
CAMPUS UNIVERSITÁRIO DE BARRA DO BUGRES
DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO
JUNIOR CESAR DA ROCHA
APLICAÇÃO DE PADRÕES DE PROJETO PARA A MELHORIA DA
MANUTENABILIDADE DE SOFTWARE
BARRA DO BUGRES – MT
2012
JUNIOR CESAR DA ROCHA
APLICAÇÃO DE PADRÕES DE PROJETO PARA A MELHORIA DA
MANUTENABILIDADE DE SOFTWARE
Trabalho de conclusão de curso apresentado ao
Departamento de Ciência da Computação,
Universidade do Estado de Mato Grosso –
UNEMAT, como requisito para obtenção do
título de Bacharel em Ciência da Computação,
sob orientação do professor Esp. Alexandre
Berndt.
BARRA D BUGRES – MT
2012
JUNIOR CESAR DA ROCHA
APLICAÇÃO DE PADRÕES DE PROJETO PARA A MELHORIA DA
MANUTENABILIDADE DE SOFTWARE
Trabalho de conclusão de curso apresentado ao
Departamento de Ciência da Computação,
Universidade do Estado de Mato Grosso –
UNEMAT, como requisito para obtenção do
título de Bacharel em Ciência da Computação
na área de engenharia de software.
Banca Examinadora
____________________________________________
Prof. Esp. Alexandre Berndt - UNEMAT
Orientador
___________________________________________
Prof. Me. José Fernandes Torres da Cunha - UNEMAT
Convidado
____________________________________________
Prof. Me. Allan Karly Luizi - UNEMAT
Indicado pelo Departamento
Aprovado em: 28 de Junho de 2012
AGRADECIMENTOS
A Deus, por ter proporcionado todas as condições humanas para que eu pudesse
alcançar este objetivo.
Aos meus pais e irmãos que, com todo apoio, atenção e carinho, contribuíram para a
conclusão desse trabalho monográfico.
Ao meu orientador, professor Alexandre Berndt, pelo ensinamento e dedicação
disponibilizados no auxilio à conclusão dessa monografia.
A todos os meus professores, pela dedicação e ensinamentos disponibilizados nas
aulas. Cada um de forma especial contribuiu para a conclusão desse trabalho e
consequentemente para minha formação profissional.
Aos amigos e colegas que fiz durante o curso, em especial, Paulo Henrique, Michael
e Rodrigo, por todos os momentos que vivenciamos juntos durante esses quatro anos e meio
de curso.
À UNEMAT, pela formação que recebi em Ciência da Computação.
RESUMO
A comunidade de desenvolvimento de software vem adotando cada vez mais os conceitos
propostos pelos padrões de projeto no processo de desenvolvimento de software. Estudos
reportam evidências de que esses padrões causam um impacto positivo na qualidade do
software, mas em alguns casos a adoção de padrões de projeto pode ser inapropriada. Esse
trabalho monográfico relata a origem e os fundamentos dos padrões de projeto, e busca
evidenciar a importância da aplicação de padrões para obter a excelência e a qualidade
desejadas para os sistemas de software. Através de uma pesquisa bibliográfica esse trabalho
evidenciou que a aplicação de padrões de projeto na fase de desenvolvimento do software é
um recurso positivo nos processos futuros de manutenção. Fatores como reusabilidade,
modularidade, uso de interfaces, composição de objetos, baixo acoplamento e alta coesão são
diretamente manipulados através dos padrões de projeto e consequentemente promovem
melhorias na manutenabilidade. Apesar dos benefícios proporcionados, os padrões de projeto
também podem ter efeitos negativos sobre os sistemas de software.
Palavras-chave: Engenharia de software. Padrões de projeto. Manutenabilidade.
ABSTRACT
The software development community has been increasingly adopting the concepts of design
patterns in the process of software development. Studies report evidences that these patterns
cause a positive impact on software quality, but in some cases the adoption of design patterns
may be inappropriate. This monographic work describes the origin and fundamentals of
design patterns and seeks to evidence the importance of applying patterns to obtain the
excellence and quality desired for software systems. Through a bibliographic research this
work suggested that the use of design patterns during software development is a positive
factor in future maintenance processes. Factors such as reusability, modularity, use of
interfaces, object composition, loose coupling and high cohesion are directly manipulated
through the design patterns and they consequently promote enhancements in the
maintainability. Despite the benefits provided, design patterns can also have negative effects
on the software systems.
Keywords: Software engineering. Design patterns. Maintainability.
SUMÁRIO
1 PADRÕES DE PROJETO .................................................................................................. 10
1.1 Origem ........................................................................................................................... 10
1.2 Fundamentos ................................................................................................................. 11
1.3 Benefícios e limitações .................................................................................................. 13
2 PADRÕES DE PROJETO GOF ........................................................................................ 16
2.1 Classificação .................................................................................................................. 16
2.2 Padrões de criação ........................................................................................................ 18
2.2.1 Descrição e objetivos ............................................................................................. 19
2.2.2 Padrão Abstract Factory ........................................................................................ 20
2.3 Padrões estruturais ....................................................................................................... 23
2.3.1 Descrição e objetivos ............................................................................................. 23
2.3.2 Padrão Adapter ....................................................................................................... 25
2.4 Padrões comportamentais ............................................................................................ 26
2.4.1 Descrição e objetivos ............................................................................................. 27
2.4.2 Padrão Strategy ...................................................................................................... 30
3 PADRÕES DE PROJETO PARA A MELHORIA DA MANUTENABILIDADE ....... 34
3.1 Manutenção de software .............................................................................................. 34
3.2 Manutenabilidade ......................................................................................................... 35
3.3 Modularidade ................................................................................................................ 38
3.3.1 Acoplamento .......................................................................................................... 39
3.3.2 Coesão ..................................................................................................................... 39
3.4 Reusabilidade ................................................................................................................ 40
3.5 Uso de interfaces ........................................................................................................... 41
3.6 Limitações...................................................................................................................... 42
CONCLUSÃO ......................................................................................................................... 43
REFERÊNCIAS ..................................................................................................................... 45
8
INTRODUÇÃO
O princípio da aplicação de padrões de projeto foi relatado em Alexander (1979),
onde teve início a documentação de padrões aplicados a projetos arquitetônicos. Ao adaptar o
conceito de padrões de projeto ao desenvolvimento de software orientado a objetos, Gamma
et al. (1995) publicou o primeiro catálogo de padrões de projeto de software, que é
considerado hoje uma referência para a compreensão do conceito de padrões de projeto
aplicados ao desenvolvimento de software.
Padrões de projeto de software são soluções para problemas específicos em um
determinado contexto, onde uma solução resolve um problema de modo que se possa
reutilizar essa mesma solução milhares de vezes sem necessariamente seguir os mesmos
passos (GAMMA et al., 2000). As soluções propostas por esses padrões geralmente são
respostas a problemas que tendem a se repetir na construção de todos os softwares para esse
mesmo domínio do problema (MAGELA, 2006).
A aplicação de padrões de projeto de software busca melhorar a legibilidade e a
facilidade de entendimento do software, sendo considerado como parte integrante da
documentação do projeto (GAMMA et al., 2000). A partir da aplicação de padrões de projeto
é possível promover reusabilidade, modularidade e manutenabilidade do software, pois os
padrões fornecem soluções mais completas e melhor estruturadas do que uma solução simples
para resolver determinado problema. Entretanto, pode-se adicionar complexidade
desnecessária no software usando uma solução proposta por padrões (VOKAC et al., 2004).
Os padrões de projeto representam um avanço na área de engenharia de software, pois
oferecem estruturas para a reutilização de soluções de projeto que já foram testadas e
aprovadas por profissionais experientes. Cada padrão fornece uma solução abstrata para um
problema, permitindo assim desenvolver um projeto em uma notação de mais alto nível
(THOMAZINI NETO, 2006).
A indústria de desenvolvimento de software necessita cada vez mais de recursos de
engenharia de software para tornar os processos de desenvolvimento e manutenção mais
ágeis, no entanto, existem dificuldades em projetar software orientado a objetos de modo que
sejam estabelecidas condições que promovam flexibilidade suficiente para lidar com o
processo de desenvolvimento e manutenção do software (SHALLOWAY; TROTT, 2004).
Neste contexto os padrões de projeto tem grande influência na manutenabilidade de software,
pois eles elevam o nível de facilidade com que o software pode ser modificado (GAMMA et
al., 2000). A manutenção de software é um processo realizado frequentemente, e pode gerar
9
altos custos, tanto pelo custo direto da manutenção quanto pelo custo da indisponibilidade do
sistema (XIONG; XIE; NG, 2011).
Esta pesquisa tem como objetivo relatar a origem dos padrões de projeto de software,
seus fundamentos e definições, como eles se aplicam ao desenvolvimento de software, e
apontar as vantagens e limitações da sua utilização no processo de manutenção de software. O
capítulo 1 relata o histórico, os fundamentos e os conceitos teóricos sobre padrões de projeto.
O capítulo 2 descreve os padrões de projeto GOF (Gang of four – termo utilizado na
engenharia de software para fazer referência à publicação do primeiro catálogo de padrões de
projeto de software). E o capítulo 3 busca apontar as vantagens e limitações da aplicação de
padrões de projeto para a melhoria da manutenabilidade de software.
10
CAPÍTULO I
1 PADRÕES DE PROJETO
Os padrões de projeto de software foram adotados pela engenharia de software a
partir da década de 90. No fundamento destes padrões está a descrição de soluções para
problemas recorrentes no desenvolvimento de software orientado a objetos. Este capítulo
contextualiza os padrões de projeto de software, a seção 1.1 relata os princípios que deram
origem aos padrões de projeto, a seção 1.2 descreve os seus fundamentos e a seção 1.3 faz
uma abordagem sobre os benefícios e as limitações dos padrões de projeto.
1.1 Origem
O termo padrões de projeto é conhecido inicialmente pelo seu uso em projetos
arquitetônicos. Esse novo conceito foi criado na década de 70, a partir dos trabalhos de
Christopher Alexander, um arquiteto urbano e urbanista que associou o termo padrão às
repetições de formas em arquitetura.
Alexander (1979) publicou um catálogo com 253 padrões aplicados a projetos
arquitetônicos, o qual passou a ser utilizado como uma alternativa aos métodos tradicionais
empregados pela arquitetura. Nessa publicação houve o questionamento sobre a existência de
uma base objetiva para qualificar determinado projeto como sendo bom ou ruim. Essa base
objetiva surgiu a partir da análise de projetos arquitetônicos e da afirmação de que seria
possível qualificar projetos de arquitetura não apenas como uma questão de gosto, mas a
partir de uma base objetiva e mensurável.
Sob a ótica de padrões, Alexander (1979) passou a analisar os projetos de cidades,
ruas, entre outros aspectos que envolviam conceitos arquitetônicos, e descobriu que as boas
construções tinham algo em comum. Ao analisar dois projetos arquitetônicos que tivessem
sido elaborados de maneira distinta, observou-se que eles poderiam ser similares na tentativa
de resolver o mesmo problema. Esse foi o conceito que se tornou a base inicial para o
processo de identificação de padrões que persistiam em projetos de boa qualidade.
Passando de padrões de projetos de arquitetura para padrões de projeto de software,
observa-se os trabalhos de Pree (1995) e Gamma et al. (1995), os quais observaram os
conceitos sobre padrões de projeto e notaram que as soluções e os propósitos apresentados
pelos padrões voltados para projetos arquitetônicos poderiam ser aplicados a projetos de
11
software orientado a objetos, pois visavam à flexibilidade e a reutilização de componentes, os
quais poderiam ser aplicados em sistemas de software.
Gamma et al. (1995) publicaram as suas primeiras experiências sobre padrões de
projeto de software em um livro intitulado Design Patterns: Elements of reusable object
oriented software. Essa publicação, constituída por 23 padrões, também ficou conhecida
como catálogo GOF. Esta obra é considerada hoje a base fundamental para a compreensão do
conceito de padrões de projetos de software. A obra em questão aplicou a ideia de padrões a
projetos de software, descrevendo os fundamentos e uma estrutura para catalogar os padrões
de projeto.
Shalloway e Trott (2004) cita o trabalho de Pree (1995) e Gamma et al. (1995) como
as publicações que tiveram uma grande influência na formação de uma comunidade de
estudiosos sobre padrões de projeto. Ambas as publicações foram bem aceitas na área de
desenvolvimento de software, e amplamente utilizadas tanto no campo acadêmico quanto
empresarial.
1.2 Fundamentos
Gamma et al. (2000) define padrões de projeto como soluções para problemas
específicos em um determinado contexto, onde cada solução resolve um problema de modo
que se possa utilizar essa solução milhares de vezes sem necessariamente seguir o mesmo
caminho.
Um padrão de projeto nomeia, abstrai e identifica os aspectos-chave de uma
estrutura de projeto comum para torná-la útil para a criação de um projeto
orientado a objetos reutilizável. O padrão de projeto identifica as classes e
instâncias participantes, seus papéis, colaborações e a distribuição de
responsabilidades. Cada padrão de projeto focaliza um problema ou tópico
particular de projeto orientado a objetos. Ele descreve em que situação pode
ser aplicado, se ele pode ser aplicado em função de outras restrições de
projeto e as consequências, custos e benefícios de sua utilização. (GAMMA
et al., 2000, p. 19).
Gamma et al. (2000) descrevem alguns elementos que são essenciais para que um
padrão possa ser compreendido e utilizado em projetos de software. Nessa definição, cada
padrão deve ser caracterizado a partir de quatro elementos básicos: nome, problema, solução e
consequências.
12
O nome do padrão é uma referência que podemos usar para descrever um
problema de projeto, suas soluções e consequências em uma ou duas
palavras. Dar nome a um padrão aumenta imediatamente o nosso
vocabulário de projeto. Isso nos permite projetar em um nível mais alto de
abstração [...]
O problema mostra em que situação aplicar o padrão. Ele explica o
problema e seu contexto. Pode descrever problemas de projeto específicos,
tais como representar algoritmos como objetos. Pode descrever estruturas de
classe ou objeto sintomáticas de um problema inflexível. Algumas vezes o
problema incluirá uma lista de condições que devem ser satisfeitas para que
faça sentido aplicar o padrão.
A solução descreve os elementos que compõe o padrão de projeto, seus
relacionamentos, suas responsabilidades e colaborações. A solução não
descreve um projeto concreto ou uma implementação em particular porque
um padrão é um gabarito que pode ser aplicado em muitas situações
diferentes. Em vez disso o padrão fornece uma descrição abstrata de um
problema de projeto e de como um arranjo geral de elementos (classes e
objetos) o resolve.
As consequências são os resultados e análises das vantagens e desvantagens
(trade offs) da aplicação do padrão. Embora as consequências sejam
raramente mencionadas quando descrevemos decisões de projeto, elas são
críticas para a avaliação de alternativas de projetos e para a compreensão de
custos e benefícios da aplicação do padrão. (GAMMA et al., 2000, p. 19,
grifo do autor).
Fowler (2006) e Magela (2006) apresentam conceitos similares aos de Gamma et al.
(2000), ao definir padrões de projeto de software como sendo soluções usuais e específicas
para a resolução de um ou mais problemas que ocorrem com frequência no processo de
desenvolvimento de sistemas de software. De acordo com Magela (2006, p. 98) um padrão de
projeto representa “[...] a solução para um problema em um contexto específico que tende a se
repetir na construção de todos os softwares para esse mesmo domínio do problema [...]”.
Outra definição é apresentada por Arnout (2004), onde é relatado que:
Um padrão de projeto de software é um conjunto de ideias arquiteturais de
domínio independente. Tipicamente um padrão descreve as classes
envolvidas e a colaboração entre as suas instancias, definidas a partir de
sistemas do mundo real. Onde as pessoas podem aprender a aplicá-los em
projetos de software em resposta a um problema específico. (ARNOUT,
2004, p. 40, tradução nossa).
Na tentativa de definir uma base sólida a partir da qual os padrões de projeto são
identificados e se tornam úteis para as pessoas, Fowler (2006) descreve que os padrões de
projeto podem ser identificados através da observação de problemas que ocorrem na prática, e
que a descoberta e a definição de novos padrões estão relacionadas à experiência acerca de
determinado problema. Partindo desse princípio, pode-se afirmar que a descoberta de novos
13
padrões se da através da observação de projetos que funcionam e da busca pela essência da
sua solução, esse é um processo que exige grande capacidade de análise e experiência na
abordagem do problema.
Fowler (2006) e Freeman Erich e Freeman Elizabeth (2009) observaram que os
padrões de projeto podem ser úteis na comunicação entre os membros de uma equipe ou
grupo de trabalho, uma vez que os padrões permitem estabelecer um vocabulário
compartilhado na comunicação entre os membros da equipe. “Quando você se comunica
usando padrões, está fazendo mais do que apenas compartilhar um dialeto” (FREEMAN,
Erich; FREEMAN, Elizabeth, 2009, p. 45). Esse dialeto é a expressão de um conjunto de
características, benefícios e restrições que determinado padrão representa. A consequência da
adoção de padrões nessa relação de comunicação entre as pessoas possibilita uma
compreensão imediata e precisa do problema e das possíveis soluções que estão sendo
propostas para o problema.
1.3 Benefícios e limitações
A indústria de desenvolvimento de software tem evoluído na última década e vem
utilizando cada vez mais recursos de engenharia de software para tornar os processos de
desenvolvimento e manutenção de softwares mais ágeis. Em contrapartida a essa tendência
existe uma grande dificuldade em projetar software orientado a objetos que seja de fato
reutilizável e flexível o suficiente para lidar com as complexidades inerentes ao processo de
desenvolvimento e manutenção de software (SHALLOWAY; TROTT, 2004). Gamma et al.
(2000, p. 17, grifo do autor) relata que:
Projetar software orientado a objetos é difícil, mas projetar software
reutilizável orientado a objetos é ainda mais complicado. Você deve
identificar objetos pertinentes, fatorá-los em classes no nível correto de
granularidade, definir as interfaces das classes, as hierarquias de herança e
estabelecer as relações-chave entre eles. O seu projeto deve ser específico
para o problema a resolver, mas também genérico o suficiente para atender
problemas e requisitos futuros. Também deseja evitar o re-projeto, ou pelo
menos minimizá-lo. Os mais experientes projetistas de software orientado a
objetos lhe dirão que um projeto reutilizável e flexível é difícil, senão
impossível, de obter corretamente da primeira vez. Antes que um projeto
esteja terminado, eles normalmente tentam reutilizá-lo várias vezes,
modificando-o a cada vez.
Gamma et al. (2000) associa os padrões de projeto à experiência adquirida a partir de
projetos de software bem sucedidos. Em decorrência disso, os projetistas experientes tendem
14
a reutilizar soluções que já se mostraram eficientes em projetos anteriores. É justamente neste
ponto que os padrões de projeto atribuem vantagem àqueles que fazem uso de padrões para a
solução de diferentes problemas de projeto.
O desenvolvimento de software envolve uma considerável repetição de recursos, onde
determinadas aplicações podem compartilhar as mesmas necessidades. A ideia de reuso
remete à possibilidade de reutilizar elementos de software que possam ser aplicados em
qualquer projeto que necessite explicitamente dessa funcionalidade. Nesse contexto, os
padrões de projeto abstraem a questão do reuso, atribuindo a possibilidade da reutilização de
padrões Arnout (2004).
Dentre as razões pelos quais os padrões de projeto atribuem maior qualidade a projetos
de software, Arnout (2004) cita uma lista de benefícios que podem ser aplicados ao
desenvolvimento de software:
Cada padrão reúne uma fonte de conhecimento definida a partir da experiência em
projetos de software. Uma das consequências disso é que as pessoas sem
experiência em desenvolvimento de software podem se beneficiar disso,
adquirindo experiência mais rapidamente.
Os padrões contribuem para o desenvolvimento de software de maior qualidade a
partir da definição de uma estrutura que permita atribuir extensibilidade ao
software.
Os padrões definem uma linguagem comum para discussões de troca de
informações, tanto entre os próprios desenvolvedores quanto entre
desenvolvedores e gerentes de projeto.
Gamma et al. (2000) afirma que projetar sistemas de software de modo que sejam
estabelecidas condições reais de reutilização, extensibilidade e facilidade de manutenção é um
processo bastante complexo. Considerando o desenvolvimento de um projeto de software a
partir do início, é necessário encontrar os objetos corretos, definir interfaces, estabelecer a
hierarquia de herança correta entre as classes, entre outras coisas. Considerando ainda que o
projeto deva apresentar soluções não apenas para o problema em questão, mas também ser
abrangente o suficiente para tratar problemas que possam surgir futuramente, dificilmente
será definido a solução ideal para o problema. Gamma et al. (2000, p. 18) relata que:
Os padrões de projeto tornam mais fáceis reutilizar projetos e arquiteturas
bem-sucedidas. Expressar técnicas testadas e aprovadas as torna mais
acessíveis para os desenvolvedores de novos sistemas. Os padrões de projeto
15
ajudam a escolher alternativas de projeto que tornam um sistema reutilizável
e a evitar alternativas que comprometam a reutilização. Os padrões de
projeto podem melhorar a documentação e a manutenção de sistemas ao
fornecer uma especificação explícita de interações de classes e objetos e o
seu objetivo subjacente. Em suma, ajudam um projetista a obter mais
rapidamente um projeto adequado.
Uma das características relevantes dos padrões de projeto é justamente a capacidade
que eles têm de apresentar alternativas de reuso de arquiteturas que já foram projetadas,
testadas e se mostraram eficientes, assim, evitando alternativas que comprometam a eficiência
do sistema de software que está sendo projetado (GAMMA et al., 2000).
Para Shalloway e Trott (2004) os motivos pelo qual a utilização de padrões de
projeto se torna relevante consistem na sua capacidade de reutilizar soluções e de estabelecer
uma terminologia comum. A reutilização de soluções se refere ao fato de reutilizar conceitos a
partir da experiência de projetos já estabelecidos, sem ter que reinventar soluções para os
mesmos problemas. Já a definição de uma terminologia comum permite estabelecer uma base
comum para a comunicação entre os membros de um projeto durante a sua fase de análise e
desenvolvimento.
A comunicação e o trabalho em equipe requerem uma base de vocabulário e
um ponto de vista comum do problema. Os padrões de projeto fornecem um
ponto comum de referência durante a fase de análise e elaboração de um
projeto. (SHALLOWAY; TROTT, 2004, p. 99).
Shalloway e Trott (2004) complementa afirmando que os padrões de projeto também
atribuem maior facilidade de modificação em sistemas de software.
A maioria dos padrões de projeto torna o software mais passível de
modificação. A razão para tal é que eles são soluções comprovadas pelo
tempo, portanto, evoluíram em estruturas que podem tratar mudanças mais
prontamente do que as que, muitas vezes, vêm primeiro a mente como uma
solução. (SHALLOWAY; TROTT, 2004, p. 99).
Arnout (2004) questiona a posição de Gamma et al. (2000) em relação à reutilização
de soluções proposta por padrões de projeto. Arnout (2004) questiona que a definição de uma
solução utilizando padrões deve ser adaptada para cada novo contexto, o que significa que o
uso de padrões de projeto não proporciona reusabilidade em termos de código, pois ele
precisa ser adaptado a cada novo problema em particular.
16
CAPÍTULO II
2 PADRÕES DE PROJETO GOF
Este capítulo faz uma abordagem teórica sobre os padrões de projeto GOF. A seção
2.1 descreve os critérios de classificação dos padrões de projeto GOF. As seções seguintes
descrevem os padrões de acordo com as suas finalidades: a seção 2.2 descreve os padrões de
criação, a seção 2.3 descreve os padrões estruturais e a seção 2.4 descreve os padrões
comportamentais.
2.1 Classificação
Gamma et al. (2000) classifica os padrões de projeto a partir dos critérios de
finalidade e escopo. A finalidade define o que o padrão faz, um padrão pode ter finalidade de
criação, estrutural ou comportamental. O escopo direciona o padrão a relacionamentos entre
classes ou objetos. Os padrões direcionados a classes lidam com os relacionamentos entre
classes e suas subclasses através do mecanismo da herança, abordando o problema no nível
das classes e definindo soluções em tempo de compilação. Já os padrões direcionados a
objetos lidam com os relacionamentos entre objetos, que podem ser definidos em tempo de
execução através dos recursos de polimorfismo e da composição de objetos.
O método de classificação de padrões apresentado em Gamma et al. (2000) são
fundamentais para a compreensão dos inúmeros padrões de projeto existentes, além de
auxiliar na curva de aprendizagem e na descoberta de novos padrões. O Quadro 1 apresenta os
padrões de projeto de acordo com as suas classificações.
17
Quadro 1 – Classificação dos padrões de projeto
Finalidade
De criação Estrutural Comportamental
Escopo
Classe Factory Method Adapter (class) Interpreter
Template Method
Objeto
Abstract Factory
Builder
Prototype
Singleton
Adapter (object)
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Chain of Responsability
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor
Fonte: Adaptado de Gamma et al. (2000, p. 26)
Em relação ao escopo o Quadro 1 mostra dois conjuntos de padrões, um direcionado
a classe e outro direcionado a objeto. Em relação à finalidade (propósito), existem três
conjuntos de padrões com diferentes finalidades: de criação, estrutural e comportamental.
Os padrões de criação no escopo de classe delegam o processo de criação de objetos
para as subclasses, enquanto que os de escopo de objeto postergam esse processo para outros
objetos. Os padrões estruturais no escopo de classe utilizam a herança para compor classes,
enquanto que os de escopo de objeto descrevem estruturas para relacionar objetos. E os
padrões comportamentais no escopo de classe utilizam a herança para descrever algoritmos e
fluxos de controle, enquanto que aqueles voltados para objetos descrevem como um grupo de
objetos se relaciona e compartilha a execução de tarefas (GAMMA et al., 2000).
A Figura 1 ilustra graficamente as relações entre os padrões de projeto de acordo
com o modo que os padrões mencionam seus inter-relacionamentos.
18
Figura 1 – Relacionamento entre os padrões de projeto
Fonte: Gamma et al. (2000, p. 26)
2.2 Padrões de criação
Conforme exposto na seção 2.1, os padrões de projeto podem ser classificados de
acordo com a sua finalidade e escopo. Gamma et al. (2000) descreve que os padrões de
criação têm por finalidade tornar o sistema independente de como os objetos são criados e
compostos, a partir da abstração do processo de instanciação dos objetos. Os padrões de
criação com escopo de classe utilizam a herança para definir as classes que são instanciadas,
enquanto que os padrões de criação com escopo de objeto utilizam fortemente a composição
para delegar o processo de criação de objetos (GAMMA et al., 2000).
19
Sistemas de software se tornam complexos a medida que evoluem, e necessitam de
mecanismos que forneçam flexibilidade para gerir as modificações no processo de
manutenção. Os padrões de criação contribuem no sentido de promover a composição de
objetos e não apenas o uso da herança (GAMMA et al., 2000).
Os padrões de criação se tornam importantes à medida que os sistemas
evoluem no sentido de depender mais da composição de objetos do que da
herança de classes. Quando isso acontece, a ênfase se desloca da codificação
rígida de um conjunto fixo de comportamentos para a definição de um
conjunto menor de comportamentos fundamentais, os quais podem ser
compostos em qualquer número para definir comportamentos mais
complexos. Assim, criar objetos com comportamentos particulares exige
mais do que simplesmente instanciar uma classe. (GAMMA et al., 2000, p.
91).
Nesse contexto, o sistema passa a conhecer os seus objetos a partir de classes
abstratas e não apenas por classes concretas. Consequentemente, os padrões de criação
atribuem flexibilidade e permitem que o sistema seja definido através de objetos que variam
amplamente em estrutura e funcionalidade.
Os padrões de criação com escopo de objeto são Singleton, Prototype, Builder e
Abstract Factory. Em relação ao escopo de classe existe um único padrão, o Factory Method
(GAMMA et al., 2000). Para um melhor entendimento da classificação por criação, o padrão
Abstract Factory será relatado de forma detalhada mais adiante.
2.2.1 Descrição e objetivos
O padrão Singleton estabelece uma maneira de garantir que uma classe tenha
somente uma instância a partir da definição de um único ponto de acesso a classe. De acordo
com Gamma et al. (2000) o Singleton é útil quando há necessidade de apenas uma instância
de uma classe e essa instância tiver que dar acesso aos clientes através de um único ponto, ou
quando essa instância tiver que ser extensível através de subclasses, possibilitando aos
clientes usar uma instância estendida sem alterar o seu código.
O padrão Prototype, segundo Gamma et al. (2000), objetiva a redução do número de
classes e a especificação dos tipos de objetos a serem criados usando uma instância protótipo,
onde novos objetos podem ser criados a partir de cópias desse protótipo. O Prototype pode ser
aplicado quando as instâncias de uma classe puderem ter poucas combinações diferentes de
estados.
20
O padrão Builder é descrito por Gamma et al. (2000) como um recurso para separar a
construção de um objeto complexo da sua representação, de modo que o mesmo processo de
construção possa criar diferentes representações. O padrão pode ser adotado sempre que a
lógica para a criação de um objeto complexo for independente das partes que compõem o
objeto. O processo de construção deve permitir diferentes representações para o objeto que é
construído.
2.2.2 Padrão Abstract Factory
O padrão Abstract Factory é responsável por fornecer uma interface para criação de
famílias de objetos que se relacionam ou dependem um do outro sem a necessidade de
especificar suas classes concretas (FREEMAN, Erich; FREEMAN, Elizabeth, 2009).
A família de objetos criada a partir do padrão Abstract Factory é definida por
Gamma et al. (2000) como uma família de objetos-produto, que é um conjunto de objetos que
de algum modo se relacionam para atingir um determinado objetivo. O padrão Abstract
Factory define justamente um tipo abstrato para criar uma família de produtos relacionados.
Na definição de Gamma et al. (2000), produtos são objetos concretos que atingem um
objetivo específico do sistema, definidos por subclasses de um tipo abstrato.
O padrão Abstract Factory ajuda a controlar as classes de objetos criadas por
uma aplicação. Uma vez que a fábrica encapsula a responsabilidade e o
processo de criar objetos-produto, isola os clientes das classes de
implementação. Os clientes manipulam as instâncias através das suas
interfaces abstratas. Nomes de classes-produto ficam isolados na
implementação da fábrica concreta. (GAMMA et al., 2000, p. 98).
A vantagem do padrão Abstract Factory é que ele permite definir uma regra de
negócio ao mesmo tempo em que promove baixo acoplamento, tornando o sistema pouco
dependente das implementações concretas. Gamma et al. (2000) recomenda o uso do padrão
Abstract Factory sempre que for identificado alguma das características a seguir:
Houver independência de como os produtos de um sistema são criados.
O sistema tiver de ser configurado como um produto de uma família de múltiplos
produtos.
21
Uma família de objetos for projetada para ser usada em conjunto, e houver a
necessidade de garantir esta restrição;
Um ponto-chave do padrão Abstract Factory consiste em estabelecer condições para
definir um conjunto de classes de produtos de modo que somente suas interfaces sejam
responsáveis pelo controle dos recursos, e não suas implementações concretas (GAMMA et
al., 2000). A Figura 2 exemplifica a aplicação do padrão Abstract Factory.
Figura 2 – padrão Abstract Factory
Fonte: Gamma et al. (2000, p. 96)
O diagrama da Figura 2 mostra o conceito geral do padrão Abstract Factory. A partir
da análise desse diagrama é possível compreender a aplicabilidade do padrão. Como pode ser
observado no diagrama, são definidos grupos de famílias de classes que implementam a
mesma interface. Gamma et al. (2000) define uma família de classes quando há um conjunto
de classes concretas que herdam características de uma mesma classe abstrata.
Gamma et al. (2000) relata que a classe AbstractFactory atua como uma fábrica
abstrata que contém apenas as assinaturas dos métodos que instanciam fábricas concretas.
Cada fábrica concreta é responsável por definir um conjunto específico de recursos do
sistema, ela reúne um conjunto de produtos que devem fazer parte do sistema em um
determinado contexto. Uma fábrica abstrata permite implementar uma ou várias fábricas
concretas, onde cada qual define o uso de um conjunto de produtos para contextos diferentes.
Com isso, a possibilidade de definir uma nova regra ou criar uma nova funcionalidade se
torna um processo bem definido.
Uma fábrica abstrata nos da uma interface para criar uma família de
produtos. Ao escrever o código que usa essa interface, desvinculamos nosso
22
código da fábrica real que cria os produtos. Isso nos permite implementar
uma variedade de fábricas que fazem produtos para contextos diferentes –
como regiões diferentes, sistemas operacionais diferentes ou aparências
diferentes. Como nosso código é desvinculado dos produtos reais, podemos
substituir fabricas diferentes para obter comportamentos diferentes.
(FREEMAN, Erich; FREEMAN, Elizabeth, 2009, p. 135).
O papel das fábricas concretas é justamente definir regras de negócio. O diagrama da
Figura 2 mostra duas fábricas concretas, ConcreteFactory1 e ConcreteFactory2, que definem
regras a partir da seleção de um conjunto de produtos, que juntos atendem a um propósito
específico do sistema. No entanto, no nível das fábricas concretas o sistema trata das
colaborações entre classes ainda de modo abstrato, pois as fábricas concretas apenas definem
a criação de um conjunto de produtos que visam atender a um objetivo ou regra de negócio.
Uma vez que o código fica desvinculado dos produtos concretos, pode-se criar ou modificar
fábricas para obter comportamentos diferentes (GAMMA et al., 2000).
Fábricas concretas apenas cuidam da instanciação de objetos-produto, o processo de
criação de produtos concretos fica a cargo das classes de produtos, as quais podem partir
desde níveis concretos a níveis abstratos, onde através da herança criam-se classes de
produtos concretos. No diagrama da Figura 2, as classes AbstractProductA e
AbstractProductB cuidam da implementação de produtos concretos. Segundo Gamma et al.
(2000) definir classes que atuam como produtos permite codificar regras de negócio
específicas, e isso facilita a reutilização das funcionalidades do produto, sendo que os
produtos são compostos em fábricas concretas a medida que a aplicação exige os recursos do
produto.
Do diagrama da Figura 2 a classe Client são os objetos que interagem com alguma
fábrica abstrata. Os clientes apenas necessitam saber qual tipo de abstração estão usando, pois
as subclasses do tipo abstrato tratam das implementações concretas, mantendo os clientes
vinculados apenas aos tipos abstratos. As fábricas concretas têm conhecimento apenas dos
produtos instanciados por elas e as instancias da classe Client não podem fazer referências
diretas para os produtos ou fábricas concretas, há apenas a possibilidade de manter referências
para a fábrica abstrata. A vantagem desse recurso é que novas fábricas ou produtos podem ser
definidos sem qualquer impacto no objeto cliente. Isso torna a codificação flexível e garante
coesão e acoplamento (GAMMA et al., 2000).
Apesar das vantagens do padrão Abstract Factory, existem algumas desvantagens na
sua utilização. Segundo Gamma et al. (2000) o padrão dificulta o suporte a novos tipos de
23
produtos em consequência da complexidade de extensão de fábricas abstratas e criação de
novos tipos de produtos.
Estender fábricas abstratas para produzir novos tipos de Produtos não é fácil.
Isso se deve ao fato de que a interface de AbstractFactory fixa o conjunto de
produtos que podem ser criados. Suportar novos tipos de produto exige
estender a interface da fábrica, o que envolve mudar a classe
AbstractFactory e todas as suas subclasses. (GAMMA et al., 2000, p. 98).
No relato de Gamma et al. (2000) a interface da fábrica abstrata fixa um conjunto de
produtos que podem ser criados, em consequência disso o suporte a novos tipos de produto
exige que a interface da fábrica abstrata seja estendida.
2.3 Padrões estruturais
De acordo com Gamma et al. (2000) os padrões de projeto estruturais tem a função
de definir o modo como classes e objetos são compostos para formar estruturas maiores. No
escopo de classe os padrões estruturais utilizam a herança para compor interfaces. Enquanto
que no escopo de objeto os padrões descrevem estratégias para compor objetos em tempo de
execução. Os padrões estruturais atribuem flexibilidade ao sistema, obtida principalmente
pela sua capacidade de compor objetos em tempo de execução.
Os padrões de projeto classificados como estruturais são: Adapter, Bridge,
Composite, Decorator, Facade, Flyweight e Proxy (GAMMA et al., 2000). O padrão Adapter
será explicado de forma detalhada para demonstrar a aplicabilidade dos padrões classificados
como estruturais.
2.3.1 Descrição e objetivos
Os padrões de projeto estruturais têm por objetivo descrever métodos de organização
de classes e objetos, atribuindo ao sistema maior flexibilidade de adaptação a mudanças e
operações de manutenção (GAMMA et al., 2000).
O padrão Bridge permite realizar abstrações em objetos, de modo que o objeto se
torne independente da sua implementação concreta, e permite que o objeto possa variar
independente da sua implementação. Uma abstração pode ser realizada através do uso da
herança, onde uma classe abstrata define uma interface para abstrair classes em uma
24
hierarquia, e as subclasses concretas as implementam de maneiras diferentes (GAMMA et al.,
2000).
O padrão Composite é outro exemplo de um padrão estrutural. Segundo Gamma et
al. (2000), o padrão descreve como construir hierarquias de classes em estruturas de árvores,
esse mecanismo permite definir objetos simples e compostos para criar hierarquias
arbitrariamente complexas. Desse modo, o padrão é aplicado para representar hierarquias de
objetos clientes que necessitam tratar um conjunto de objetos em estruturas compostas e de
modo uniforme. Isso permite que os objetos clientes sejam capazes de ignorar a diferença
entre objetos individuais e a composição de um conjunto de objetos.
Segundo Gamma et al. (2000) O padrão Decorator visa atribuir responsabilidades
adicionais a um objeto em tempo de execução ao fornecer alternativas para extensões de
funcionalidades.
[...] Os Decorators fornecem uma alternativa flexível ao uso de subclasses
para extensão de funcionalidades [...] Algumas vezes queremos acrescentar
responsabilidades a objetos individuais, e não a toda uma classe. Por
exemplo, um toolkit para construção de interfaces gráficas de usuário deveria
permitir a adição de propriedades, como bordas, ou comportamentos, como
rolamento, para qualquer componente da interface do usuário. (GAMMA et
al., 2000, p. 170).
O padrão Facade (fachada) tem por objetivo fornecer uma interface única para os
recursos de um subsistema, abstraindo o acesso aos recursos internos do subsistema. Ao
aplicar o padrão define-se uma interface de alto nível que torna o subsistema mais fácil de ser
utilizado (GAMMA et al., 2000).
Estruturar um sistema em subsistemas ajuda a reduzir a complexidade. Um
objetivo comum de todos os projetos é minimizar a comunicação e as
dependências entre subsistemas. Uma maneira de atingir esse objetivo é
introduzir um objeto facade (fachada), o qual fornece uma interface única e
simplificada para os recursos e facilidades mais gerais de um subsistema.
(GAMMA et al., 2000, p. 170, grifo do autor).
O padrão Flyweight, como o próprio nome sugere, tem por objetivo fornecer uma
estrutura para o compartilhamento de objetos leves e que geralmente se encontram em grande
número em uma aplicação (GAMMA et al., 2000).
O padrão Proxy, segundo Gamma et al. (2000), fornece um objeto substituto
responsável por registrar a localização de outro objeto de modo que o acesso a este outro
25
objeto possa ser controlado. Proxy pode ser aplicado sempre que há necessidade de uma
referência mais variável do que um simples apontador para um objeto. O padrão Proxy
também pode ser adaptado para incluir o padrão Flyweight em situações onde várias cópias de
um objeto complexo devem existir.
2.3.2 Padrão Adapter
De acordo com Gamma et al. (2000) o padrão Adapter permite que classes com
interfaces incompatíveis possam atuar em conjunto através de uma interface única, que
permite a um objeto utilizar os serviços de outros objetos com interfaces diferentes. O padrão
fornece um adaptador que realiza a comunicação, proporcionando ao sistema um mecanismo
de adaptação a mudanças.
[...] Em geral, um Adapter faz com que uma interface adaptada (em inglês,
adaptee) seja compatível com outra, dessa forma fornecendo uma abstração
uniforme de diferentes interfaces. A classe adaptadora (adapter) atinge esse
objetivo herdando, privadamente, de uma classe adaptada. O adapter, então,
exprime sua interface em termos da interface da classe adaptada. (GAMMA
et al., 2000, p. 139).
Gamma et al. (2000) subdivide o padrão Adapter em adaptadores de objeto e
adaptadores de classe. Basicamente, um adaptador de objeto utiliza a composição de objetos
para situações em que o adaptador contenha dois ou mais objetos que necessitam ser
adaptados para implementar uma interface alvo, enquanto que um adaptador de classe usa o
recurso de herança múltipla para adaptar duas interfaces incompatíveis. As Figuras 3 e 4
mostram os diagramas que representam adaptadores de classe e de objeto.
Figura 3 – Padrão Adapter para classes
Fonte: Gamma et al. (2000, p. 143)
26
Figura 4 – Padrão Adapter para objetos
Fonte: Gamma et al. (2000, p. 143)
Ao observar as Figuras 3 e 4 é possível notar que ambos os adaptadores, de classe e
de objeto, tem um princípio em comum, realizar o acoplamento da classe Target (alvo),
chamada pelo cliente, à classe Adaptee (adaptada). Isso implica que o cliente não sofrerá
alterações a medida que necessita se relacionar com a classe Target. Supondo que a interface
Adaptee realize algo que o cliente deseja, porém Target e Adaptee sejam interfaces
incompatíveis, a classe Adapter realiza essa comunicação (GAMMA et al., 2000).
A medida que o sistema se torna complexo e o nível de interação entre as classes
cresce, os adaptadores de classe e de objeto assumem características diferentes. Os
adaptadores de classe fazem uso de classes concretas para adaptar duas classes incompatíveis,
onde Adapter é geralmente uma subclasse da classe adaptada, denominada Adaptee. Um
adaptador de classe tem capacidade de substituir apenas os comportamentos da classe
adaptada e não funciona quando há necessidade de adaptar simultaneamente as suas
subclasses. Em contrapartida, os adaptadores de objeto permitem que uma única classe,
denominada Adapter, manipule várias classes simultaneamente, a classe adaptada,
denominada Adaptee, e todas as suas subclasses. A medida que o número de classes que
implementam a classe adaptada cresce, a capacidade do adaptador de objeto diminui, pois o
adaptador deve ter referências a todas as subclasses concretas da classe adaptada (GAMMA et
al., 2000).
2.4 Padrões comportamentais
De acordo com Gamma et al. (2000) os padrões de projeto comportamentais tem a
função de encapsular o comportamento de classes e objetos de modo que os seus níveis de
complexidade sejam minimizado. Os padrões comportamentais fornecem flexibilidade ao
27
sistema em função da sua capacidade de definir comportamentos a objetos em tempo de
execução. No escopo de classe, os padrões comportamentais descrevem estratégias de
relacionamentos entre classes e utilizam a herança para distribuir o comportamento entre os
objetos. No escopo de objeto os padrões descrevem estratégias para definir objetos que
necessitam de cooperação para a execução de tarefas que exigem a interação mútua de um
conjunto de objetos.
Os padrões comportamentais se preocupam com algoritmos e a atribuição de
responsabilidades entre objetos. Os padrões comportamentais não descrevem
apenas padrões de objetos ou classes, mas também os padrões de
comunicação entre eles. Esses padrões caracterizam fluxos de controle
difíceis de seguir em tempo de execução. Eles afastam o foco do fluxo de
controle para permitir que você se concentre somente na maneira como os
objetos são interconectados. (GAMMA et al., 2000, p. 139).
Os padrões de projeto classificados como comportamentais são: Interpreter,
Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento,
Observer, State, Strategy e Visitor (GAMMA et al., 2000).
2.4.1 Descrição e objetivos
O padrão Chain of Responsibility tem como objetivo definir regras de acoplamento
fraco entre objetos remetentes e receptores, fornecendo a vários objetos a oportunidade de
atender uma mesma solicitação. Seguindo esse princípio, determinada solicitação é passada ao
longo de uma cadeia de objetos até que um deles esteja apto a atender a solicitação. De acordo
com Gamma et al. (2000, p. 211-212) o padrão Chain of Responsibility permite:
[...] enviar solicitações implicitamente para um objeto através de uma cadeia
de objetos candidatos. Qualquer candidato pode satisfazer a solicitação
dependendo de condições em tempo de execução. O número de candidatos é
aberto e você pode selecionar quais candidatos participam da cadeia em
tempo de execução.
Chain of Responsibility pode ser aplicado quando há um conjunto de objetos aptos a
tratar uma solicitação, porém apenas um dentre estes objetos é o suficiente para tratar a
solicitação e este pode ser definido em tempo de execução. A medida que determinado objeto
emite uma solicitação sem especificar explicitamente o receptor, a solicitação se propaga ao
28
longo de uma cadeia até que determinado objeto assuma dinamicamente a responsabilidade
de atender a solicitação (GAMMA et al., 2000).
O padrão Command tem por objetivo encapsular solicitações como objetos,
permitindo que os objetos clientes sejam parametrizados com diferentes solicitações. Usos
conhecidos do padrão são as operações de copiar e desfazer presentes em um grande número
de aplicativos. Em resumo o padrão define uma estrutura de comandos para a implementação
de operações que podem ser desfeitas em tempo de execução (GAMMA et al., 2000).
O padrão Interpreter está associado à representação de gramáticas. De acordo com
Gamma et al. (2000) o padrão descreve metodologias para definir gramáticas para linguagens
simples, representar sentenças na linguagem e interpretar essas sentenças. Nesse contexto, o
padrão envolve a definição de uma gramática e a representação e interpretação de expressões
regulares da gramática. O padrão pode ser aplicado quando houver uma linguagem para
interpretar e sentenças dessa linguagem puderem ser representadas como árvores sintáticas
abstratas.
O padrão Iterator também conhecido como Cursor, fornece um método de acesso
aos elementos de um objeto de modo sequencial e sem expor a sua representação interna.
Gamma et al. (2000) relata o exemplo de um objeto que constitui uma lista, onde os
elementos da lista podem ser acessados a partir de diferentes critérios sem que a sua estrutura
interna seja exposta. A ideia principal do padrão é transferir a responsabilidade de acesso e
percurso de um conjunto de objeto para um objeto iterator, fornecendo uma interface que
percorra diferentes estruturas agregadas.
O padrão Mediator abstrair a interação entre um conjunto de objetos. De acordo com
Gamma et al. (2000, p. 257) o padrão Mediator tem como objetivo: “[...] definir um objeto
que encapsula a forma como um conjunto de objetos se interagem. O Mediator promove o
acoplamento fraco ao evitar que os objetos se refiram uns aos outros explicitamente e permite
variar suas interações independentemente.” O padrão pode ser aplicado quando a
comunicação entre um conjunto de objetos ocorre de modo complexo, onde as
interdependências resultantes são difíceis de compreender. A aplicabilidade do padrão
promove a reutilização de objetos que mantém uma comunicação com um número
arbitrariamente elevado de objetos, pois ele abstrai e estrutura essas relações de comunicação
entre os objetos.
29
Segundo Gamma et al. (2000) o padrão Memento registra o estado interno de um
objeto sem violar o encapsulamento, de modo que o objeto possa ser restaurado para esse
mesmo estado mais tarde. A aplicabilidade do padrão ocorre quando o estado interno de um
objeto necessita ser salvo em determinado momento na execução da aplicação, de modo que o
objeto possa recuperar o estado salvo posteriormente.
O padrão Observer define uma dependência de um para muitos entre objetos, onde
existe um objeto que possui informações de interesse para um conjunto de objetos
dependentes deste. Quando o objeto de interesse muda de estado, todos os seus dependentes
são notificados e atualizados automaticamente. O padrão pode ser aplicado quando um objeto
deseja notificar um conjunto indefinido de outros objetos, sem a necessidade de conhecer
quais são esses objetos. O tipo de interação disponibilizada pelo padrão Observer também é
conhecido como publish-subscribe, onde um objeto de interesse (subject) atua como um
publicador de notificações, enviando-as sem ter que saber quem são os objetos observadores
(GAMMA et al., 2000). O padrão Observer pode ser aplicado a medida que:
[...] uma abstração tem dois aspectos, um dependente do outro.
Encapsulando esses aspectos em objetos separados, permite-se variá-los e
reutilizá-los independentemente [...] Quando uma mudança em um objeto
exige mudanças em outros, e você não sabe quantos objetos necessitam ser
mudados [...] Quando um objeto deve ser capaz de notificar outros objetos
sem fazer hipóteses, ou usar informações, sobre quem são esses objetos. Em
outras palavras, você não quer que esses objetos sejam fortemente
acoplados. (GAMMA et al., 2000, p. 275).
O padrão State permite que um objeto altere seu comportamento quando o seu estado
interno muda. O padrão permite a introdução de uma classe abstrata que, por composição de
objetos, pode assumir diferentes comportamentos. Gamma et al. (2000, p. 285) recomenda o
padrão State nos seguintes casos:
O comportamento de um objeto depende do seu estado e ele pode mudar seu
comportamento em tempo de execução, dependendo desse estado [...] Esse
estado é normalmente representado por uma ou mais constantes enumeradas.
Frequentemente, várias operações conterão essa mesma estrutura
condicional. O padrão State coloca cada ramo do comando adicional em uma
classe separada. Isto lhe permite tratar o estado do objeto como um objeto
propriamente dito, que pode variar independentemente de outros objetos.
30
Segundo Gamma et al. (2000) o padrão Template Method define a estrutura de um
algoritmo em uma operação, permitindo que subclasses redefinam certos passos do algoritmo
sem mudar a sua estrutura. O conceito apresentado por este padrão torna-o aplicável na
implementação de partes de algoritmos que não variam durante a execução da aplicação. Ao
identificar as partes que não variam, o padrão delega para as subclasses a implementação do
comportamento que pode variar em tempo de execução.
O padrão Visitor tem por objetivo representar operações a serem executadas nos
elementos de uma estrutura de objetos, permitindo definir uma nova operação sem mudar as
classes dos elementos sobre os quais o objeto atua. O padrão permite que sejam adicionadas
novas funcionalidades a classe de um objeto sem a necessidade de modificação dessa classe
(GAMMA et al., 2000).
2.4.2 Padrão Strategy
O padrão Strategy permite definir uma família de algoritmos e encapsular cada
algoritmo como uma classe, permitindo que o algoritmo seja definido em tempo de execução
e que possa variar independentemente dos clientes que o utilizam (GAMMA et al., 2000).
A partir da definição de Gamma et al. (2000) nota-se que podem ser definidas
estratégias que permitem configurar uma classe capaz de adquirir um dentre muitos
comportamentos que a aplicação pode requerer em tempo de execução.
Figura 5 – Padrão Strategy
Fonte: Gamma et al. (2000, p. 294)
O diagrama exposto na Figura 5 define uma interface comum a todos os algoritmos
suportados. A interface denominada Strategy está apta a assumir o comportamento de uma
dentre varias classes ConcreteStrategy. Context representa genericamente um objeto em um
determinado contexto e usa a interface Strategy para chamar um dado algoritmo, definido por
31
uma das classes ConcreteStrategy. Na origem das colaborações estão os objetos clientes, que
passam um objeto ConcreteStrategy para o contexto. O contexto repassa as solicitações dos
objetos clientes para sua estratégia em resposta a requisição de cada cliente. Nota-se que os
objetos clientes interagem exclusivamente com o contexto, e para cada interface existe uma
família de classes ConcreteStrategy onde os objetos clientes decidem em tempo de execução o
algoritmo a ser executado (GAMMA et al., 2000).
Rocha (2011) aplicou o padrão Strategy para o desenvolvimento de rotinas de
geração de eventos aleatórios a partir de distribuições teóricas de probabilidade. A Figura 6
mostra o diagrama de classes envolvido na rotina.
Figura 6 – Diagrama de classes envolvido na geração de eventos aleatórios.
Fonte: Rocha (2011, p. 16)
No diagrama da Figura 6 tem-se que Entity é o contexto, ProbabilityDistribution é a
estratégia, e as classes concretas Exponential, Uniform e Constant constituem a família de
algoritmos possíveis de serem adotados pela estratégia. A interface
ProbabilityDistributionBehavior apenas define regras de comportamento às classes que a
implementam (ROCHA, 2011).
De acordo com Rocha (2011) essa é uma situação típica onde o padrão Strategy pode
ser aplicado, pois as classes concretas de geração de variáveis aleatórias formam uma família
32
de classes que compartilham um comportamento obrigatório, e são capazes de fornecer
variáveis aleatórias referentes a uma dada distribuição de probabilidade requisitada em tempo
de execução pelo objeto cliente.
A vantagem do padrão Strategy nesta situação é que uma nova distribuição teórica de
probabilidade pode ser facilmente adicionada ao projeto a partir da criação de uma nova
classe que estenda a classe abstrata ProbabilityDistribution e implemente a interface
ProbabilityDistributionBehavior (ROCHA, 2011).
Cassimiro (2010) utilizou o padrão Strategy para modelar um sistema chamado
TMTurismo, como mostra a Figura 7.
Figura 7 – Padrão Strategy para os pacotes turísticos.
Fonte: Cassimiro (2010, p. 38)
De acordo com Cassimiro (2010) o sistema TMTurismo deve ser flexível o suficiente
para o atendente modelar um pacote turístico de acordo com a preferência do cliente. Esse
33
fato implica que o cliente vai informar qual o destino quer ir, o tipo de passagem, a
hospedagem e as opções de veículo e passeios juntamente com atividades desejadas.
O padrão Strategy foi implementado com o intuito de proporcionar alterações nos
pacotes turísticos de forma organizada e planejada no código fonte, uma vez que se novos
pacotes forem criados ou novos comportamentos adicionados, é necessário apenas herdar da
classe abstrata PacoteTuristicoStrategy, no caso da criação de novos pacote, ou criar uma
interface com sua família de comportamento e adicionar a sua referência na classe
PacoteTuristicoStrategy.
34
CAPÍTULO III
3 PADRÕES DE PROJETO PARA A MELHORIA DA MANUTENABILIDADE
Os capítulos anteriores apresentaram os princípios e os fundamentos dos padrões de
projeto de software, com o objetivo de discutir neste capítulo as vantagens e as limitações da
aplicação desses padrões no processo de manutenção de software, visando a melhoria da
manutenabilidade.
3.1 Manutenção de software
Pressman (1995) e Sommerville (2003) definem manutenção de software como o
processo de modificação de um sistema após a sua conclusão. Esse processo de modificação
pode ser simples, destinado a corrigir erros de código, ou significativo, com a finalidade de
adicionar novos componentes ou realizar a reestruturação do software. IEEE - Institute of
Electrical and Electronics Engineers (1997) relata que as atividades de manutenção iniciam o
processo de modificação no ciclo de vida do software.
Pressman (1995) e Peters e Pedrycs (2001) categorizam a manutenção de software
em quatro grupos:
Manutenção adaptativa: modificação do software para mantê-lo utilizável após
mudanças no ambiente;
Manutenção corretiva: modificação do software para corrigir falhas descobertas após
a entrega;
Manutenção preventiva: modificação do software antes que ocorram falhas
operacionais;
Manutenção de aperfeiçoamento: modificação do software para aperfeiçoamento, em
função das mudanças da organização ou de regras de negócio.
O processo de manutenção de software é uma consequência dos procedimentos de
gestão da qualidade realizados na fase de desenvolvimento do projeto. Em função disso,
quanto menos definidos esses procedimentos, maiores os defeitos ou falhas que devem ser
removidos durante a operação do software (PAULA FILHO, 2003).
35
3.2 Manutenabilidade
IEEE (1990, p. 46, tradução nossa) define manutenabilidade de software como “[...] a
facilidade com que um sistema ou componente de software pode ser modificado para corrigir
falhas, melhorar o desempenho ou outros atributos, ou se adaptar a uma modificação do
ambiente”. Seguindo essa mesma orientação, Pressman (1995) descreve a manutenabilidade
como a facilidade com que um software pode ser corrigido, adaptado ou ampliado, caso haja a
necessidade de inclusão ou alteração nos requisitos funcionais.
Gamma et al. (2000) sustenta que os padrões de projeto tem grande influência na
manutenabilidade de software. Na medida em que influenciam diretamente em alguns fatores,
tais como limitação de dependências de plataforma, viabilização de estruturas em camadas,
facilidade de extensão, entre outros, os padrões de projetos elevam o nível de facilidade com
que um sistema de software pode ser modificado.
Os padrões de projeto também tornam uma aplicação mais fácil de ser
mantida quando são usados para limitar dependências de plataforma e
fornecer uma estrutura de camadas a um sistema. Eles melhoram a facilidade
de extensão ao mostrar como estender hierarquias de classes e explorar a
composição de objetos. (GAMMA et al., 2000, p. 41).
Prechelt et al. (2001) realizou um experimento com intuito de investigar a efetividade
do uso dos padrões Observer, Visitor, Decorator, Composite e AbstractFactory em processos
de manutenção de software. Participaram voluntariamente da experiência 29 profissionais da
área, os quais foram submetidos a testes de programação utilizando papel e caneta. Os
resultados da experiência mostraram efeitos positivos e negativos sobre os padrões analisados.
O padrão Observer teve efeito negativo sobre a manutenabilidade, o padrão Visitor se
manteve neutro, o padrão Decorator teve efeito positivo, e os padrões Composite e
AbstractFactory mostraram-se pouco significativos.
Jeanmart et al. (2009) realizou um estudo para avaliar o impacto do padrão Visitor
sobre a manutenabilidade de software. Os resultados do estudo mostraram que o padrão
Visitor tem um impacto positivo sobre a manutenabilidade de software, diferenciando dos
resultados obtidos por Prechelt et al. (2001), no qual o padrão se manteve neutro. No estudo
de Jeanmart et al. (2009), apesar do padrão Visitor ter influenciado pouco no esforço de
compreensão do software, a sua representação gráfica junto ao diagrama de classes reduziu
consideravelmente os esforços nas tarefas de modificação do software.
36
Prechelt et al. (2002) realizou um estudo para analisar a relevância da documentação
gerada a partir da aplicação de padrões de projeto, no sentido de facilitar mudanças no
processo de manutenção. Os parâmetros considerados no estudo foram o tempo gasto e a
eficiência esperada em cada tarefa de modificação do software. No software objeto do estudo
foram analisados os padrões Composite, Observer, Template Method, e Visitor, e os
resultados mostraram que, com o suporte de uma documentação explícita, as tarefas de
manutenção podem ser realizadas mais rapidamente e com menos falhas.
Nanthaamornphong e Carver (2011) replicaram o experimento realizado por Prechelt
et al. (2001), no qual foi realizado um estudo com foco no impacto que os padrões de projeto
têm sobre a manutenabilidade e a compreensão de software. Um novo parâmetro incluído
nesse experimento e que não foi considerado por Prechelt et al. (2001), foi a avaliação do
nível de compreensão do software. As tarefas de manutenção foram realizadas em duas
versões do mesmo software, uma com a presença de padrões, e outra elaborada somente a
partir de soluções alternativas aos padrões. Dados estatísticos do estudo indicaram que para as
tarefas de manutenção os padrões de projeto não contribuíram para a melhoria da
manutenabilidade e compreensão do software.
Ng et al. (2006) refizeram o software JHotDrow – um editor de desenho de código
fonte aberto – adicionando padrões de projeto em algumas funcionalidades do software. O
objetivo do trabalho foi realizar três tarefas de manutenção em funcionalidades similares ao
software original e ao software refeito. Dois grupos de pessoas participaram do experimento,
um formado por profissionais experientes na área e outro grupo ainda sem experiência prática.
Os resultados do experimento mostraram que o tempo gasto nas tarefas de manutenção
referente à versão do software refeito foi menor que o tempo gasto na versão original. Outro
fator interessante foi que, até mesmo o grupo de pessoas inexperientes, realizaram as tarefas
em um espaço de tempo relativamente inferior. Além disso, a solução proposta pelo grupo
inexperiente alcançou o mesmo nível de qualidade da solução proposta pelo grupo experiente.
[...] Uma vez que os padrões de projeto descritos apoiaram as modificações
necessárias no software, as pessoas que utilizaram a abordagem refeita
gastaram menos tempo ao analisar os códigos a serem modificados na tarefa
de manutenção [...] A parte interessante dos nossos resultados é que,
independentemente da experiência das pessoas, o fator tempo usando a
abordagem refeita foi acentuadamente menor do que a abordagem direta,
mesmo após incluir o tempo gasto no processo de redefinição do software.
(NG et al., 2006, p. 9, tradução nossa).
37
Ng et al. (2007) realizaram um estudo empírico para avaliar a relevância dos padrões
de projeto aplicados na fase de desenvolvimento do software e os reflexos sobre os processos
posteriores de manutenção. O objetivo do trabalho foi analisar a interação entre dois cenários:
a aplicação de padrões na fase de desenvolvimento do software e a utilização destes padrões
em tarefas futuras de modificação. Os resultados da pesquisa mostraram que os padrões de
projeto aplicados na fase de desenvolvimento do software foram efetivamente úteis no sentido
de prever mudanças futuras. Estatisticamente o estudo mostrou que há menos falhas de código
ao realizar tarefas de modificação a partir de padrões que tenham sido implementados na fase
de desenvolvimento do software.
Ng, Yu e Cheung (2010) relataram um estudo empírico onde foram investigados os
efeitos de cinco fatores humanos que podem influenciar na manutenabilidade do software:
exposição prévia dos profissionais aos padrões de projeto; exposição prévia ao software
utilizado no estudo; exposição prévia a linguagem de programação; experiência dos
profissionais; e soluções alternativas ao uso dos padrões. Foi selecionado para o estudo um
software em que já havia a presença de padrões de projeto em sua estrutura, e os resultados
mostraram que a exposição prévia ao programa foi o fator mais significativo em termos do
tempo gasto na manutenção, a exposição prévia aos padrões de projeto e à linguagem de
programação não foram significativos, e o uso de soluções alternativas aos padrões de projeto
foi inconclusivo no estudo.
Os resultados obtidos em Ng, Yu e Cheung (2010) foram reafirmados em Ng et al.
(2012). Além disso, este último estudo identificou um novo fator relevante para a
manutenabilidade do software, que consiste no fato de que os profissionais tendem a aplicar
soluções mais simples quando essa solução é mais fácil de ser aplicada que a solução proposta
por um padrão conhecido. Esse novo fator é descrito no estudo da seguinte maneira:
Uso inconsciente de padrões sugere que, se uma solução mais simples do
que a solução proposta por um padrão conhecido é identificada, o
profissional provavelmente escolherá a solução mais simples. A título de
orientação, os desenvolvedores não devem aplicar padrões de projeto para
apoiar modificações simplesmente porque determinado padrão é aplicável,
também é necessário considerar se há alternativas mais simples. (NG et al.,
2012, p. 26, tradução nossa).
Em resumo, o estudo concluiu que há três fatores estritamente correlacionados ao
tempo despendido na execução de tarefas de manutenção: os padrões de projeto existentes no
software; o conhecimento prévio do software; e o uso de soluções alternativas.
38
Vokac et al. (2004) replicaram o experimento realizado por Prechelt et al. (2001). Os
resultados do estudo mais recente se diferenciaram do estudo anterior em relação aos padrões
Observer e Visitor. Enquanto que a experiência original mostrou efeitos negativos em relação
ao padrão Observer, os resultados do estudo mais recentes mostraram dados estatísticos
favoráveis ao uso do padrão, uma vez que o padrão Observer se mostrou bastante
compreensivo e intuitivo até mesmo pelos profissionais com pouca experiência sobre o
padrão. Em contrapartida, enquanto que a experiência original apresentou efeitos positivos em
relação ao padrão Visitor, no estudo mais recente o padrão se mostrou significativamente
confuso e pouco compreensivo pelos profissionais. Os resultados do estudo indicaram ainda
que alguns padrões, tais como Observer e Decorator são relativamente mais fáceis de serem
compreendidos e utilizados do que outros.
Chatzigeorgiou, Tsantalis e Deligiannis (2008) realizou um estudo empírico para
avaliar a habilidade de um grupo de estudantes na compreensão de padrões de projeto. Os
estudantes tiveram que desenvolver duas versões de um mesmo software; uma versão
aplicando padrões de projeto e outra aplicando soluções alternativas. Os resultados indicaram
que a versão do software com a presença de padrões oferecia uma arquitetura bem elaborada,
uma vez que padrões foram aplicados corretamente. Em contrapartida, a versão do software
sem a presença de padrões apresentou uma arquitetura pobre e com falhas.
3.3 Modularidade
De acordo com IEEE (1990) modularidade é o grau com que um sistema ou
programa de computador é composto em componentes, de modo que uma mudança em um
componente tenha o mínimo de impacto em outros componentes. Shalloway e Trott (2004)
relata que a modularidade ajuda a tornar o código mais compreensível, e que essa capacidade
de compreensão, por sua vez, o torna mais fácil de manter.
A modularidade de software está fortemente relacionada ao conceito de acoplamento
e coesão. Esses dois conceitos de software são constantemente utilizados pelos padrões de
projeto e influenciam positivamente na modularidade do software (SHALLOWAY; TROTT,
2004).
39
3.3.1 Acoplamento
De acordo com IEEE (1990) acoplamento é a medida que define o grau de
interdependência entre dois módulos de software. Lino (2011) descreve este mesmo conceito
e relata que em sistemas que são estruturados em módulos, devem ser criadas interfaces bem
definidas para a comunicação entre os diversos módulos, reduzindo assim o impacto que a
modificação de um módulo possa causar no sistema.
Gamma et al. (2000), Shalloway e Trott (2004) e Lino (2011) consideram que esse
grau de dependência entre módulos deve ser fraco para promover a reusabilidade, e
descrevem que os padrões de projeto têm justamente esse objetivo, reduzir as dependências
para aumentar a reusabilidade interna do software.
Os padrões de projeto que reduzem dependências podem aumentar a
reusabilidade interna. O acoplamento mais fraco aumenta a probabilidade de
que uma classe de objetos possa cooperar com várias outras. Por exemplo,
quando você elimina dependências de operações específicas, pelo isolamento
e encapsulamento de cada operação, torna mais fácil a reutilização de uma
operação em contextos diferentes [...] (GAMMA et al., 2000, p. 41).
Gamma et al. (2000) observa ainda que o acoplamento reduzido também promove
portabilidade, facilidade de modificação e extensibilidade em sistemas de softwares. Os
padrões de projeto usam técnicas para reduzir o acoplamento e definir camadas para obter
sistemas com alto grau de modularidade.
São vários os padrões de projeto que promovem efetivamente o acoplamento entre
módulos ou componentes de software. Gamma et al. (2000) e Shalloway e Trott (2004)
descrevem quatro padrões que atuam no sentido de reduzir o acoplamento de sistemas de
software: Chain of Responsability, Facade, Mediator e Observer.
3.3.2 Coesão
De acordo com IEEE (1990) a coesão é a intensidade ou grau com que as tarefas
executadas por um módulo de software estão relacionadas. Shalloway e Trott (2004) e
Ferreira (2011) seguem esse mesmo conceito ao relacionar a coesão ao nível de comunicação
entre os elementos internos de um módulo. Lino (2011) afirma que a coesão permite que um
módulo ou classe dependa menos dos outros componentes, uma vez que a comunicação
interna de cada módulo é otimizada.
40
A quantidade de conexões entre os módulos de um sistema tende a ser menor a
medida que o nível de coesão interna de cada módulo aumenta. Isso resulta em um impacto
positivo no processo de modificação interna de determinado módulo, uma vez que as
consequências desse processo sobre os outros módulos do software são minimizadas
(FERREIRA; BIGONHA, M.; BIGONHA, R., 2008).
O nível de coesão de um módulo retrata o impacto que o processo de modificação de
um módulo causa sobre os outros módulos do software. Gamma et al. (2000) afirma que os
padrões de projeto buscam justamente elevar esse nível de coesão, pois a medida que o
módulo se torna coeso ele promove a modularidade e consequentemente contribui para a
manutenabilidade do software.
3.4 Reusabilidade
Freeman Erich e Freeman Elizabeth (2009) relata que os princípios de orientação a
objeto como herança, composição, polimorfismo, entre outros, devem estar associados aos
padrões de projeto para atribuir facilidade de reutilização em projetos de software. Os padrões
de projeto permitem aplicar esses princípios de orientação a objeto considerando um alto nível
de abstração para que se possa definir a melhor solução.
O desenvolvimento de software envolve uma considerável repetição de recursos,
onde determinadas aplicações podem compartilhar as mesmas funcionalidades. Arnout (2004)
relata que a concepção de reuso se refere à possibilidade de reaproveitar elementos de
software que possam ser utilizados em qualquer projeto que necessite explicitamente dessa
funcionalidade. Nesse contexto, os padrões de projeto abstraem o reuso de funcionalidades,
atribuindo a possibilidade de reutilização de soluções padronizadas.
Gamma et al. (2000) relata que a herança de classe e a composição de objetos são as
duas técnicas mais comuns para a reutilização de funcionalidades. Enquanto que a herança de
classe é definida em tempo de compilação e é dependente da implementação, a composição de
objetos é definida dinamicamente em tempo de execução e exige a obtenção de referências a
outros objetos. Assim, a herança e a composição atuam em conjunto e, em função disso,
promovem a reusabilidade interna do software e são aplicadas frequentemente aos padrões de
projeto.
41
3.5 Uso de interfaces
As interfaces são fundamentais em sistemas orientados a objeto. A definição de uma
interface consiste em reunir um conjunto de regras para as classes que a implementam. Isso
permite que os objetos sejam conhecidos somente através das suas interfaces, e o único modo
de obter informações sobre o objeto ou de pedir que ele execute alguma operação é sob o
intermédio da sua interface. O benefício do uso de interfaces é que elas permitem especificar
um objeto sem definir a sua implementação concreta, consequentemente dois ou mais objetos
da mesma interface podem realizar operações de modos diferentes (GAMMA et al., 2000).
Gamma et al. (2000) menciona a ligação dinâmica como um recurso bastante
explorado ao utilizar interfaces. O entendimento da ligação dinâmica consiste em associar
uma solicitação a um objeto e a uma de suas operações em tempo de execução.
Quando uma mensagem é enviada a um objeto, a operação específica que
será executada depende de ambos, mensagem e objeto receptor. Diferentes
objetos que suportam solicitações idênticas, podem ter diferentes
implementações das operações que atendem a estas solicitações. A
associação em tempo de execução de uma solicitação a um objeto e a uma
das suas operações é conhecida como ligação dinâmica. (GAMMA et al.,
2000, p. 29, grifo do autor).
O uso da ligação dinâmica significa que o envio de uma solicitação não define um
fluxo de operação em particular até o momento da execução. Em razão disso o programa é
capaz de esperar um objeto com uma interface em particular, sabendo que qualquer objeto que
tenha a interface correta está apto a aceitar a solicitação. Além do mais, a ligação dinâmica
permite substituir objetos que tenham interfaces idênticas em tempo de execução (GAMMA
et al., 2000).
De acordo com Gamma et al. (2000) os padrões de projeto permitem definir
interfaces pela identificação de seus elementos-chave e pelos tipos de dados que são enviados
através de uma interface. Os padrões de projeto também especificam relacionamentos entre
interfaces ao exigir que determinadas classes tenham interfaces similares, ou colocam
restrições sobre interfaces de determinadas classes. Um exemplo disso pode ser observado nos
padrões Decorator e Proxy, ao exigir que as interfaces de objetos Decorator e Proxy sejam
idênticas. O padrão Strategy depende fortemente do uso de interfaces ao definir para cada
família de algoritmos uma interface comum para todos os algoritmos suportados. No padrão
Visitor uma interface deve refletir todas as classes de objetos denominados visitantes.
42
Ao abstrair o processo de criação de objetos, os padrões de criação concedem
diferentes maneiras de associar uma interface à sua implementação de forma transparente no
momento da instanciação. Os padrões de criação asseguram que o projeto esteja definido em
termos de interfaces e não apenas de implementações concretas. Gamma et al. (2000, p. 33)
relata o seguinte: “Não declare variáveis como instâncias de classes concretas específicas. Em
vez disso, prenda-se somente a uma interface definida por uma classe abstrata [...]”
3.6 Limitações
Wendorff (2001) realizou uma análise para averiguar o uso excessivo de padrões de
projeto em um amplo sistema comercial. O estudo reportou consequências negativas que a
prática do uso excessivo de padrões pode causar nos processos futuros de manutenção. O
estudo revelou ainda que muitas vezes os padrões são aplicados sem que haja uma análise
prévia das suas consequências. Em função disso a aplicação de padrões pode ter efeitos
negativos sobre o software e consequentemente conduzir a processos de reengenharia e altos
custos de manutenção no futuro.
Gamma et al. (2000) afirmam que cada padrão de projeto se refere a um problema
que ocorre com determinada frequência em um contexto específico, descrevendo uma solução
para o problema de modo que se possa utilizar essa solução milhares de vezes sem
necessariamente seguir o mesmo caminho. Esta asserção é questionada por Arnout (2004), o
qual indaga que a definição de uma solução utilizando padrões deve ser adaptada para cada
novo contexto, o que significa que o uso de padrões de projeto não proporciona reusabilidade
em termos de código, mas sim em termos de uma adaptação a cada problema ou contexto em
particular.
43
CONCLUSÃO
Padrões de projeto de software são soluções para os problemas que ocorrem com
frequência no processo de desenvolvimento de sistemas de software. Pesquisas bibliográficas
revelam que os padrões de projeto fornecem alternativas de reuso de soluções que já foram
projetadas, testadas e se mostraram eficientes, assim, evitando alternativas que comprometam
a eficiência do sistema de software.
Os padrões de projeto GOF são classificados em três grupos principais: padrões de
criação, que descrevem técnicas para instanciar objetos; padrões estruturais, que descrevem
métodos de organização de classes e objetos em estruturas maiores; e padrões
comportamentais, que descrevem métodos de atribuição de responsabilidades a classes e
objetos.
Os avanços na indústria de software vêm requisitando cada vez mais os recursos de
engenharia de software para tornar os processos de desenvolvimento e manutenção mais
ágeis, menos suscetíveis a erros e a um menor custo. É neste contexto que a proposta dos
padrões de projeto ganhou relevância na comunidade de engenharia de software. As soluções
propostas por padrões de projeto retratam a experiência de profissionais e de projetos bem
sucedidos, definem uma terminologia comum que permite estabelecer um vocabulário
compartilhado na comunicação entre os membros da equipe, ajudam na identificação de
equívocos ou armadilhas comuns que ocorrem no desenvolvimento de software, e contribuem
para o desenvolvimento de software de maior qualidade.
Os estudos de caso apresentados neste trabalho monográfico mostraram que a
aplicação de padrões de projeto pode levar à construção de software com maior qualidade
estrutural e, portanto, de mais fácil manutenção. Os experimentos revelaram indícios de que a
aplicação de padrões de projeto na fase desenvolvimento do software é um fator positivo nos
processos futuros de manutenção: a documentação gerada a partir da aplicação de padrões de
projeto contribuiu para a manutenabilidade, uma vez que o suporte de uma documentação
explícita possibilita que as tarefas de manutenção sejam realizadas mais rapidamente e com
menos falhas; os padrões Decorator e Observer revelaram-se como os mais fáceis de serem
compreendidos e se mostraram bastante intuitivos, sendo utilizados facilmente pelos
profissionais com pouca experiência na aplicação destes padrões; o padrão Visitor reduziu os
esforços em tarefas de modificação do software, em função da sua representação gráfica junto
ao diagrama de classes.
44
Sistemas de software modulares mantém o código compreensível e
consequentemente mais fácil de manter. O grau de modularidade depende dos níveis de
acoplamento entre módulos e da coesão interna de cada módulo, à medida que o nível de
acoplamento é reduzido e o de coesão é elevado, obtém-se um software com maior grau de
modularidade. A influência dos padrões de projeto sobre a modularidade do software ocorre
através da manipulação direta dos níveis de acoplamento e coesão.
Apesar dos benefícios proporcionados, os padrões de projeto também podem ter
efeitos negativos no software. A aplicação de padrões sem que haja uma análise prévia das
suas consequências pode levar a processos de reengenharia e gerar autos custos de
manutenção.
Este trabalho monográfico aponta para os seguintes estudos futuros: realização de
experimentos em softwares de diferentes tamanhos e propósitos para avaliar a influência dos
padrões de projeto sobre o processo de manutenção; realização de trabalhos similares,
considerando métricas de software para avaliar a relevância dos padrões de projeto em
diferentes aspectos do software.
45
REFERÊNCIAS
ALEXANDER, C. The timeless way of building. New York: Oxford University Press, 1979.
ARNOUT, K. From patterns to components. 2004. 430f. Dissertação (Tese de doutorado).
Swiss federal institute of technology, Zurich, 2004.
CASSIMIRO, M. H. O. Padrões arquiteturais e seus benefícios no processo de
manutenção do software. 2010, 43f. Trabalho de conclusão de curso (graduação em Ciência
da Computação). Faculdade de Ciências Empresariais, Belo Horizonte, 2010. Disponível em:
<http://www.ricardoterra.com.br/publications/students/2010_cassimiro.pdf >. Acesso em: 22
maio 2012.
CHATZIGEORGIOU, A.; TSANTALIS, N.; DELIGIANNIS, I. An empirical study on
students’ ability to comprehend design patterns. Computers & Education, Oxford, UK, v.
51, n. 3, p. 1007-1016, 2008. Disponível em:
<http://eprints.csse.uom.gr/5/1/CompEdu_2008.pdf>. Acesso em: 22 maio 2012.
FREEMAN, Erich; FREEMAN, Elizabeth. Use a cabeça: padrões de projetos. 2. ed. Rio de
Janeiro: Alta books, 2009.
FERREIRA, K. A. M.; BIGONHA, M. A. S.; BIGONHA, R. S. Reestruturação de software
dirigida por conectividade para redução de custo de manutenção. Revista de informática
teórica e aplicada, Porto Alegre, v. 15, n. 2, p. 155-180, 2008. Disponível em:
<http://seer.ufrgs.br/rita/article/view/rita_v15_n2_p155-180>. Acesso em: 02 jun. 2012.
FERREIRA, K. A. M. Um modelo de predição de amplitude da propagação de
modificações contratuais em software orientado por objetos. 2011. 224f. Dissertação
(Tese de doutorado). Universidade federal de Minas Gerais, Belo Horizonte, 2011. Disponível
em: <http://www.bibliotecadigital.ufmg.br/dspace/bitstream/1843/SLSS-
8GYFSX/1/keciaalinemarquesferreira.pdf>. Acesso em: 02 jun. 2012.
FOWLER, M. Padrões de arquitetura de aplicações corporativas. Porto Alegre: Bookman,
2006.
GAMMA, E.; HELM, R.; JOHNSON, R.; VLISSIDES, J. Design Patterns: elements of
reusable object-oriented software. [S.l.]: Addison-Wesley, 1995.
GAMMA, E.; HELM, R.; JOHNSON, R.; VLISSIDES, J. Padrões de projeto: soluções
reutilizáveis de software orientado a objetos. São Paulo: Bookman, 2000.
IEEE. Standard glossary of software engineering terminology. Std 610.12, 1990, New
York: IEEE, ISBN 1-55937-067-X. Disponível em:
<http://www.idi.ntnu.no/grupper/su/publ/ese/ieee-se-glossary-610.12-1990.pdf>. Acesso em:
01 jun. 2012.
46
IEEE. Standard for developing software life cycle processes. Std. 1074, 1997, New York:
IEEE, ISBN 0-7381-0532-5. Disponível em:
<http://arantxa.ii.uam.es/~sacuna/is1/normas/IEEE_Std_1074_1997.pdf>. Acesso em: 01 jun.
2012.
JEANMART, S.; GUEHENEUC, Y.; SAHRAOUI, H.; HABRA, N. Impact of the visitor
pattern on program comprehension and maintenance. In: International Symposium on
Empirical Software Engineering and Measurement, 3., 2009, Lake Buena Vista, Florida,
USA. Proceedings… Whashington: IEEE, 2009. p. 69-78. Disponível em: < http://www-
etud.iro.umontreal.ca/~ptidej/yann-gael/Work/Publications/Documents/ESEM09.doc.pdf>.
Acesso em: 24 maio 2012.
LINO, C. E. Reestruturação de software com adoção de padrões de projeto para a
melhoria da manutenabilidade. 2011. 68f. Trabalho de conclusão de curso (Graduação em
Ciência da Computação), Universidade Federal de Lavras, Lavras, 2011. Disponível em:
<http://www.bsi.ufla.br/monografias/2011/CarlosEduardoLino.pdf>. Acesso em: 14 abr.
2012.
MAGELA, R. Engenharia de software aplicada: princípios. Rio de Janeiro: Alta Books,
2006.
NANTHAAMORNPHONG, A.; CARVER, J. C. Design patterns in software maintenance:
an experiment replication at University of Alabama. In: International workshop on replication
in empirical software engineering research, 2., 2011, Banff, Alberta, Canada. Proceedings…
Tuscaloosa: UA, 2011. p. 15-24.
NG, T.H. ; CHEUNG, S.C.; CHAN, W.K. ; YU, Y.T. Work experience versus refactoring
to design patterns: a controlled experiment. In: Symposium on foundations of software
engineering, 14., 2006, Portland. Proceedings… New York: ACM, 2006, pp. 12-22.
Disponível em: <http://www.cs.cityu.edu.hk/~cssam/publications/ng-FSE06.pdf>. Acesso
em: 24 maio 2012.
NG, T.H. ; CHEUNG, S.C.; CHAN, W.K. ; YU, Y.T. Do maintainers utilize deployed
design patterns effectively?. In: International Conference on Software Engineering, 29.,
2007, Minneapolis, Minesota, USA. Proceedings… Whashington: IEEE, 2007, p. 168-177.
Disponível em: <http://www.cs.cityu.edu.hk/~wkchan/papers/icse07-
ng+cheung+chan+yu.pdf>. Acesso em: 02 jun. 2012.
NG, T.H. ; YU, Y.T.; CHEUNG, S.C. Factors for effective use of developed design
patterns. In: International conference on quality software, 10., 2010, Zhangjiajie, China.
Proceedings… Whashington: IEEE, 2010, p. 112-121. Disponível em:
<http://www.cs.cityu.edu.hk/~cssam/publications/ng-QSIC10.pdf>. Acesso em: 02 jun. 2012.
NG, T.H. ; CHEUNG, S.C.; CHAN, W.K. ; YU, Y.T. Human and Program Factors
Affecting the Maintenance of programs with deployed design patters. Information and
software technology, Butterworth-Heinemann Newton, Massachusetts, USA, v. 54, n. 1, p.
99-118, 2012. Disponível em: <http://www.cs.cityu.edu.hk/~cssam/publications/ng-
IST12.pdf>. Acesso em: 23 maio 2012.
47
PAULA FILHO, W. P. Engenharia de software: fundamentos, métodos e padrões. 2. ed. Rio
de Janeiro: LTC, 2003.
PRECHELT, L.; BROSSLER, P.; TICHY, W. F.; UNGER, B.; VOTTA, L. G. A controlled
experiment in maintenance comparing design patterns to simpler solutions. Transactions
on software engineering, Piscataway, New Jersey, USA, v. 27, n. 12, p. 1134-1144, 2001.
Disponível em: <http://page.mi.fu-berlin.de/prechelt/Biblio/patmain_tse2001.pdf >. Acesso
em: 24 maio 2012.
PRECHELT, L.; PHILIPPSEN, N.; TICHY, W. F.; UNGER, B. Two controlled
experiments assessing the usefulness of design pattern documentation in program
maintenance. Transactions on software engineering, Piscataway, New Jersey, USA, v. 28, n. 6,
p. 595-606, 2002. Disponível em: <http://page.mi.fu-
berlin.de/prechelt/Biblio/patdoc_tse2002.pdf>. Acesso em: 22 maio 2012.
PRESSMAN, R. S. Engenharia de software. São Paulo: Mackron Books, 1995.
PETERS, J. F.; PEDRYCS, W. Engenharia de software: teoria e prática. Rio de Janeiro:
Campus, 2001.
PREE, W. Design patterns for object-oriented software development. [S.l.]: Addison-
Wesley, 1995.
ROCHA, J. C. Software de modelagem e simulação de redes de filas. 2011. 53f. Relatório
de estágio. Universidade do estado de Mato Grosso, Barra do Bugres, 2011.
SOMMERVILLE, I. Engenharia de software. 6. ed. São Paulo: Addison Wesley, 2003.
SHALLOWAY, A.; TROTT, J. R. Explicando padrões de projeto: uma nova perspectiva
em projeto orientado a objeto. Porto Alegre: Bookman, 2004.
THOMAZINI NETO, L. F. Padrões de projeto. 2006. 47f. Trabalho de conclusão de curso
(Graduação em Ciência da Computação), Faculdade de Jaguariúna, Jaguariúna, 2006.
VOKAC, M.; TICHY, W; SJOBERG, D. I. K.; ARISHOLM, E.; ALDRIM M. A controlled
experiment comparing the maintainability of programs designed with and without
design patterns: a replication in a real programming environment. Transactions on
software engineering, Hingham, Massachusetts, USA, v.9, n. 3, p. 149-195, 2004. Disponível
em: <http://faculty.ksu.edu.sa/ghazy/CSC548_Sample/A%20Controlled%20Experiment.pdf>.
Acesso em: 24 maio 2012.
XIONG, C.; XIE, M.; NG, S. Optimal software maintenance policy considering
unavailable time. Journal of software maintenance and evolution: research and practice,
[S.l.], v. 23, n. 1, p. 21-33, 2011. Disponível em:
<http://onlinelibrary.wiley.com/doi/10.1002/smr.467/pdf >. Acesso em: 04 jun. 2012.
48
WENDORFF, P. Assessment of design patterns during software reengineering: lessons
learned from a large commercial project. In: European Conference on Software Maintenance
and Reengineering, 1., 2001, Oldenburg, Germany. Proceedings… Whashington: IEEE,
2001. p. 77-84. Disponível em: <http://www.integrative-
paradigm.org/papers/CSMR500.pdf>. Acesso em: 23 maio 2012.