UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE...

64
Universidade Federal do Ceará Centro de Tecnologia Departamento de Engenharia de Teleinformática Curso de Graduação de Engenharia de Teleinformática UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Igor Arcanjo Chaves Fortaleza Ceará Junho/2012

description

Monografia - Engenharia de Teleinformática UFC - UM ARCABOUÇO DE APOIO AO APRENDIZADO DEPADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DEPROGRAMAÇÃO ORIENTADA A OBJETOS

Transcript of UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE...

Page 1: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

Universidade Federal do Ceará

Centro de Tecnologia

Departamento de Engenharia de Teleinformática

Curso de Graduação de Engenharia de Teleinformática

UM ARCABOUÇO DE APOIO AO APRENDIZADO DE

PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE

PROGRAMAÇÃO ORIENTADA A OBJETOS

Igor Arcanjo Chaves

Fortaleza – Ceará

Junho/2012

Page 2: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

UM ARCABOUÇO DE APOIO AO APRENDIZADO DE

PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE

PROGRAMAÇÃO ORIENTADA A OBJETOS

Projeto Final de Curso submetido à

Coordenação do programa de Graduação em

Engenharia de Teleinformática da

Universidade Federal do Ceará como parte

dos requisitos para a obtenção do grau de

Engenheiro de Teleinformática.

Autor: Igor Arcanjo Chaves

Orientador: Prof. Dr. José Marques Soares

Fortaleza – Ceará

Junho/2012

Page 3: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

Título do Trabalho: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES

DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA

A OBJETOS

Autor: Igor Arcanjo Chaves

Defesa em: 29/06/2012 Nota Obtida: 9,7

Banca Examinadora

_________________________________________

Prof. Dr. José Marques Soares

Orientador

_________________________________________

Prof. Dr. Danielo Gonçalves Gomes

Universidade Federal do Ceará

_________________________________________

Prof. Dr. Antonio de Barros Serra

Instituto Federal de Educação, Ciência e Tecnologia do Ceará

Fortaleza, 29 de Junho de 2012

Page 4: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

Dedico esta monografia aos meus pais, Tarcisio e Helena, pelo apoio

incondicional, aos meus irmãos, Breno e Tassia, que apesar da

distância sempre estiveram ao meu lado e à minha namorada,

Fernanda, que nos momentos mais difíceis me deu forças e inspiração

para continuar e jamais desistir dos meus objetivos.

“Que os vossos esforços desafiem as impossibilidades, lembrai-vos de

que as grandes coisas do homem foram conquistadas do que parecia

impossível.”

Charles Chaplin

Page 5: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

AGRADECIMENTOS

Considerando este trabalho como o resultado de uma longa caminhada, o

agradecimento às pessoas que contribuíram para a minha formação não é uma tarefa fácil.

Para não correr o risco de cometer injustiças agradeço de antemão todas as pessoas que

passaram pela minha vida e que direta ou indiretamente me ajudaram nessa longa caminhada

em busca do sucesso.

Gostaria de agradacer também em particular algumas pessoas que tiveram participação

fundamental para a construção desse trabalho:

Ao meu professor e orientador, Prof. Dr. José Marques, pelos conhecimentos

transmitidos em sala de aula e também fora dela e pela força e dedicação na orientação deste

trabalho.

Ao GREat (Grupo de Redes de Computadores, Engenharia de Software e Sistemas),

em especial à Prof. Dra. Rossana Andrade e ao Reinaldo Braga, pela oportunidade ímpar que

tive ao ingressar no grupo e pelo total apoio e confiança depositada em mim durante todo o

tempo em que estive no grupo.

Aos amigos de faculdade pelos momentos de descontração dentro e fora de sala de

aula, pelas noites em claro estudando para provas e trabalhos da faculdade e pela forte

amizade que construímos durante essa longa caminhada.

A todos os professores do Departamento de Engenharia de Teleinformática pelo

aprendizado passado durante minha graduação.

À Universidade Federal do Ceará pela formação de nível superior de excelente

qualidade.

Page 6: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

Resumo

Os processos modernos de engenharia de software, em especial as metodologias ágeis,

tem como principal objetivo não só a produtividade na construção de softwares, mas também

a sua produção com requisitos de alta qualidade, o que inclui características de reusabilidade e

expansibilidade. Umas das técnicas para se alcançar qualidade e produtividade é o uso de

padrões de projeto (ou design patterns). Em muitos programas acadêmicos, os padrões de

projeto só são estudados em disciplinas de Engenharia de Software, mais precisamente,

durante as fases associadas à codificação. Defende-se a inclusão de maneira objetiva do

estudo sobre padrões de projeto já em disciplinas de programação orientada a objetos, visto

que eles podem ser vistos como técnicas avançadas e consolidadas de construção de software

e representam um elemento de compreensão efetiva dos mecanismos de herança e

polimorfismo. Nesse sentido, este trabalho propõe um arcabouço simples para dar suporte ao

aprendizado de padrões de projeto em disciplinas de programação orientada a objetos. O

Arcabouço é apresentado através do desenvolvimento inicial de um conjunto de padrões de

projeto que são julgados importantes, podendo ser generalizado para futuras expansões. Para

cada um desses padrões, são descritas as suas principais características, a situação que

comumente requer o seu uso, além de sua implementação em Java um caso de exemplo.

Finalmente, é proposto um exercício para sedimentar o seu aprendizado, explorando-se, em

seguida, o reuso das classes e interfaces que fazem parte da estrutura do padrão a fim de

mostrar a facilidade de evolução da solução e ressaltar as características de baixo acoplamento

de suas partes.

Palavras-Chaves: Padrão de Projeto, Programação Orientada a Objetos, Engenharia

de Software, Qualidade de Software.

Page 7: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

Abstract

Modern processes of software engineering, particularly agile methods, has its the main

goal not only the productivity in building software, but also its production with high quality

requirements, which includes characteristics of reusability and expandability. One of the

techniques to achieve quality and productivity is the use of design patterns. In many academic

programs, design patterns are only studied in the disciplines of Software Engineering, more

specifically during the phases associated with encoding. The text supports the inclusion of an

objective study on design patterns already in programming disciplines, especially in object-

oriented programming, since they can be viewed as advanced and consolidated programming

techniques, besides it represents an element of effective understanding of the mechanisms of

inheritance and polymorphism. Thus, this study aims to build a framework to support the

learning of design patterns in disciplines of object-oriented programming. The framework is

presented by developing a set of design patterns that are deemed important and can be

generalized for future expansion. For each of these patterns, it's describes its main

characteristics, the situation that usually requires its use, and its implementation in Java an

example case. Finally, we propose an exercise to consolidate their learning, exploring,

whenever possible, the reuse of classes and implementing interfaces involved in the expansion

of pattern in order to emphasize the fundamentals of low coupling provided by it.

Keywords: Design Patterns, Object Oriented Programming, Software Engineering,

Software Quality.

Page 8: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

SUMÁRIO

1. Introdução .................................................................................................................................... 12

1.1. Motivação............................................................................................................................. 12

1.2. Objetivos .............................................................................................................................. 13

1.3. Organização do documento ................................................................................................. 14

2. Padrões de Projeto ....................................................................................................................... 15

2.1 Introdução .................................................................................................................................. 15

2.2 Elementos Indispensáveis de Programação Orientada a Objetos .............................................. 16

Herança ........................................................................................................................................ 17

Polimorfismo ................................................................................................................................ 18

2.3 Arcabouço para o Estudo de Padrões de Projeto ....................................................................... 20

2.4 Strategy ...................................................................................................................................... 23

Apresentação ............................................................................................................................... 23

Descrição com Exemplo ............................................................................................................... 23

Codificação do Exemplo ............................................................................................................... 26

Proposição .................................................................................................................................... 29

Extensão ....................................................................................................................................... 30

2.5 Abstract Factory ......................................................................................................................... 30

Apresentação ............................................................................................................................... 30

Descrição com Exemplo ............................................................................................................... 30

Codificação do Exemplo ............................................................................................................... 33

Proposição .................................................................................................................................... 37

Extensão ....................................................................................................................................... 37

2.6 Composite .................................................................................................................................. 37

Apresentação ............................................................................................................................... 37

Descrição com Exemplo ............................................................................................................... 38

Codificação do Exemplo ............................................................................................................... 39

Proposição .................................................................................................................................... 41

Extensão ....................................................................................................................................... 41

2.7 Padrões de Projeto em Construção ............................................................................................ 42

3. A Gênese do Arcabouço Proposto ................................................................................................ 43

4. Considerações finais ..................................................................................................................... 48

Page 9: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

5. Referências Bibliográficas............................................................................................................. 50

6. Apêndice ...................................................................................................................................... 52

6.1. Apêndice A - Facade .................................................................................................................. 52

Apresentação ............................................................................................................................... 52

Descrição com Exemplo ............................................................................................................... 52

Codificação do Exemplo ............................................................................................................... 54

Proposição .................................................................................................................................... 55

Extensão ....................................................................................................................................... 56

6.2. Apêndice B - Singleton............................................................................................................... 56

Apresentação ............................................................................................................................... 56

Descrição com Exemplo ............................................................................................................... 56

Codificação do Exemplo ............................................................................................................... 57

Proposição .................................................................................................................................... 59

Extensão ....................................................................................................................................... 59

6.2. Apêndice C - Iterator ................................................................................................................. 59

Apresentação ............................................................................................................................... 59

Descrição com Exemplo ............................................................................................................... 60

Codificação do Exemplo ............................................................................................................... 61

Proposição .................................................................................................................................... 64

Extensão ....................................................................................................................................... 64

Page 10: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

LISTA DE FIGURAS

Figura 1 – Exemplo de Classe e Objetos (UML). .................................................................... 16

Figura 2 – Exemplo de Herança. .............................................................................................. 18

Figura 3 – Exemplo de Polimorfismo....................................................................................... 20

Figura 4 – Arcabouço para o estudo de padrões. ...................................................................... 22

Figura 5 – Diagrama de Classes Inicial (UML) Strategy ......................................................... 23

Figura 6 – Classes RubberDuck e WoodDuck ......................................................................... 24

Figura 7 – Classes RubberDuck ............................................................................................... 25

Figura 8 – Diagrama de Classes Final (UML) Strategy ........................................................... 26

Figura 9 – Classes FlyBehavior.java, FlyWithWings.java e FlyNoWay.java ......................... 26

Figura 10 – Classes QuackBehavior.java, Quack.java, MuteQuack.java e Squeak.java ......... 27

Figura 11 – Classe Duck.java ................................................................................................... 28

Figura 12 – Classes MallardDuck.java, ReadheadDuck.java, WoodDuck.java e

RubberDuck.java ...................................................................................................................... 29

Figura 13 – Classe Application.java ......................................................................................... 29

Figura 14 – (a) Classes Button e Menu (b) Classe Application.java ........................................ 31

Figura 15 – (a) Classes WinButton e LinuxButton (b) Classe Application.java ...................... 31

Figura 16 – Diagrama de Classes (UML) Abstract Factory ..................................................... 33

Figura 17 – Classe GUIFactory.java I ...................................................................................... 34

Figura 18 – Classes WinFactory.java e LinuxFactory.java ...................................................... 34

Figura 19 – Classe Button.java ................................................................................................. 34

Figura 20 – Classes WinButton.java e LinuxButton.java ........................................................ 35

Figura 21 – Classes Application.java ....................................................................................... 36

Figura 22 – Classe GUIFactory.java II ..................................................................................... 36

Figura 23 – Diagrama de Classes (UML) Composite .............................................................. 39

Figura 24 – Classe ComponenteGrafico.java ........................................................................... 39

Figura 25 – Classes Linha.java e Texto.java ............................................................................ 40

Figura 26 – Classe Imagem.java............................................................................................... 41

Figura 27 – Enunciado da Atividade sobre Design Patterns .................................................... 44

Figura 28 – Diagrama de Classes (UML) Facade .................................................................... 53

Figura 29 – Classes Motor.java, Porta.java, Farol.java e Radio.java ....................................... 54

Figura 30 – Classe CarroFacade.java ....................................................................................... 55

Figura 31 – Exercício Proposto Facade .................................................................................... 56

Figura 32 – Diagrama de Classes (UML) Singleton ................................................................ 57

Figura 33 – Classe Singleton.java ............................................................................................ 58

Figura 34 – Classe Main.java ................................................................................................... 59

Figura 35 – Diagrama de Classes (UML) Iterator .................................................................... 61

Figura 36 – Classes Estrutura.java e Iterador.java ................................................................... 61

Figura 37 – Classes Fila.java e Lista.java ................................................................................ 62

Figura 38 – Classes IteradorLista.java e IteradorFila.java ....................................................... 63

Figura 39 – Classe Aplicacao.java ........................................................................................... 64

Page 11: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

LISTA DE TABELAS

Tabela 1– Avaliação média dos alunos da turma de graduação para a atividade sobre padrões

de projeto na disciplina de Engenharia de Software (2012-1).................................................. 46

Page 12: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

12

1. Introdução

1.1. Motivação

A definição de Engenharia de Software não é única. Apesar das distintas definições de

diversos autores, elas apresentam características de convergência. O IEEE (Institute of

Eletrical and Eletronics Engineers) [1] define engenharia de software como o estudo e

aplicação de uma abordagem sistemática, disciplinada e quantificável para o

desenvolvimento, operação e manutenção do software. De acordo com Ian Summerville [2] a

engenharia de software se relaciona com todos os apectos da produção do software, desde a

especificação do sistema até a manutenção que será feita após o software entrar em produção.

Os processos modernos de engenharia de software, em especial as metodologias ágeis,

tem como principal objetivo não só a produção de softwares com alta produtividade, mas

também com alta qualidade e que sejam reusáveis e expansíveis.

Qualidade de software é outro termo utilizado na engenharia de software na qual a

definição não é uma unanimidade. A NBR ISO 9000:2005 [3] define qualidade como o "grau

no qual um conjunto de características inerentes satisfaz a requisitos". Segundo a mesma

norma requisito é a "necessidade ou expectativa que é expressa, geralmente, de forma

implícita ou obrigatória". Dessa forma, pode-se inferir que a qualidade pode ser medida

através do grau de satisfação das pessoas envolvidas na realização de determinado serviço ou

produto, tornando a qualidade algo bem subjetivo, já que depende da interpretação de cada ser

envolvido e não somente do que está escrito ou expresso.

De acordo com Pressman [4] a qualidade de software precisa ser implementada e não

ficar somente na idéia. Ele diz que é preciso definir explicitamente o termo qualidade quando

o mesmo for utilizado, é preciso também criar um conjunto de atividades que irão ajudar a

garantir que a qualidade definida seja alcançada e, também, utilizar métricas para melhoraria

de processo de software aumentando, consequentemente, a qualidade do produto final.

Portanto, a busca da qualidade de software não é algo que deve se preocupar somente após o

código ser gerado, ela precisa ser uma atividade que seja aplicada ao longo do processo de

desenvolvimento de software.

Bruegge [5] sintetiza o conceito Engenharia de Software englobando diversas

características, definindo-o como “uma coleção de técnicas, metodologias e ferramentas que

dão suporte à produção de sistemas de alta qualidade, com um orçamento determinado e

Page 13: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

13

dentro do cronograma estabelecido, considerando que mudanças nos requisitos e no ambiente

ocorrem frequentemente”.

Umas das técnicas para se alcançar qualidade e produtividade, imprimindo, ao mesmo

tempo, características que ofereçam maior suporte a mudanças, é o uso de padrões de projeto,

mais conhecido pelo termo em inglês design patterns. A idéia de projetar soluções a partir de

problemas já conhecidos, solucionados e documentados não é nova e não teve origem na

engenharia de software, o conceito de padrões, dentro dessa ótica, foi apresentada por um

arquiteto chamado Christopher Alexander [6] em 1977, no contexto de arquitetura. Segundo

ele cada padrão descreve um problema que ocorre repetidas vezes em nosso ambiente, para

então descrever a parte central da solução para esse problema que poderá ser utilizada

inúmeras vezes, sem nunca ter que fazê-lo duas vezes da mesma maneira.

Essa definição de padrão chamou a atenção da comunidade de engenharia de software

e em 1995 Erich Gamma, Richard Helm, Ralph Jonhson e Jonh Vlissides lançaram o livro

Design Patterns – elements of reusable object-oriented software [7]. Esse livro descreve 23

padrões de projetos sendo classificados, de acordo com os autores, em 3 categorias: padrões

de projeto de criação, estruturais e comportamentais. Segundo os autores a utilização de

padrões de projeto facilita o reúso de projetos e arquiteturas de software que tiveram êxito em

experiências anteriores. Os padrões também ajudam os desenvolvedores a modelar

alternativas que não comprometam o reúso, além de melhorar a documentação e,

consequentemente, a manutenção do software. De forma objetiva o padrão de projeto ajuda o

desenvolvedor a modelar o seu problema rápida e corretamente.

Os padrões de projeto representam soluções que foram generalizadas ao longo do

tempo para problemas de características recorrentes. Dessa maneira, justifica-se incluir, de

maneira objetiva, o estudo sobre padrões de projeto já em disciplinas de programação, em

especial, em programação orientada a objetos, visto que eles podem ser vistos como técnicas

avançadas e consolidadas de programação.

1.2. Objetivos

Sabendo da importância da utilização de padrões de projeto para a qualidade e

produtividade do desenvolvimento de software, este trabalho tem por objetivo propor um

arcabouço constituído por recursos técnicos de apoio ao ensino e aprendizagem para

introdução aos padrões de projeto em disciplinas de programação orientada a objetos.

Page 14: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

14

Visa-se associar, de maneira efetiva, a teoria e a prática sobre o estudo de padrões de

maneira desvinculada de disciplinas de Engenharia de Software. O arcabouço inclui, para

cada um dos padrões, os seguintes pontos:

1) Introdução teórica ao padrão, identificando seus objetivos e benefícios;

2) Modelagem, através de diagrama de classes (UML) do padrão de projetos;

3) Descrição das classes envolvidas no padrão;

4) Implementação de um cenário simples com o uso do padrão;

5) Sugestão de exercício prático para um cenário diferente do apresentado, usando

o mesmo padrão.

Através desse arcabouço, pretende-se que o aprendizado e o ensino de orientação a

objetos, com premissas de baixo acoplamento, alta coesão e reusabilidade, se dê de forma

mais eficaz. Para isso, será sempre feita a contextualização por intermédio de exemplos

práticos, seguido da aplicação do padrão para aquele tipo de problema.

1.3. Organização do documento

Este trabalho está disposto da seguinte maneira: no primeiro capítulo, foram

apresentados uma breve introdução sobre engenharia de software e padrões de projeto seguido

da motivação deste trabalho, finalizando com a descrição de seus objetivos; no segundo

capítulo o conceito de padrão de projeto é descrito, em seguida discute-se o conceito de

programação orientada a objetos, logo após é proposto um arcabouço para o estudo de

padrões de projeto, para então apresentar os padrões nos moldes do arcabouço proposto; no

capítulo terceiro são descritas algumas dificuldades no aprendizado de padrões de projeto em

sala de aula; no quarto capítulo fazemos as considerações finais; na seção posterior temos as

referências bibliográficas; e, por fim, temos no apêndice, capítulo seis, padrões de projeto que

ainda encontram-se em construção nos moldes do arcabouço em questão.

Page 15: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

15

2. Padrões de Projeto

2.1 Introdução

Gamma et al [7] definem que padrões de projeto “são descrições de objetos e classes

comunicantes que precisam ser personalizadas para resolver um problema geral de projeto

num contexto particular”. Eles surgiram como o resultado de experiências e soluções para

problemas recorrentes no desenvolvimento de software. Eles podem ser definidos, também,

como arquiteturas testadas para construir softwares orientados a objetos flexíveis e

sustentáveis [8].

O grupo conhecido como Gang of Four, formado por Erich Gamma, Richard Helm,

Ralph Johnson e John Vlissides, no livro lançado em 1995, descreve 23 padrões de projeto

agrupados em 3 categorias: criacionais, estruturais e comportamentais [7]. Ele ainda subdivide

cada categoria de padrão em padrões de classe ou de objeto.

Padrões de projeto criacionais estão relacionados com o processo de criação e

instanciação de objetos. Eles ajudam a projetar um sistema independente de como os objetos

são criados, compostos e representados. O padrão criacional de classe utiliza herança para

variar a forma como a classe é instanciada, enquanto o padrão criacional de objeto delega sua

instanciação para outro objeto.

Padrões do tipo estrutural fazem referência à forma como classes e objetos são

compostos para formar estruturas maiores. No padrão estrutural de classe, utiliza-se o

conceito de herança para compor implementações ou interfaces. Já nos padrões estruturais de

objeto são descritas formas de compor objetos para adquirir novas funcionalidades em tempo

de execução, o que não é possível através da composição estática de classes.

Padrões comportamentais descrevem a interação e atribuição de responsabilidades

entre objetos e classes. Eles não descrevem somente padrões de objetos ou classes mas

também padrões de comunicação entre eles. Esse tipo de padrão caracteriza os fluxos

complexos de controle que é difícil de acompanhar em tempo de execução. Os padrões

comportamentais de classe utilizam herança para distribuir comportamentos,

responsabilidades entre as classes, já os padrões de objeto utilizam a composição para fazer

essa distribuição.

Neste trabalho não temos como objetivo abordar todos os padrões de projeto, mas um

conjunto que seja suficientemente capaz de cobrir e exemplificar a estrutura do arcabouço

Page 16: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

16

proposto. Assim, são expostos e discutidos os padrões criacionais Singleton e Abstract

Factory, os padrões estruturais Facade e Composite e os padrões comportamentais Iterator e

Strategy.

2.2 Elementos Indispensáveis de Programação Orientada a Objetos

Para estudar padrões de projeto, é necessário um conhecimento consistente do

paradigma de programação orientada a objetos. Esse paradigma baseia-se na análise, projeto e

desenvolvimento de sistemas a partir da utilização de objetos, que possuem atributos e

comportamentos, e se comunicam entre si, através de mensagens, colaborando para a

formação de sistemas. Esse paradigma é baseado nos seguintes conceitos: objeto, classe,

encapsulamento, herança e polimorfismo.

Os conceitos de classe e objeto estão intimamente ligados. O objeto pode ser definido

como uma entidade física, palpável ou mesmo conceitual, abstrata. Cada objeto tem suas

características, as quais chamamos de atributos, e comportamentos, que também podem ser

chamados de métodos. Existem objetos que possuem propriedades e comportamentos

similares, dando origem ao conceito de classe (de objetos). As classes definem um conjunto

de atributos e de comportamentos que são comuns a um conjunto de objetos. Enquanto um

objeto é uma entidade que executa uma função no sistema, uma classe define uma estrutura

comum aos tipos de objetos.

Na Figura 1 é apresentado um exemplo onde a classe Pessoa possui três atributos ,

nome, cpf e endereco, e três métodos, comer(), estudar(), dormir(). Tem-se também a

representação de dois objetos da classe Pessoa, identificados como joao e maria. A

convenção utilizada é inerente à Unified Modeling Language (UML).

Figura 1 – Exemplo de Classe e Objetos (UML).

O encapsulamento é um conceito que, como o próprio nome insinua, empacota, ou

seja, protege algumas propriedades do objeto de modificações que possam deixar o objeto em

Page 17: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

17

estado inconsistente. Utilizando esse conceito obtemos vários benefícios, entre eles proteger

dados e operações, deixar o código mais legível e melhor estruturado, tornando a manutenção

menos custosa. Para dar suporte ao encapsulamento bem como à definição da interface

pública de um objeto (métodos e atributos expostos para outros objetos), a mairoria das

linguagens OO, como o Java, fornece quatro tipos de modificadores de acesso ou visibilidade:

public, private, protected e default.

Os atributos e métodos de um objeto ou classe são comumente chamados de membros

desse objeto ou classe. Desse modo, quando um membro de uma classe é definido como

public, significa que todos os objetos têm acesso a esse membro. Quando, por outro lado, esse

membro é definido como private, só quem tem acesso a esse membro é a própria classe. Os

modificadores protected e default são quase idênticos. Enquanto o membro default pode ser

acessado apenas pelas classes que pertencerem ao mesmo pacote, o membro protected pode

ser acessado também pelas suas subclasses, mesmo que suas subclasses não perteçam ao

mesmo pacote [9].

Herança

O conceito de herança é definido por [8] como uma forma de reutilizar o código

quando uma nova classe é criada, absorvendo membros de uma classe já existente,

economizando tempo durante o desenvolvimento do software.

Quando uma classe herda de uma outra classe existente, esta classe é chamada de

superclasse e aquela de subclasse. A subclasse herda as propriedades da superclasse, ou seja,

ela tem acesso aos atributos e métodos, dependendo dos modificadores de acesso, da

superclasse. Existem dois tipos de herança, simples e múltipla, na primeira uma classe só

pode herdar de somente uma superclasse diretamente, como é o caso do Java, já na herança

múltipla uma classe pode herdar mais de uma superclasse diretamente, um exemplo é a

linguagem C++.

Na Figura 2, é mostrado um exemplo onde as classes Estudante e Engenheiro são

subclasses da classe Pessoa. Desse modo, as subclasses herdam todos os atributos, pois eles

possuem modificadores de acesso protected, e todos os métodos da superclasse, pois possuem

modificadores de acesso public.

Page 18: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

18

Figura 2 – Exemplo de Herança.

Polimorfismo

Polimorfismo, que vem do grego "muitas formas", permite que se utilizem objetos

pertencentes a classes relacionadas entre si pela relação de herança. Através de uma interface

única, o objetivo é o de tratar uma variedade de classes relacionadas de forma uniforme,

facilitando, por um lado, a especialização do comportamento e, por outro lado, simplificando

a adição de novas classes ao software sem requerer modificação nas classes pré-existentes, o

que imprime ao software características de baixo acoplamento.

O polimorfismo permite que o processamento de objetos que possuem a mesma

superclasse em uma hierarquia sejam tratados como se todas fossem objetos da superclasse

[8]. Utilizando o polimorfismo, pode-se projetar e implementar sistemas que são facilmente

extensíveis, ou seja, a adição de novas classes pode ser feita com pouca ou nenhuma

modificação, contanto que essas novas classes façam parte da hierarquia de herança do

sistema. Nota-se que polimorfismo está intimamente ligado à utilização de herança.

Entretanto, para que esse requisito seja cumprido de maneira correta, é necessário que a

hierarquia de classes atenda ao princípio de substituição de Liskov [10], que define que, se um

objeto do tipo S pode ser substituído em todos os locais onde um objeto do tipo T, é esperado,

então S é um subtipo de T. Se, em algum caso, essa substituição não resultar em um

comportamento correto e esperado, o reuso promovido pela herança foi utilizado de maneira

incorreta, modificando a semântica da interface comum encontrada na hierarquia de classes, e

o princípio de Liskov foi quebrado.

Page 19: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

19

Na Figura 3 mostra-se um exemplo em Java utilizando conceito de polimorfismo. A

classe abstrata Animal que contém o método também abstrato display() é a superclasse das

classes concretas Dog e Cat que implementam o método herdado. A aplicação é representada

pela classe Application, onde, na linha 8, tem-se a instanciação de uma lista de objetos,

animalList, do tipo Animal. Ainda na aplicação, tem-se a instanciação de dois objetos, dog e

cat, do tipo Dog e Cat, respectivamente. Nas linhas 12 e 13 esses dois objetos são adicionados

na lista animalList. É criado, também na classe Application, o método showAnimals(), que

recebe como parâmetro um ArrayList<Animal>. Nesse método varrem-se todos os objetos e

chama-se, para cada um deles o método, display(). Note que, na linha 22, apesar de não saber

qual o tipo de animal, é chamado o método display() e será mostrado na tela o tipo

correspondente ao animal que ele representa.

É possível observar também que ao adicionar outra classe que herde de Animal, por

exemplo a classe Coelho, eu não precisarei modificar o código no método showAnimals(). A

única alteração será para colocar o coelho na lista de animais.

Page 20: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

20

Figura 3 – Exemplo de Polimorfismo.

A aplicação dos conceitos de herança e polimorfismo, desenvolvidos através do

princípio de substituição de Liskov, são elementos de relevância indispensáveis à

compreensão e à utilização dos padrões de projeto.

2.3 Arcabouço para o Estudo de Padrões de Projeto

Como já mencionado anteriormente, a utilização de padrões de projeto é de extrema

importância no desenvolvimento de software de qualidade e com produtividade. Este trabalho

descreve os padrões de projeto com foco na introdução do seu aprendizado em disciplinas de

programação orientada a objetos. Utiliza-se um modelo que associa, de maneira efetiva, a

Page 21: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

21

teoria e a prática na utilização dos padrões de projeto. O modelo proposto é formado por três

blocos principais: apresentação, desenvolvimento conceitual e desenvolvimento prático,

descritos em seguida:

Apresentação – Neste bloco é descrito formalmente o padrão de projeto e o

seu propósito, indicando-se como e onde ele pode ser utilizado, mas sem

maiores detalhamentos técnicos sobre implementação ou modelagem.

Desenvolvimento conceitual – Neste bloco são explorados os aspectos

conceituais e a motivação para usar o padrão estudado. Esse bloco subdivide-se

em duas partes.

o Descrição com exemplo – apresenta-se um problema técnico com o

exemplo e usa-se uma abordagem de tentativas intermediárias de

solução do mesmo, até chegar à estrutura efetivamente proposta pelo

padrão de projetos, mostrando, assim, os benefícios de sua utilização.

As estruturas são desenvolvidas com apoio em diagramas de classes

simplificados. Esses diagramas têm por objetivo enfatizar a solução do

padrão de projeto e não mostrar, necessariamente, todas as

propriedades das classes envolvidas. Não é obrigatória a utilização de

diagramas em UML, podendo-se utilizar outras formas de apresentação.

Entretanto, devido à representatividade e adequação dessa linguagem

de modelagem à Orientação a Objetos, seu uso é fortemente

recomendado. Eventualmente, os conhecimentos sobre diagramas de

classe podem ser desenvolvidos de maneira concomitante, caso isso não

tenha ocorrido ao longo do aprendizado do curso de orientação a

objetos.

o Codificação do exemplo – Nesta parte, é realizada e discutida a

codificação que materializa o exemplo desenvolvido na parte

precedente do bloco “desenvolvimento conceitual”. É mostrada e

discutida a implementação que realiza as relações apresentadas no

diagrama de classes apresentado. O código contendo os exemplos é

fornecido aos alunos, que podem executá-lo em seu ambiente de

programação e servirá de apoio para o “desenvolvimento prático”, que

consiste no último bloco do arcabouço.

Page 22: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

22

Desenvolvimento Prático - Este bloco visa o desenvolvimento prático do

aluno através da solução para um ou mais problemas propostos. O bloco é

dividido em duas partes:

o Proposição – É feito o enunciado de um ou mais problemas que devem

ser diferentes do exemplo que foi apresentado no bloco

“desenvolvimento conceitual”. Evita-se, assim, a falsa sensação de

aprendizado, permitindo a consolidação do conhecimento acerca do

padrão em estudo.

o Extensão – Etapa que possibilita validar características de baixo

acoplamento e de reusabilidade da aplicação, propondo-se uma

modificação no enunciado proposto da parte anterior que deve ser

desenvolvido sem comprometer a estrutura proposta pelo padrão de

projetos em questão.

Figura 4 – Arcabouço para o estudo de padrões.

Na Figura 4, a estruturação seqüencial das seções de utilização do arcabouço é

apresentada pelas setas contínuas. Entretanto, usando-se as setas pontilhadas, procura-se

representar a não-linearidade do aprendizado, uma vez que, de qualquer ponto, pode-se

recorrer aos elementos constituintes das seções anteriores para auxiliar no desenvolvimento.

Note que, na estrutura apresentada na Figura 4, os blocos mais abaixo (em cinza) são

aqueles em que se desenvolve a prática laboratorial pelo aluno. Esses blocos representam dois

momentos particulares da aprendizagem de padrões de projeto. Nas próximas seções são

apresentados alguns padrões de projeto estruturados de acordo com o arcabouço proposto.

Embora os exemplos e os exercícios estejam sendo propostos em Java, o arcabouço proposto

Extensão

Apresentação

Descrição com Exemplo

Codificação do Exemplo

Proposição

Desenvolvimento conceitual

Desenvolvimento prático

Page 23: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

23

não faz nenhuma restrição em relação à linguagem de programação ou tecnologia a serem

utilizados.

2.4 Strategy

Apresentação

O Padrão Strategy define uma família de algoritmos que são encapsulados em objetos

independentes dos objetos para os quais os algoritmos foram efetivamente concebidos.

Encapsular comportamentos associados a objetos pertencentes a uma hierarquia de

classes permite que os algoritmos variem independentemente dos clientes que o utilizam [7].

Além disso, a estrutura proposta pelo padrão Strategy possibilita efetuar a modificação do

comportamento de um objeto em tempo de execução.

Descrição com Exemplo

Para apresentar este padrão, é utilizado aqui o exemplo encontrado em [11], em que o

contexto é um jogo de computadores cujas personagens são patos de diferentes tipos. Os patos

do jogo possuem um conjunto de atributos e comportamentos semelhantes, mas podem

apresentar algumas especificidades entre si. Exploram-se os comportamentos de nadar e

produzir sons. Inicialmente, utilizando técnicas de orientação a objetos, propõe-se a definição

da superclasse abstrata Duck e, a partir dela, os demais tipos de patos são criados. O diagrama

de classes mostrado na Figura 5(a) exemplifica a especialização de Duck para apenas duas

subclasses.

Figura 5 – Diagrama de Classes Inicial (UML) Strategy

Page 24: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

24

Supondo-se a necessidade de adicionar um novo comportamento para patos existentes

ou para novos patos que sejam agregados ao jogo, percebe-se que alguns deles podem voar.

Utilizando-de técnicas de orientação a objetos, propõe-se a criação do método fly() na

superclasse Duck, como mostra a Figura 5(b).

Figura 6 – Classes RubberDuck e WoodDuck

Entretanto, percebe-se que nem todos os patos podem voar. Por exemplo, patos de

borracha não voam. Uma alternativa inicial é sobrescrever o método fly() na classe dos patos

de borracha, RubberDuck, para modificar o seu comportamento em relação à ativação deste

método, como mostrado na Figura 6. Analisando-se a extensibilidade da solução, ao adicionar

outro tipo de pato, por exemplo, um pato de madeira, representado pela classe WoodDuck,

teremos que modificar novamente os métodos quack() e fly(), como mostrado na Figura 6.

Pode-se observar que essa solução possui várias desvantagens: (i) código duplicado entre

diferentes classes; (ii) alterações no comportamento em tempo de execução se tornam difíceis;

(iii) é difícil saber de antemão o comportamento de todos os patos.

Como generalizar o comportamento inserindo os métodos fly() e quack() na

superclasse Duck traz os problemas citados, explora-se outra alternativa com a utilização de

interfaces distintas para representar os dois comportamentos: Flyable e Quackable. Desse

modo, sugere-se que os patos que voam implementem a interface Flyable e,

consequentemente, o método fly(). Da mesma maneira, os patos que grasnam devem

implementar a interface Quackable e, consequentemente, o método quack(), como mostrado

no diagrama de classes da Figura 7. Embora, da perspectiva de um objeto, essa solução trate o

encapsulamento de uma maneira mais limpa, ela compromete a reutilização do código que

define cada um desses comportamentos. Imaginando um cenário em que diversos tipos de

pato apresentem o mesmo comportamento de voo, por exemplo, o mesmo código precisaria

ser replicado para todos os patos que o implementam. Além isso, uma alteração, mesmo que

pequena, no comportamento de vôo exigiria uma atualização em todas as classes que o

implementam, tornando a manutenção uma tarefa extremamente custosa e podendo gerar

inconsistência no sistema.

Page 25: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

25

Figura 7 – Classes RubberDuck

Para solucionar os problemas citados, propõe-se o padrão de projeto Strategy. A

solução, mostrada na Figura 8, é o encapsulamento dos comportamentos em objetos distintos,

que são agregados como atributo dos objetos que os utilizam. Isso é feito por meio da criação

de interfaces para representar cada comportamento, nesse caso as interfaces FlyBehavior e

QuackBehavior. A partir delas são criadas classes concretas que implementam cada

comportamento: FlyWithWings, FlyNoWay, Quack, Squeak e MuteQuack. Observa-se que na

classe Duck, agora, tem-se como atributo dois objetos, um do tipo QuackBehavior e outro do

tipo FlyBehavior, que serão responsáveis pela realização do comportamento específico. A

classe apresenta, dessa forma, os métodos performFly() e performQuack(), no lugar dos

métodos fly() e quack(), e setQuackBehavior() e setFlyBehavior(). Estes últimos permitem

configurar o comportamento de vôo para cada pato de forma dinâmica. Note que a mudança

de comportamento ao longo da interação com jogos eletrônicos é uma característica comum

às personagens dos mesmos. No contexto aqui explorado, um pato poderia, por exemplo,

adquirir como bônus a habilidade de voar logo após uma passagem de fase do jogo.

Page 26: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

26

Figura 8 – Diagrama de Classes Final (UML) Strategy

Codificação do Exemplo

Na Figura 9 temos a implementação da interface FlyBehavior e das classes concretas

FlyNoWay e FlyWithWings que implementam essa interface. Na Figura 10, temos a

implementação da outra interface, QuackBehavior, e das classes concretas Quack, Squeak e

MuteQuack que implementam essa interface.

Figura 9 – Classes FlyBehavior.java, FlyWithWings.java e FlyNoWay.java

Page 27: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

27

Figura 10 – Classes QuackBehavior.java, Quack.java, MuteQuack.java e Squeak.java

Na classe abstrata Duck, Figura 11, temos a implementação dos métodos

performQuack() e performFly(). Neles são executados os comportamentos de grasnar e voar,

respectivamente, chamados através dos objetos quackBehavior e flyBehavior. Note que o

comportamento que será executado dependerá da instância desses objetos. Os métodos

setQuackBehavior() e setFlyBehavior() também são implementados, permitindo a mudança

de comportamento em tempo de execução.

Page 28: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

28

Figura 11 – Classe Duck.java

Na Figura 12, temos as classes MallardDuck, WoodDuck, RedheadDuck e

RubberDuck que estendem a classe abstrata Duck. É importante observar que no construtor

dessas classes temos a instanciação dos objetos quackBehavior e flyBehavior, herdados da

classe Duck, de acordo com cada tipo de pato, o que estabelece a relação de agregação entre

os patos e os seus comportamentos. A agregação é “simples” visto que os objetos relativos

aos comportamentos persistem à eventual eliminação do pato que o utilize.

Page 29: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

29

Figura 12 – Classes MallardDuck.java, ReadheadDuck.java, WoodDuck.java e RubberDuck.java

Na Figura 13, temos uma pequena aplicação, classe Application, onde mostramos o

funcionamento das classes discutidas anteriormente.

Figura 13 – Classe Application.java

Proposição

Um Sistema de Controle de Produção Científica (SCPC), em desenvolvimento para

uma instituição de ensino, permite a organização de diferentes tipos de documentos, tais como

monografias, artigos, relatórios e estatísticas. Possuindo os diferentes documentos um

conjunto de características em comum, para diversas funcionalidades do sistema, eles são

tratados de maneira indistinta. Entretanto, algumas operações, embora comuns a todos os

tipos de documento, apresentam especificidades, como é o caso da operação de codificação.

Relatórios e estatísticas são codificados em HTML, para serem apresentadas na interface de

Page 30: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

30

navegadores Web, enquanto que artigos e monografias são codificados em PDF. Além disso,

alterando-se o modo de operação do sistema, deve ser possível codificar também em PDF os

documentos do tipo relatório e estatística.

A partir do problema apresentado, prospecte uma solução reutiliável que leve em

consideração a possibilidade de diferentes formas de condificação para todos os tipos de

documento, sem deixar de considerar suas semelhanças. Com base no padrão Strategy,

elabore um diagrama de classes capaz de abstrair todos os tipos de objetos envolvidos na

solução. Em seguida, implemente a solução modelada.

Lembre-se que a solução deve tratar tanto a especificidade do comportamento de

codificação para os diferentes tipos de documento como a dinâmica associada à alteração no

modo de operação para os documentos do tipo relatório e estatística.

Extensão

Uma modificação foi solicitada para o SCPC. Será preciso agora adicionar um outro

tipo de documento, o edital, e outro tipo de codificação, XML, visto que o sistema será

integrado ao sistema da Pró-Reitoria de Pós-Graduação. Modifique o diagrama de classes e a

implementação desenvolvidos para contemplar essas novas características no sistema.

Verifique se foi necessário modificar alguma das classes ou operações do modelo

original. Caso isso tenha acontecido, é possível que você não tenha desenvolvido o padrão

Strategy corretamente.

2.5 Abstract Factory

Apresentação

O padrão de projeto Abstract Factory tem por objetivo fornecer uma interface para

criação de famílias de objetos relacionados ou dependentes sem especificar suas classes

concretas [7]. Esse padrão permite que o sistema determine em tempo de execução qual

subclasse irá instanciar um objeto. Pois em determinadas aplicações a subclasse não é

conhecida durante o desenvolvimento ou simplesmente não se deseja especificar a subclasse.

Descrição com Exemplo

Tomando como exemplo a construção de um toolkit, que é um conjunto de

componentes básicos de interface gráfica com o usuário, por exemplo, botões, janelas, menus,

Page 31: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

31

entre outros, para uma aplicação que será executada pelo sistema operacional Windows.

Inicialmente, a solução modelada para este toolkit utiliza a classe Button para representar o

componente gráfico botão, que possui o método paint() que irá desenhá-lo na tela, mostrada

na Figura 14(a). A partir dela são criados todos os botões da aplicação, que são utilizados,

nesse exemplo, pela classe Application.java mostrada na Figura 14 (b).

Figura 14 – (a) Classes Button e Menu (b) Classe Application.java

Supondo agora que essa aplicação deverá ser executada também no sistema

operacional Linux, foi desenvolvido um novo diagrama de classes, mostrado na Figura 15(a).

Utilizando os conceitos de Orientação a Objetos a classe Button agora se tornou abstrata, e as

classes WinButton e LinuxButton estendem dela, onde cada uma dessas classes irá

implementar o método paint() que irá desenhar o componente de acordo com seu sistema

operacional.

Figura 15 – (a) Classes WinButton e LinuxButton (b) Classe Application.java

Page 32: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

32

Entretanto, utilizando essa solução, nota-se que as características de baixo

acoplamento e de reusabilidade da aplicação não são atendidas, pois em uma nova expansão

da aplicação para outro sistema operacional, teria-se que modificar novamente todas as partes

da aplicação onde os botões fossem criados, tornando a manutenção custosa e podendo gerar

inconsistências na aplicação.

Portanto, para que o toolkit da aplicação seja portátil para diferentes sistemas

operacionais, Windows ou Linux, é necessário que esses componentes não sejam codificados

exclusivamente para uma determinada interface gráfica, pois isso dificultaria a mudança de

uma interface para outra, com isso dificultando também a manutenção desse código.

Esse problema pode ser resolvido, utilizando o padrão de projeto Abstract Factory,

criando-se uma classe abstrata GUIFactory, mostrada na Figura 16, que será a classe base

para a criação dos componentes gráficos. Nessa classe serão definidos os métodos abstratos

para criação dos componentes, no nosso exemplo o método createButton(). Será também

nessa classe definido, através do método getFactory(), qual factory (fábrica em inglês),

WinFactory ou LinuxFactory, será utilizada para a criação de fato dos componentes. As

classes WinFactory e LinuxFactory são subclasses concretas da GUIFactory, são nessas

classes concretas que os componentes gráficos serão construídos de fato, através dos métodos

abstratos herdados da classe mãe, que serão implementados por elas, ou seja, a partir de agora

a criação dos componentes gráficos será de responsabilidade dessas duas classes concretas.

As classes que representam os componentes gráficos também serão criadas utilizando

a mesma ideia. No nosso exemplo, a classe abstrata Button possui o método abstrato paint().

A partir dessa classe serão criadas as suas subclasses, WinButton e LinuxButton, e nelas

implementados o método herdado paint().

Neste momento a criação de componentes gráfico torna-se transparente para a

aplicação, pois ela enxergará somente as classes GUIFactory e Button, como mostra o

diagrama de classes na Figura 16. Com isso o problema de portabilidade é resolvido sem

precisar modificar o código na aplicação que somente irá se preocupar com a criação dos

componentes, sem se preocupar em qual sistema operacional ela será executada. Internamente

será definido qual factory utilizar, WinFactory ou LinuxFactory, e, consequentemente, que

componentes criar, WinButton ou LinuxButton.

Page 33: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

33

Figura 16 – Diagrama de Classes (UML) Abstract Factory

Codificação do Exemplo

Na Figura 17 temos a implementação da classe GUIFactory. Note que no método

estático getFactory() na linha 7 é definido em qual sistema operacional a aplicação está

rodando em tempo de execução e dependendo dele será instanciado um objeto do tipo

WinFactory ou LinuxFactory. É criado também, como dito anteriormente, o método abstrato

createButton(), que será implementado pelas suas subclasses para criar o componente gráfico

botão.

Page 34: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

34

Figura 17 – Classe GUIFactory.java I

As classes WinFactory e LinuxFactory estendem de GUIFactory, Figura 18. Note que

o método abstrato createButton() é implementado e dependendo da classe ele irá retornar um

objeto do tipo WinButton ou LinuxButton.

Figura 18 – Classes WinFactory.java e LinuxFactory.java

A classe abstrata Button, Figura 19, é criada com o método abstrato paint(), que

deverá ser implementada pelas suas subclasses concretas.

Figura 19 – Classe Button.java

Page 35: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

35

WinButton e LinuxButton, Figura 20, são as classes concretas que herdam de Button.

Nelas será definido como o botão será criado de fato, dependendo do sistema operacional,

através da implementação do método paint().

Figura 20 – Classes WinButton.java e LinuxButton.java

Note que na aplicação, aqui representada pela classe Application, mostrada na Figura

21, utiliza-se somente as classes GUIFactory e Button, que são as classes bases para a criação

dos componentes gráficos. Na linha 7 obtém-se o objeto factory através do método

GUIFactory.getFactory(), dessa forma vê-se que, para a aplicação, é transparente se esse

método irá retornar um objeto do tipo WinFactory ou LinuxFactory. Na linha 8, o objeto

button recebe um objeto através da chamada método factory.createButton() e posteriormente,

na linha 9, temos a chamada do método button.paint(). Note, mais uma vez, que para a

aplicação o tipo de botão que será criado é indiferente, bem como a forma como esse botão

vai ser desenhado na tela. Desse modo a aplicação não precisa se preocupar em qual sistema

operacional ela será executada, facilitando o seu desenvolvimento.

Page 36: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

36

Figura 21 – Classes Application.java

É importante notar que ao surgir uma necessidade de expandir essa aplicação para

outro sistema operacional, por exemplo o Lion da Apple, não se faz necessário grandes

mudanças. Primeiramente iremos criar a classes LionFactory e LionButton, herdando de

GUIFactory e Button, respectivamente. Por fim, modificaríamos apenas o método

getFactory() da classe GUIFactory, como mostrado na Figura 22, mudança essa que não

impacta em nenhuma das classes previamente implementadas, principalmente na aplicação.

Figura 22 – Classe GUIFactory.java II

Page 37: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

37

Proposição

Uma montadora de veículos está desenvolvendo um sistema para auxiliar sua linha de

montagem. Esse sistema será responsável pelo controle completo da montagem dos veículos

dessa montadora, desde o controle de estoque das peças que serão utilizadas até a montagem

das peças no veículo.

Sabe-se que cada modelo de veículo tem sua própria linha de montagem. Pois, apesar

de alguns modelos compartilharem algumas peças comuns, a montagem e grande parte das

peças são diferentes.

Inicialmente, a montadora quer que o sistema funcione para dois modelos de carro,

modelo X e modelo Y, a partir do qual serão feitos testes e será decidido pelos sócios se o

sistema será implantado para outros modelos ou não. Desenvolva, a partir do problema

descrito, uma solução para esse sistema, tendo como foco o baixo acoplamento e a

reusabilidade. Utilizando o padrão Abstract Factory elabora o diagrama de classes e

implemente a solução modelada.

Extensão

Após inúmeros testes a montadora aprovou o sistema de linha de montagem

desenvolvido, para os modelos de carro X e Y. Agora ela quer que a linha de montagem de

seu mais novo carro, modelo Z, também seja controlada por esse sistema. Modifique o

diagrama de classes e a implementação desenvolvidas para contemplar essa modificação.

Analise onde as modificações foram realizadas, se foi preciso modificar alguma das

classes implementadas ou as operações do sistema anterior, pois, em caso afirmativo, é

possível que o padrão Abstract Factory não tenha sido desenvolvido corretamente.

2.6 Composite

Apresentação

O padrão de projeto Composite consiste na criação de uma estrutura em árvore para

compor objetos utilizando componentes em estruturas hierárquicas. Cada um desses

componentes implementa uma mesma interface ou estende uma mesma superclasse. Esse

padrão permite que o cliente utilize esses componentes e a composição desses componentes

de forma uniforme.

Page 38: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

38

Descrição com Exemplo

De acordo com [7] o desenvolvimento de interfaces gráficas fazem com que os

desenvolvedores construam diagramas complexos a partir de componentes gráficos simples.

O desenvolvedor pode agrupar um grupo de componentes para formar uma componente

maior, que por sua vez será utilizado para formar um outro componente ainda maior e assim

sucessivamente. Uma simples implementação seria a definição de classes de componentes

gráficos primitivos como Texto e Linha e de classes que funcionariam como containers para

essas classes primitivas, por exemplo Imagem.

Entretanto, o código utilizando essa abordagem teria que tratar as classes primitivas e

containers de forma diferente, embora na maioria das vezes elas tenham comportamentos

muito semelhantes. Fazer essa distinção faz com que o código se torne mais complexo na

medida que a aplicação cresce. Nesse contexto o padrão Composite propõe uma solução

recursiva para que os desenvolvedores não precisem fazer essa distinção.

Esse padrão tem como principal característica uma classe abstrata que representa tanto

o tipo primitivo como também o container, que é formado por um ou mais objetos do tipo

primitivo. Essa classe irá conter as características do objeto individual e as operações que a

composição desses objetos possuem. Desse modo o desenvolvedor não irá se preocupar com

as diferenças entre as composições e os objetos individuais, passando a tratar cada um deles

uniformemente.

Na Figura 23 temos o diagrama de classe utilizando o padrão de projeto em questão,

tomando como exemplo a construção de interfaces gráficas. Note que a classe abstrata

ComponenteGrafico representa os objetos individuais, como Linha e Texto, e a composição

desses objetos, nesse exemplo representado pela classe Imagem.

Observe que as classes Linha e Texto, apesar de serem subclasses da

ComponenteGrafico, não implementam os métodos relacionados a composição de objetos, já

que são classes primitivas e não são compostas por outros objetos. Essas classes só

implementam o método desenhar, que é característico da classe primitiva.

A classe Imagem, que representa a composição de objetos gráficos, por sua vez

implementa o método desenhar de forma que esse execute o método desenhar de cada um dos

objetos gráficos que o compõem. Implementam-se também os métodos que relacionam a

composição desses objetos como Adicionar e Remover.

Page 39: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

39

Figura 23 – Diagrama de Classes (UML) Composite

Codificação do Exemplo

Está implementado em Java o exemplo discutido acima de forma simplificada. A

classe ComponenteGrafico é abstrata e possui 4 métodos que deverão ser implementados

pelas suas subclasses. Essa classe representa tanto os objetos primitivos quanto a composição

deles.

Figura 24 – Classe ComponenteGrafico.java

As classes Linha e Texto são as classes primitivas que herdam de ComponenteGrafico.

Essas classes implementam o método desenhar de acordo com o tipo do componente gráfico.

Os outros métodos herdados da superclasse são implementados de forma a não executarem

nenhuma ação significativa por não fazerem sentido para elas.

Page 40: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

40

Figura 25 – Classes Linha.java e Texto.java

A classe Imagem, que também herda de ComponenteGrafico, implementa os métodos

adicionar, remover e getChild, já que ela é uma classe que é formada a partir da composição

de vários objetos do tipo ComponenteGrafico, inclusive dela mesma. Note que nessa classe

temos um atributo que não existe nas outras classes, uma lista de objetos do tipo

ComponenteGrafico. Essa lista simboliza a composição desse objeto a partir de outros

objetos, isso fica melhor entendido quando observamos a implementação do método

desenhar. Ao executar esse método ele irá chamar o método desenhar de cada um dos objetos

que o compõem, desse modo o conjunto dos objetos desenhados formam o objeto da classe

Imagem.

Page 41: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

41

Figura 26 – Classe Imagem.java

Proposição

Um engenheiro de software está criando uma nova linguagem de programação, para

isso ele terá que definir uma gramática com os comandos que serão utilizados nessa nova

linguagem. Faça o diagrama de classes para representar os comandos dessa linguagem da

melhor forma possível utilizando o padrão discutido.

Dica: divida os comandos da gramática em comandos simples e comandos compostos.

Extensão

Após feito o diagrama de classes no exemplo proposto, deseja-se adicionar dois novos

comandos, um simple e um composto. Modifique o diagrama de classes para contemplar os

novos comandos a serem implementados.

Page 42: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

42

2.7 Padrões de Projeto em Construção

No Apêndice deste trabalho estão descritos mais três padrões de projeto que ainda se

encontram em construção no formato do arcabouço proposto. Esses padrões são: Facade, no

apêndice A; Singleton, no apêndice B; e o Iterator, no apêndice C.

Page 43: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

43

3. A Gênese do Arcabouço Proposto

Embora o arcabouço proposto neste trabalho não tenha ainda sido utilizado na prática

em um curso de Programação Orientada a Objetos, sua concepção é fruto de um estudo

teórico e da análise dos resultados da aplicação de uma atividade prática sobre Padrões de

Projetos em duas disciplinas de Engenharia de Software no Departamento de Engenharia de

Teleinformática da Universidade Federal do Ceará. Uma das disciplinas foi ministrada no

curso de graduação e a outra no curso de pós-graduação (neste último caso, em forma de

Estudos Especiais).

Ao longo do semestre, o professor da disciplina inferiu que a maioria dos alunos

possuíam sérias dificuldades conceituais em OO, especialmente em relação ao uso de

interfaces e na aplicação do polimorfismo. Essa dificuldade comprometeu de maneira

substancial o processo de aprendizagem de alguns conteúdos da disciplina, como a UML,

tendo sido revelada a partir de atividades de concepção de diagramas de classe e de sequência

em um dos trabalhos propostos na disciplina. Nesse sentido, faz-se em seguida um breve

relato do desenvolvimento do curso de Engenharia de Software no semestre letivo 2012-1,

registrando-se algumas observações e percepções identificadas pelo professor ou retiradas das

avaliações que foram realizadas ao final de cada atividade pelos alunos.

As duas disciplinas, de graduação e pós-graduação, foram contextualizadas sobre um

mesmo problema-base, o qual foi trabalhado ao longo de todo o semestre letivo. Várias

atividades foram propostas com base na metodologia PBL (Problem Based Learning),

fazendo-se algumas adaptações em termo de estruturação e de orientação para compatibilizar

a metodologia à realidade dos alunos (e do próprio professor), visto que possuíam pouco ou

nenhum contato com esse tipo de abordagem. As primeiras atividades foram relativamente

orientadas para a Análise e Projeto Orientados a Objeto (APOO). Já na segunda atividade,

trabalhou-se com os principais casos de uso identificados para o problema base. Solicitou-se

aos alunos que fizessem, para cada um dos principais casos de uso identificados, a abstração

dos objetos do domínio do negócio com ele comprometidos. Em seguida, pediu-se a

elaboração, também para cada caso de uso, de um diagrama de sequência que representasse o

desenvolvimento da solução do mesmo. Para isso, após rápida definição dos conceitos de

objetos de entidade, de controle e de fronteira, sugeriu-se a abstração de outros tipos de objeto

(no domínio da solução) que auxiliassem a implementação do caso de uso, o que, em um

sistema OO, se dá através da interação, ou comunicação, entre objetos.

Page 44: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

44

A atividade foi realizada em grupo, como sugere a PBL. Os alunos manifestaram

grande dificuldade em seu desenvolvimento, o que foi, inicialmente, percebido pelo professor

como uma dificuldade relacionada com a metodologia. Entretanto, a partir das apresentações

e discussões realizadas em sala de aula, notou-se uma limitação particular em lidar com

soluções orientadas a objeto. Para os alunos de graduação, essa situação foi percebida com

alguma surpresa, visto que, na grade curricular do curso de Engenharia de Teleinformática,

existe uma disciplina semestral especificamente voltada para a Orientação a Objetos

(Técnicas de Programação para Engenharias II). No caso da pós-graduação, existe uma

heterogeneidade natural, devido ao fato de os alunos serem egressos de diversos cursos,

alguns não tendo tido qualquer tipo de formação em Orientação a Objetos.

A partir das percepções relatadas anteriormente, e tendo em perspectiva o avanço da

disciplina com incursões em Projeto (design) OO, com definição da arquitetura do sistema,

componentização, especificação das interfaces entre os componentes, entre outros aspectos

que dependem de um backgroud razoavelmente consistente em OO, foi preciso estabelecer

novos parâmetros para o aprendizado de Engenharia de Software. Em especial, percebeu-se

que seria praticamente inútil trabalhar Padrões de Projeto, que fazem parte do programa da

disciplina, sem o devido amadurecimento de conceitos de OO.

Figura 27 – Enunciado da Atividade sobre Design Patterns

Desenvolva um estudo sobre padrões de projetos e, para cada padrão definido para o seu grupo, registre

seus estudos em uma documentação contendo:

1. A apresentação do estudo sobre o padrão

2. Uma possível aplicação do padrão estudado no sistema “Máquinas de Alimentos em Redes” sobre

o qual vem sendo contextualizadas as nossas atividades. Na apresentação da aplicação, desenvolva:

2.1. o diagrama de classes para a situação-exemplo;

2.2. a implementação de teste com uma linguagem Orientada a Objetos (não precisa ser uma

aplicação completa, basta ser uma simulação de uso para as classes que compõem a

implementação do padrão!).

3. Observações:

3.1. Caso não consiga identificar uma aplicação no sistema que vem sendo trabalhado, exemplifique

o uso do padrão em um outro contexto.

3.2. Sugere-se a geração do código a partir do diagrama de classes concebido, usando, para isso,

uma ferramenta CASE (EA, Astah, Umbrello, etc.), além da complementação do código com o

desenvolvimento dos métodos especificados.

Lista de padrões a serem estudados por grupo (podendo ser estendida, caso o grupo deseje):

Grupo A - ADAPTER, OBSERVER, PROXY, COMMAND, BRIDGE, DECORATOR

Grupo B – ADAPTER, OBSERVER, PROXY, COMMAND, FACADE, TEMPLATE

Grupo C – ADAPTER, OBSERVER, PROXY, COMMAND, ITERATOR, COMPOSITE

Grupo D – ADAPTER, OBSERVER, PROXY, COMMAND, FACTORY, STRATEGY

Grupo E – ADAPTER, OBSERVER, PROXY, COMMAND, ITERATOR, STATE

Grupo F – OBSERVER, COMMAND, COMPOSITE (individual)

Page 45: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

45

Assim, foi proposta uma atividade sobre Padrões de Projeto na disciplina de

Engenharia de Software que está na gênese do arcabouço formalizado neste trabalho de

conclusão de curso. O enunciado desta atividade encontra-se do quadro da Figura 27.

Durante a concepção desta atividade, considerou-se a possibilidade de reconstrução

dos conceitos fundamentais de Orientação a Objetos, pedindo-se, não só a modelagem de

situações de uso dos padrões de projeto, mas também a implementação da solução usando

uma linguagem OO.

A atividade foi desenvolvida em dupla. A quantidade de padrões solicitada por grupo

exigia que todos os componentes realizassem atividades de modelagem e programação,

inviabilizando o acúmulo da atividade de programação para um único aluno por dupla.

Alguns padrões foram desenvolvidos por todos os grupos visando a discussão e a comparação

das soluções em sala de aula.

Os resultados dessa atividade foram bastante significativos. Além da documentação

solicitada, associada aos estudos sobre o padrão, incluindo a codificação de uma situação

exemplo, pediu-se a apresentação do diagrama de classes em sala de aula, a explicação da

solução e a demonstração do seu uso. Durante as apresentações, tanto no curso de graduação

como no de pós-graduação, verificou-se que algumas soluções desenvolvidas resolviam o

problema ao qual se propunham, mas não se aplicavam corretamente ao padrão. Em geral, a

verificação da inconsistência era feita quando se solicitava a extensão da solução para

verificar a reusabilidade do padrão. Apesar do estresse inicial dos alunos, visto que as

modificações eram feitas “ao vivo”, com projeção do desktop do computador usado no

quadro, a atividade e a discussão se mostrou altamente produtiva e didática, reforçando os

conceitos de OO e mostrando o alto grau de reusabilidade e baixo acoplamento propiciado

pelos padrões de projeto.

A partir dessa observação, foram estruturados os blocos do arcabouço proposto neste

trabalho, que estão representados na Figura 4. Fruto das experiências relatadas no parágrafo

anterior, a ênfase é dada para o último bloco do arcabouço, relativo ao desenvolvimento

prático, onde na primeira parte é desenvolvido uma solução para um problema proposto,

enquanto na segunda parte valida-se a primeira, demonstrando a extensibilidade provida pelo

padrão.

Outro aspecto que apresentou uma particular dificuldade para o desenvolvimento da

atividade de padrões de projeto, que foi registrado entre os alunos de engenharia de software

nos dois cursos, foi a necessidade de encontrar a aplicabilidade do padrão de projeto em

Page 46: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

46

estudo para o sistema sobre o qual se desenvolviam as atividades da disciplina. Esse tipo de

dificuldade pode comprometer o tempo do aluno e retirar o foco de seu aprendizado da

programação Orientada a Objetos. Assim, tendo em vista a sua aplicação em disciplinas de

programação, e não em disciplinas de engenharia de software, estabeleceu-se que o arcabouço

deve enunciar diretamente uma situação problema apropriada ao uso do padrão.

Ao final da atividade, foi solicitado aos alunos do curso de graduação que

preenchessem um formulário de avaliação. As questões eram avaliadas pelos alunos usando

uma escala de representação variando de A (nota máxima) a E (nota mínima), ou X (não se

aplica). Dentre outros aspectos menos relevantes para este trabalho, as quatro perguntas

abaixo foram colocadas:

1) Como você avalia os seus CONHECIMENTOS SOBRE ORIENTAÇÃO A

OBJETOS ANTES DO DESENVOLMENTO DESTA atividade?

2) Como você avalia os seus CONHECIMENTOS SOBRE ORIENTAÇÃO A

OBJETOS DEPOIS DO DESENVOLMENTO DESTA atividade?

3) Após a realização do trabalho, como você avalia a sua ABSORÇÃO DO

CONTEÚDO “DESIGN PATTERNS”?

4) Caso você venha a trabalhar ou trabalhe com desenvolvimento de software,

como você avalia a contribuição dessa atividade NA SUA VIDA

PROFISSIONAL?

A fim de computar as médias das respostas, os conceitos associados atribuídos pelos

alunos foram substituídos por valores numéricos da seguinte maneira: A-10, B-8, C-6, D-4, E-

2 e X-0.

A Tabela 1 resume as médias das avaliações realizadas pelos onze alunos da turma de

graduação:

Tabela 1– Avaliação média dos alunos da turma de graduação para a atividade sobre padrões de projeto

na disciplina de Engenharia de Software (2012-1)

Questão Média

1 6,6

2 8,6

3 7,8

4 8,8

Page 47: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

47

Pelas médias apresentadas nas questões 1 e 2, respectivamente 6,6 e 8,6, percebe-se

que os alunos experimentaram um significativo aumento na sensação de aprendizado sobre o

conteúdo OO após a realização da atividade que durou por volta de três semanas. Essa

sensação foi observada também pelo professor em função do desempenho e da confiança

demonstrada pelos alunos durante a apresentação das soluções relativas à atividade.

Entretanto, no que concerne o aprendizado de padrões de projeto, foi registrada uma absorção

menor dos conceitos, revelado pela média 7,8 para a pergunta 3. Isso foi reforçado por

algumas observações escritas pelos alunos nos formulários das avaliações (em espaços

destinados a comentários livres) e em algumas manifestações verbais. Os comentários

convergiam para o fato de que seria necessário um tempo maior para trabalhar

satisfatoriamente com todos os padrões propostos, o que seria praticamente inviável em uma

disciplina de 4 créditos. Essa característica parece endossar a necessidade de uma dedicação

maior aos padrões de projeto no contexto de disciplinas de programação, previamente ao

ensino de Engenharia de Software.

Por último, a média da pergunta 4 mostra que os alunos da graduação que cursaram a

disciplina têm em perspectiva que o aprendizado de padrões de projeto possui importância

significativa em seu futuro profissional. É importante relatar que apenas um ou dois dos

alunos dessa turma apresentam uma perspectiva profissional mais voltada para a área de

hardware, o que pode ter influenciado para menos a média dessa questão.

A análise exposta neste capítulo fundamenta, assim, o arcabouço proposto, embora se

tenha consciência da necessidade de experimentações e readequações sucessivas a partir do

momento em que ele seja efetivamente empregado como ferramenta de apoio didático ao

processo de ensino e aprendizagem em disciplinas de programação.

Page 48: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

48

4. Considerações finais

Dada a importância da utilização de padrões de projeto na qualidade do software a ser

produzido, foi desenvolvido neste trabalho um arcabouço para servir de apoio ao aprendizado

em disciplinas de programação orientada a objetos. Esse arcabouço é constituído por cinco

elementos que descrevem o comportamento de cada padrão de projeto: apresentação,

descrição com exemplo, codificação do exemplo, proposição e extensão.

Esse trabalho selecionou um conjunto de padrões que são julgados importantes e para

cada um deles descreve o que tem de mais importante na literatura [5], [7], [8], [11], [17],

sempre com foco na didática de ensino. Para cada padrão de projeto mostra-se em quais

aplicações ele é utilizado e destaca-se um problema em específico, tomando-o como exemplo,

que seja mais conveniente para facilitar o entendimento da solução que o padrão fornece. A

partir desse exemplo é criado o diagrama de classes da solução. O exemplo também é

implementado em Java para demonstrar o comportamento do padrão. Por fim, é apresentado

um exercício proposto e uma extensão do mesmo com o objetivo de fixar o entendimento do

padrão de projeto em questão.

O arcabouço possui duas seções principais no aprendizado de padrões de projeto,

“Proposição” e “Extensão”. Nessas seções são colocados problemas com o objetivo de prover

um melhor entendimento, na prática, do padrão de projeto, mostrando sua utilidade e sua

versatilidade na evolução e modificação da aplicação. Contudo, a elaboração de problemas

que sejam didáticos e que abordem o padrão na melhor forma possível não é uma tarefa fácil,

visto que é necessário que haja experiência em sala de aula notando as dificuldades e

deficiências dos alunos. Dessa forma, é necessário que haja uma utilização na prática do

arcabouço, tendo como propósito sua evolução de acordo com as dificuldades que forem

surgindo.

Apesar de o arcabouço proposto ainda não ter sido utilizado na prática em uma

disciplina de programação orientada a objetos, através de um estudo teórico e da análise de

uma atividade sobre padrões de projeto em duas disciplinas no Departamento de Engenharia

de Teleinformática da UFC, sendo uma na graduação e outra na pós-graduação, pode-se

inferir que as dificuldades conceituais em Orientação a Objetos, em especial no uso de

interfaces e de polimorfismo para solução de problemas, comprometeu substancialmente o

processo de aprendizagem. Percebeu-se que seria praticamente inútil trabalhar Padrões de

Page 49: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

49

Projeto sem o devido amadurecimento de conceitos de OO. Desse modo, justifica-se incluir,

de maneira objetiva, o estudo sobre padrões de projeto já em disciplinas de programação

orientada a objetos, visto que eles podem ser vistos como técnicas avançadas e consolidadas

de programação.

A utilização deste trabalho em disciplinas de programação orientada a objetos torna o

aprendizado de padrões de projeto mais eficaz, já que a teoria é vista de forma mais próxima

da prática, por ter exercícios para a melhor compreensão do padrão, e mais objetiva, pois,

diferente de alguns livros, onde há, por vezes, exaustão de informações desnecessárias, neste

trabalho o padrão é visto tendo como foco a solução para o problema apresentado.

Page 50: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

50

5. Referências Bibliográficas

[1] IEEE. Institute of Eletrical and Eletronics Engineers. Disponível em

<http://www.ieee.org>. Último acesso em 15 de maio de 2012.

[2] SOMMERVILLE, I. Engenharia de software. 8ª Edição. São Paulo: Pearson/Prentice

Hall, 2007. 522 p.

[3] ABNT (Associação Brasileira de Normas Técnicas). NBR ISO 9000/2005: Sistema de

Gestão da Qualidade - Fundamentos e Vocabulário. Rio de janeiro, 2005.

[4] PRESSMAN, R. S. Engenharia de software. 6ª Edição. São Paulo: McGraw-Hill, 2006.

720 p.

[5] Bruegge, B; Dutoit, A. H. Object-Oriented Software Engineering: Using UML, Patterns

and Java. 2nd Ed. Prentice Hall, 2003. 800 p.

[6] Alexander, C; Ishikawa, S; Silverstein, M; Jacobson, M; Fiksdahl-King, I; Angel, S. A

Pattern Language. Oxford University Press, NewYork, 1977.

[7] GAMMA, E; HELM, R; JOHNSON, R; VLISSIDES, J. Design Patterns - Elements of

Reusable Object-Oriented Software. 1a Edição. Addison-Wesley, 1995. 395p.

[8] DEITEL, H. M; DEITEL, P. J. Java: Como programar. 6ª Edição. São Paulo:Pearson,

2006. 1110 p.

[9] Sierra, K; Bates, B. SCJP Sun Certified Programmer for Java 6 Study Guide (Exam

310-065). McGraw-Hill, 2008.

[10] Liskov, B.H; Wing J.M. Behavioral Subtyping Using Invariants and Constraints.

Formal Methods for Distributed Processing, an Object Oriented Approach, Howard

Bowman and John Derrick, editors, Cambridge University Press, 2001, pp. 254-280.

[11] Freeman, E; Freeman, E; Sierra, K; Bates, B. Head First: Design Patterns. 1st Ed.

O'Reilly Media, 2004.

[12] ECLIPSE FOUNDATION. Eclipse Helios. Disponível em <http://www.eclipse.org>.

Último acesso em 30 de maio de 2012.

[13] KOSCIANKI, A; SOARES, M. S. Qualidade de software. 2ª Edição. São

Paulo:Novatec, 2007. 395 p.

[14] SERSON, R. R. A Bíblia: Certificação JAVA 6. Rio de Janeiro: Brasport, 2009.

Page 51: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

51

[15] Dicionário Web. Disponível em <http://www.dicionarioweb.com.br>. Último acesso em

10 de junho de 2012.

[16] THAYER, R. H; CHRISTENSEN, M. J. Software engineering. 3rd Ed. Hoboken, NJ:

IEEE Computer Society, 2005.

[17] SHALLOWAY, A; TROTT, J. R. Explicando padrões de projeto: uma nova perspectiva

em projeto orientado a objeto. Porto Alegre: Bookman, 2004.

Page 52: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

52

6. Apêndice

6.1. Apêndice A - Facade

Apresentação

O padrão de projeto Facade, fachada em francês, é um padrão do tipo estrutural e tem

por objetivo fornecer uma interface unificada que simplifique o entendimento e a utilização de

um subsistema mais complexo.

Descrição com Exemplo

Em algumas aplicações para um processo ser realizado é necessário que um conjunto

de ações em diferentes classes sejam executadas, a esse conjunto de classes chamamos de

subsistema. Dependendo da aplicação, esse subsistema pode se tornar bem complexo, isso

fará com que o uso e o entendimento dele se torne complexo. Com o propósito de simplificá-

lo é criado uma classe de fachada que irá conhecer as funções desse subsistema e irá fornecer

para a aplicação uma interface simplificada dos processos realizados por ele.

Ao ligar um carro, por exemplo, existem vários processos que ocorrem que não

conhecemos bem ao certo, mas que precisam ser executados para o carro ligar corretamente.

Esse comportamento é a base do padrão de projeto Façade, onde um objeto (chamado de

objeto fachada) fornece uma interface simples para um subsistema mais complexo. Nesse

caso o objeto carro é o nosso objeto fachada para o subsistema veículo. Exemplificando de

forma simplificada temos as classes Motor, Farol, Porta e Radio que fazem parte do

subsistema veículo. Ao ligar o carro o motor liga, o farol ascende, a porta tranca e o radio

liga. Ao desligar o carro o motor desliga, o farol apaga, a porta destranca e o radio desliga.

Nota-se que ao ligar e desligar o carro vários processos ocorrem, porém de forma transparente

para o cliente, ou seja, ele não precisa saber exatamente o que está por trás do processo ligar

ou desligar o carro, pois através desse padrão esses processos serão controlados pelo objeto

fachada.

Page 53: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

53

Figura 28 – Diagrama de Classes (UML) Facade

Através da estrutura mostrada na Figura 28 é possível observar que a aplicação

enxerga o objeto fachada, e através dele e de suas operações acessa os processos do

subsistema. Esse padrão apesar de fornecer uma interface que simplifica o uso e o

entendimento de um subsistema, não impede que a aplicação utilize as classes desse

subsistema diretamente.

Page 54: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

54

Codificação do Exemplo

Figura 29 – Classes Motor.java, Porta.java, Farol.java e Radio.java

As classes apresentadas na Figura 29 são classes do subsistema em questão. Note que

sem uma classe fachada a aplicação precisaria, ao ligar e desligar o carro, chamar cada um

dos métodos de cada uma das classes do subsistema.

Page 55: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

55

Figura 30 – Classe CarroFacade.java

A classe CarroFacade, Figura 30, nossa classe fachada, faria o papel de simplificador

dos processos relacionados ao subsistema, nesse caso ligar e desligar o carro. Desse modo,

como dito anteriormente, a aplicação não precisaria se preocupar com cada um dos processos

internos, e sim com os processos que realmente são relevantes para ela: ligar e desligar o

carro.

Proposição

O sistema de uma loja virtual recebe dados de um cliente através de um formulário

que contém informações de usuário e do cartão de crédito. Após receber os dados, as entradas

são validadas e gravadas em um lugar apropriado. Utilize o padrão Facade para diminuir o

acoplamento entre os componentes, reduzindo as dependências entre eles. Na Figura 31

mostra-se o diagrama de classes do exemplo em questão.

Page 56: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

56

Figura 31 – Exercício Proposto Facade

Extensão

No sistema do exercício acima, é necessário que seja adicionado ao formulário o

endereço do cliente, modifique o diagrama de classes e a implementação, explicitando onde se

dariam as modificações.

6.2. Apêndice B - Singleton

Apresentação

Assegurar que uma classe tenha somente uma única instância. Após a instanciação

desse objeto, não será mais permitido a criação de objetos adicionais dessa mesma classe.

Descrição com Exemplo

Existem aplicações que requerem que somente uma instância de uma classe seja

criada. Por exemplo, alguns sistemas se conectam a um banco de dados utilizando apenas uma

instância que gerencia a conexão, evitando que sejam desperdiçados recursos ou que se

incorra em erros. Outra exemplo é a utilização de arquivo de log, onde uma única instância

seja responsável pelo acesso a esse arquivo, evitando inconsistências nas informações

registradas.

Na API padrão do Java, por exemplo, são raros os exemplos que utilizam o padrão

Singleton, mas podemos encontrá-los em locais onde a JSE (Java Standard Edition) precisa

utilizar os recursos do SO (Sistema Operacional) ou da JVM (Java Virtual machine). A classe

Runtime é um bom exemplo, requerendo a existência de um único objeto que represente o

ambiente em que a aplicação está executando.

Page 57: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

57

Figura 32 – Diagrama de Classes (UML) Singleton

Codificação do Exemplo

O padrão de projeto Singleton, como dito acima, garante que um sistema instancie no

máximo um e somente um objeto de uma classe. No exemplo abaixo, demonstra-se como é

feita a implementação desse padrão em Java.

Na linha 3 temos a declaração da classe Singleton com o modificador final,

objetivando a não criação de subclasses o que poderia fornecer outras instâncias de objetos da

mesma hierarquia, ferindo o objetivo principal do padrão. Na linha 8 declaramos o construtor

da classe Singleton como private. Esse construtor caracteriza o padrão de projeto Singleton,

pois, a partir dele, mostramos que somente a classe Singleton pode instanciar um objeto

Singleton. Juntamente com o construtor privado é criada uma referência private, encapsulando

a referência ao objeto único, e static, que garante a existência de uma única referência ao

objeto Singleton, declarado como singleObject, na linha 5. Na linha 13 é declarado o método

getInstance() que retornará aos clientes a instância única da classe. Nesse método é

instanciado o objeto singleObject de Singleton, caso ele ainda não exista. Nele é também

utilizado o modificador synchronized para impedir a execução simultânea deste método em

eventuais requisições.

Page 58: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

58

Figura 33 – Classe Singleton.java

A classe Main.java utiliza a classe Singleton.java para exemplificar o funcionamento

desse padrão de projeto. Nessa classe podemos notar que realmente temos um e somente um

objeto instanciado do tipo Singleton, e que qualquer modificação feito nele será refletido em

todas as classes que o utilizam.

Page 59: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

59

Figura 34 – Classe Main.java

Proposição

Precisa-se desenvolver um simulador de um processador, que possui apenas um núcleo

de processamento, que será utilizado para testar algoritmos de escalonamento. Nesse projeto

será utilizado um único objeto para representar esse único núcleo de processamento, onde as

aplicações irão utilizá-lo para executar suas tarefas. Implemente a classe CPU de forma a

garantir a integridade da execução de dados, utilizando o padrão Singleton.

Extensão

A partir do exercício anterior, implemente duas classes que representem duas

aplicações distintas que irão utilizar o microprocessador em questão.

6.2. Apêndice C - Iterator

Apresentação

Prover uma forma de acessar objetos pertencentes a uma estrutura de dados sem saber

exatamente como ela é representada, ou seja, sem conhecer como essa estrutura acessa seus

dados ou mesmo como ela os organiza.

Page 60: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

60

Descrição com Exemplo

Estruturas de dados, como por exemplo arrays, listas, pilhas e filas, são largamente

utilizados no desenvolvimento de software para organizar os dados de um programa. Agora

imagine que o desenvolvedor tenha que percorrer os objetos pertencentes a dois ou mais tipos

de estruturas de dados. Para fazer isso ele terá que saber com qual estrutura de dados ele está

mexendo, entretanto se isso não for possível ele não poderá fazê-lo.

O padrão de projeto Iterator é uma solução para o problema descrito acima. Esse

padrão propõe a criação de uma classe que irá percorrer os objetos da estrutura de dados de

forma transparente, ou seja, sem precisar conhecer exatamente como os dados estão

organizados e qual o comportamento da estrutura de dados.

Na diagrama de classes mostrado na Figura 35 temos a classe que representa a

estrutura de dados Estrutura, que é uma classe abstrata, nela existe o método que será

implementado pelas suas subclasses concretas criarIterador(), nesse método será criado um

objeto que será usado para percorrer a estrutura. No exemplo abaixo, temos as classes Fila e

Lista como as subclasses concretas da classe Estrutura. Note que na implementação do

método criarIterador() cada uma das classes Fila e Lista irá retornar um objeto diferente.

Para representar a classe que irá percorrer os objetos da estrutura de dados, foi criada

uma classe abstrata Iterador que possui métodos que irão ser implementados pelas suas

subclasses concretas IteradorFila e IteradorLista. Esses métodos serão implementados de

acordo com a estrutura de dados irão percorrer, porém para o usuário isso é transparente, ele

só irá enxergar os métodos first(), next() e hasNext().

Page 61: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

61

Figura 35 – Diagrama de Classes (UML) Iterator

Codificação do Exemplo

Na Figura 36 temos a implementação em Java do exemplo discutido. Temos as classes

abstratas Estrutura, que representa as diferentes estruturas de dados, e Iterador, que

representa a classe responsável por percorrer os objetos da estrutura de dados.

Figura 36 – Classes Estrutura.java e Iterador.java

As classes concretas Fila e Lista são subclasses de Estrutura, e implementam o

método criarIterador(). Esse método irá retornar o objeto que irá percorrer os objetos que

estão que estão na estrutura. Na classe Fila o método irá retornar um objeto do tipo

IteradorFila e na classe Lista esse método irá retornar um objeto do tipo IteradorLista.

Page 62: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

62

Figura 37 – Classes Fila.java e Lista.java

As classes concretas IteradorLista e IteradorFila, são subclasses de Iterador. Elas

implementam os métodos definidos pela sua superclasse de acordo com a estrutura de dados

que elas irão percorrer.

Page 63: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

63

Figura 38 – Classes IteradorLista.java e IteradorFila.java

Na classe Aplicacao, Figura 39, temos um exemplo utilizando as classes mostrada na

Figura 38. Nas linhas 7 e 8 instanciam-se dois objetos, uma lista e uma fila, e nas linhas 11 e

12 essas estruturas são populadas. Na linha 14 temos o objeto minhaEstrutura do tipo

Estrutura e a ele atribuímos o retorno do método getEstrutura(), nesse método é retornado de

forma aleatória a instância do objeto lista ou do objeto fila. Na linha seguinte temos o objeto

it do tipo Iterador que irá receber o iterador do objeto minhaEstrutura. Finalmente, nas linhas

17 e 18 é percorrido os objetos pertencentes à estrutura minhaEstrutura através do iterador it.

É importante observar que, apesar de o tipo de estrutura do objeto minhaEstrutura não ser

conhecido, a forma de acesso aos objetos nela inseridos é feita da mesma forma, usando o

iterador, independente de como se dá o acesso a essa estrutura ou de como ela está

organizada.

Page 64: UM ARCABOUÇO DE APOIO AO APRENDIZADO DE PADRÕES DE PROJETO NO CONTEXTO DE DISCIPLINAS DE PROGRAMAÇÃO ORIENTADA A OBJETOS

64

Figura 39 – Classe Aplicacao.java

Proposição

Faça um programa em Java utilizando o padrão acima discutido utilizando pilha e

array como estruturas de dados a serem percorridas pelo iterador de forma transparente.

Extensão

Agora, adicione ao programa desenvolvido uma nova estrutura de dados, hash map.