aplicação de padrões de projeto para a melhoria da manutenabilidade de software

49
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

Upload: cesar-rocha

Post on 19-Jun-2015

2.400 views

Category:

Technology


1 download

DESCRIPTION

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.

TRANSCRIPT

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.

“Toda igualdade aparente esconde

uma hierarquia”

Masson Cooley

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.