Escolar Documentos
Profissional Documentos
Cultura Documentos
Marcos Brizeno
This book is for sale at http://leanpub.com/primeiros-passos-com-padroes-de-projeto
This version was published on 2016-02-20
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and
many iterations to get reader feedback, pivot until you have the right book and build traction once
you do.
2016 Marcos Brizeno
Ol, esse livro foi escrito pensando em pessoas que possuem um bom conhecimento de Orientao a
Objetos e querem dar os primeiros passos com Padres de Projeto.
No iremos entrar em muitos detalhes sobre os padres, mas o meu livro Refatorando com Padres
de Projeto um excelente maneira de aprofundar os estudos.
Se voc gostar do que vai ler aqui, compartilhe o material com outras pessoas!
Se tiver qualquer feedback me avise em @marcosbrizeno.
Esse livro foi distribudo de graa e pode ser encontrado em leanpub.com.
Boa leitura!
Contedo
INTRODUO
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2
3
4
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
10
11
11
12
O PADRO STRATEGY . . . . . . . . . . . . .
Exemplo de Uso . . . . . . . . . . . . . . .
Um Pouco de Teoria . . . . . . . . . . . . .
Quando No Usar . . . . . . . . . . . . . .
Evoluindo o Strategy para Template Method
Evoluindo o Strategy para State . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
16
17
17
18
A ESTRADA A FRENTE
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . . . . 19
20
20
REFERNCIAS EXTERNAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22
SOBRE O AUTOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
INTRODUO
Como desenvolvedores, ns enfrentamos vrios problemas para lidar com a informao nos sistemas:
estruturar e armazenar as informaes, transformar dados para que possam ser lidos pelos usurio,
agrupar dados de diferentes sistemas etc. Assim, desenhar um sistema e sua arquitetura nem sempre
uma tarefa simples e direta. Alm disso, conforme aprendemos mais sobre o domnio e a maneira
como o sistema utilizado, percebemos que o desenho inicial no ser suficiente e sentimos a
necessidade de modific-lo.
No entanto, a maioria dos desafios que encontramos no nico. Certamente o domnio do sistema
pode ser diferente, mas a essncia dos problemas continua a mesma: como lidar com informao.
Assim surgiu a ideia dos Padres de Projeto, como uma base coletiva de conhecimento com solues
para esses problemas comuns que encontramos todos os dias.
Ao longo deste livro vamos ver como se deu o surgimento dos Padres de Projeto e como eles
foram adaptados para o desenvolvimento de software. Em seguida vamos analisar caractersticas do
paradigma Orientado a Objetos e como eles buscam simplificar o desenvolvimento de aplicaes.
Por fim, sero explorados dois exemplos de padres voltados para o desenvolvimento Orientado a
Objetos, para exemplificar como eles podem ajudar na manuteno de sistemas.
Stafford. A diferena deste livro que os padres apresentados no so especficos para linguagens
Orientada a Objetos, mas para projetos corporativos, que precisam ser mais robustos e lidar com
problemas no triviais.
Existe tambm Padres de Projeto que propes solues para problemas especficos de uma
linguagem ou plataforma, como por exemplo o livro Core J2EE Patterns, que apresenta solues
especfica para a linguagem Java na plataforma Java 2 Enterprise Edition. Eles continuam sendo
considerados padres, a nica diferena que o contexto de sua aplicao mais restrito.
Padres de Criao
Factory Method, Abstract Factory, Builder, Prototype e Singleton
Os Padres de Criao tem como inteno principal abstrair o processo de criao de objetos, ou
seja, a sua instanciao. Desta maneira o sistema no precisa se preocupar com a lgica de criao
de objetos, permitindo que ela evolua independente do resto.
Padres Estruturais
Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy
Os Padres Estruturais se preocupam em como as classes e objetos so compostos, ou seja, sua
estrutura. O objetivo destes padres e facilitar o design do sistema, melhorando as maneiras de
relacionamento entre as entidades.
Padres Comportamentais
Interpreter, Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento,
Observer, State, Stratefy, Visitor
Os Padres Comportamentais atuam na distribuio das responsabilidades entre os objetos, ou seja,
como eles se comportam. Estes padres facilitam a comunicao entre os objetos, distribuindo as
responsabilidades.
REVISITANDO A ORIENTAO A
OBJETOS
A programao Orientada a Objetos um paradigma bastante disseminado entre os desenvolvedores, assim cada pessoa acaba tendo seu prprio entendimento. Ento, antes de falar sobre os padres
desse paradigma, vamos analisar as ideias do pensamento orientado a objetos e partir de um ponto
comum.
Alan Kay cunhou o termo Orientao a Objetos em 1967 e tido como o criador do paradigma. Em
um email, que a fonte de informao mais importante sobre o tema http://userpage.fu-berlin.de/
~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en, Dr. Kay explica quais foram suas motivaes iniciais
ao criar a Programao Orientada a Objetos.
Segundo sua definio, podemos entender o paradigma Orientado a Objetos em duas partes: 1)
objetos seriam como clulas biolgicas, que se comunicam apenas atravs de mensagens e 2)
esconder os dados, pois cada objeto possui sua prpria lgica para lidar com a informao sem
precisar exp-las.
Ao definir uma classe comum falar na interface do objeto como sendo a maneira como os objetos
desta classe trocam mensagens, ou seja os seus mtodos pblicos. Essa interface esconde o estado
interno do objeto e permite que o desenvolvedor foque nas interaes, simplificando o entendimento
do programa.
A primeira linguagem a aplicar esses conceitos foi Smalltalk, uma linguagem de tipo dinmico onde
no existem tipos primitivos e tudo implementado como uma classe. Ao longo do desenvolvimento
de novas linguagens, outras funcionalidades foram adicionadas, como por exemplo a herana e o
polimorfismo.
As linguagens Orientada a Objetos mais recentes tendem a misturar conceitos e funcionalidades de
diversos paradigmas, como por exemplo representar mtodos como objetos, utilizar lambdas para
passar blocos de cdigo como parmetros para outros mtodos etc. Mas por trs de todas essas
novas funcionalidades continua o pensamento de esconder os dados para facilitar a comunicao
entre objetos.
O conjunto de princpios que se tornou mais famoso o SOLID, criado por Robert C. Martin
(tambm conhecido na comunidade como Uncle Bob). O problema que levou a criao deles foi
a dificuldade de gerenciar dependncias entre objetos e classes, especialmente quando a aplicao
comea a crescer.
Segundo Robert, um cdigo que no consegue fazer um bom gerenciamento de dependncia se torna
difcil de manter, frgil e no reutilizvel. Em resumo, esses so os princpios e o que eles pregam:
Single Responsibility Principle (Princpio da Responsabilidade nica): Cada classe deve ter
um, e apenas um, motivo para mudar;
Open Closed Principle (Princpio Aberto Fechado): Deve ser possvel estender o comportamento de uma classe sem modific-la;
Liskov Substitution Principle (Princpio da Substituio de Liskov): Classes derivadas devem
ser compatveis com sua classe base;
Interface Segregation Principle (Princpio da Segregao de Interface): Crie interfaces mnimas
e especficas para o cliente;
Dependency Inversion Principle (Princpio da Inverso de Dependncia): Dependa de abstraes ao invs de classes concretas.
Em seu site, Robert apresenta artigos dedicados a cada um dos princpio, com motivao, exemplos
e aplicaes. Alm disso, outros princpios tambm podem ser encontrados l e a leitura recomendada para aprofundar o conhecimento no assunto: http://butunclebob.com/ArticleS.UncleBob.
PrinciplesOfOod. No meu blog, tenho uma srie de posts dedicada aos princpios solid que tambm
pode ajudar a entender melhor a importncia deles: https://brizeno.wordpress.com/solid/.
Alm do SOLID, tambm vale a pena explorar outros dois princpios de design Orientado a Objetos
que esto fortemente presentes nos Padres de Projeto:
Prefira Composio ao invs de Herana: ao herdar de uma classe estamos aumentando o nvel
de acoplamento entre elas, portanto prefervel compor objetos e criar interfaces para expor
sua lgica;
Programe voltado a Interface e no a Implementao: ao desenvolver uma classe no pense
em como ela vai funcionar, mas sim em como ela ser utilizada. Exponha interfaces que faam
sentido e simplificam seu uso.
Esses princpios foram especialmente citados aqui pois, ao refatorar o cdigo e aplicar um padro,
estamos tambm seguindo os princpios de design Orientado a Objetos.
Exemplo de Aplicao
Na Listagem 1 temos um exemplo de cdigo que pode se beneficiar do uso do Simple Factory. Nele,
o mtodo buscarProdutosPreferenciais recebe um usurio consulta um servio externo para obter os
produtos que o usurio costuma comprar. Ao final, os produtos so validados e filtrados para que
apenas aqueles com estoque sejam retornados.
No entanto, antes de chegar na lgica que realmente faz a busca dos produtos preferenciais do
usurio, preciso configurar a chamada ao servio externo. Essa responsabilidade extra aumenta o
tamanho e a complexidade do mtodo.
Listagem 1 - Mtodo que busca os produtos preferenciais de um usurio
if (toggleApiNova.habilitado()) {
config.setVersaoApi(2.1);
config.setXid(gerarUuid());
} else {
config.setVersaoApi(1.9);
config.setXid();
}
config.setEndpoint(https://intra. + getAmbienteAtual().toString() + .mega\
corp.com/);
}
ServicoRest servico = new ServicoRest(config);
List<Produto> produtos = criarProdutos(servico.executarGet())
List<Produto> produtosValidos = new ArrayList<Produto>();
for (Produto produto : produtos) {
if (produto.temEstoque()) {
produtosValidos.add(produto);
}
}
return produtosValidos;
}
Note quantas linhas apenas a criao das configuraes toma. Isso acaba desviando a ateno da
responsabilidade principal do mtodo, que buscar os produtos preferenciais do usurio.
No exemplo anterior existem dois tipos de configuraes, uma para o ambiente local e outra para
os demais ambientes. A configurao dos ambientes remotos precisa lidar ainda com um feature
toggle, para determinar qual verso da API deve ser utilizada.
A criao de configuraes locais pode ser extrada como mostrado na Listagem 2. A identificao do
recurso comum a todos as configuraes, portanto pode ser definida j no construtor da fbrica,
assim como o id do usurio. As demais configuraes so especficas ao ambiente local, ficando
portanto dentro do mtodo criarConfiguracaoLocal.
class FabricaConfiguracaoServicos {
private ConfiguracoesServicos config;
public FabricaConfiguracaoServicoProdutosPreferenciais(String idUsuario) {
config = new ConfiguracoesServicoProdutosPreferenciais();
config.setRecurso(/produtos/preferenciais/);
config.setIdUsuario(idUsuario);
}
public ConfiguracoesServicos criarConfiguracaoLocal() {
config.setEndpoint(localhost:1234);
config.setXid(gerarUuid());
config.setVersaoApi(2.1);
return config;
}
}
A lgica para criar as configuraes de servios para outros ambientes depende do feature toggle.
Nesse caso vamos passar a informao se o toggle est ativo e o ambiente atual como parmetros.
A implementao pode ficar como na Listagem 3.
Listagem 3 - Lgica especfica para configurao de servios remotos
class FabricaConfiguracaoServicos {
public ConfiguracoesServicos criarConfiguracaoRemota(boolean usarApiNova, Ambi\
ente ambiente) {
if (usarApiNova) {
config.setVersaoApi(2.1);
config.setXid(gerarUuid());
} else {
config.setVersaoApi(1.9);
config.setXid();
}
config.setEndpoint(https://intra. + ambiente.toString() + .megacorp.com);
}
}
Para utilizar o Simple Factory vamos simplesmente substituir o cdigo dentro do if pela chamada
ao mtodo fbrica apropriado. Vamos tambm extrair essa parte em um novo mtodo, para facilitar
a leitura, como mostrado na Listagem 4:
10
Apesar de simples, o ganho com a separao das responsabilidades bem grande, principalmente
na legibilidade do cdigo.
Um Pouco de Teoria
Como mencionado antes, todos os padres ajudam o seu cdigo a seguir os princpios de design
Orientado a Objetos. No caso do Simple Factory, o maior benefcio a diviso de responsabilidades
seguindo o Princpio da Responsabilidade nica.
Quem l o cdigo do mtodo buscarProdutosPreferenciais pode focar apenas em entender sua lgica,
sem ter que se preocupar em como as configuraes so criadas. Como passamos muito mais tempo
lendo cdigo do que escrevendo, essa uma grande vantagem.
11
Quando No Usar
Apesar de simples, existem situaes onde utilizar o padro Simple Factory no ajuda muito. Um
sinal bem claro de que o padro no est sendo efetivo quando a classe fbrica comea a crescer e
ter vrios mtodos para criar os mesmos produtos de maneiras diferentes. Essa talvez seja uma boa
hora para aplicar outros padres fbrica.
Nas sees seguintes vamos comparar como evoluir do Simple Factory para o Factory Method ou
para o Builder, dependendo de qual a necessidade do seu contexto. No vamos entrar em detalhes
sobre estes padres, mas outros recursos com mais detalhes sero indicados ao final do artigo (veja
a seo de Referncias Externas).
12
O PADRO STRATEGY
Ao codificar um programa, seguimos um conjunto de regras de negcio e, muitas vezes, o fluxo precisa ser dividido em vrios caminhos. Quando o cdigo cresce com vrias regras diferentes, podemos
recorrer aos padres comportamentais para melhorar a flexibilidade e facilitar a manuteno.
Padres comportamentais vo dividir as responsabilidades para resolver problemas de complexidade
do cdigo. O Strategy um exemplo de padro comportamental que busca isolar os vrios caminhos
que o algoritmo pode seguir, facilitando escolher um fluxo especfico sem precisar se preocupar com
os outros.
Exemplo de Uso
Na Listagem 5 temos a implementao do cdigo que deve calcular os pontos que um passageiro
ganhou em voos pela companhia area. As regras variam de acordo com a distncia voada, o status
do passageiro e o tipo de bilhete comprado.
Dado um passageiro, o algoritmo busca a lista de voos que ainda no foram computados e, para
cada um deles aplica as regras de pontuao. Caso o bilhete seja de primeira classe e o passageiro
tenha a categoria diamante, a distncia total do voo ser convertida em pontos. Caso o passageiro
no seja diamante, ele receber metade da distncia em voos de primeira classe, um quarto em voos
econmicos e um dcimo em voos promocionais.
Listagem 5 - Mtodo para calcular a pontuao de um passageiro
13
O PADRO STRATEGY
14
totalDePontos += voo.getDistancia()/10;
}
}
passageiro.atualizarPontuacao(totalDePontos);
passageiro.marcarVoosComoProcessados();
return totalDePontos;
}
interface EstrategiaDePontuacao {
public int calcularPontuacao(int distanciaDeVoo);
}
A implementao das estratgias tambm bem simples e pequena, pois as regras separadas so
simples. Veja como ficaria o cdigo na Listagem 7:
Listagem 7 - Classes com implementao de estratgias seguindo a interface
O PADRO STRATEGY
15
return distanciaDeVoo/4;
}
}
class EstrategiaPromocional implements EstrategiaDePontuacao {
public int calcularPontuacao(int distanciaDeVoo){
return distanciaDeVoo/10;
}
}
Um ponto de ateno ao aplicar o padro Strategy encontrar onde deve ser decidido qual estratgia
utilizar. Para determinar a regra de pontuao precisamos de informaes de um passageiro e do
bilhete. Vamos ento criar um mtodo na classe Bilhete que retorna qual a estratgia de pontuao
deve ser utilizada. Veja a implementao na Listagem seguinte:
Listagem 8 - Mtodo que decide qual estratgia deve ser utilizada
class Bilhete {
public EstrategiaDePontuacao getEstrategiaDePontuacao(boolean isPassageiroDiam\
ante){
if (bilhete.isPrimeiraClasse() && isPassageiroDiamante) {
return new EstrategiaPrimeiraClasseDiamante();
} else if (bilhete.isPrimeiraClasse()) {
return new EstrategiaPrimeiraClasse();
} else if (bilhete.isClasseEconomica()) {
return new EstrategiaClasseEconomica();
} else {
return new EstrategiaPromocional();
}
}
}
Agora basta que o mtodo calcularPontuacao pegue a estratgia do bilhete para definir quantos
pontos devem ser dados ao passageiro. A utilizao ficaria como mostrado na Listagem 8.
O PADRO STRATEGY
16
Um Pouco de Teoria
Assim como no caso do padro Simple Factory, ao aplicar o Strategy fica bem claro a diviso
das responsabilidades, seguindo o Princpio da Responsabilidade nica. A lgica para calcular a
pontuao fica mais simples uma vez que est separada.
Aps distribuir os fluxos do algoritmo nas classes estratgias, podemos tambm mover os testes
e faz-los validar apenas uma parte do cdigo. Considerando que testes so a melhor forma de
documentao, uma nova pessoa na equipe conseguir ver o funcionamento de um fluxo de cada
vez, ao invs de todo o algoritmo.
Como a estrutura de estratgias define uma interface comum para todos, tambm fcil notar o
Princpio da Substituio de Liskov. Trocar as estratgias, ou at mesmo adicionar novas, no vai ter
nenhum impacto pois o cdigo que as utiliza continuar lidando com a mesma interface.
O Princpio da Inverso de Dependncia tambm fica claro pois o cliente no usa as estratgias
concretas diretamente, apenas uma interface. Assim, cada implementao pode ter suas prprias
regras sem interferir na estrutura do cdigo.
O PADRO STRATEGY
17
Outro ponto importante que devido ao baixo acoplamento entre a classe, fica mais fcil evoluir
os cdigos separadamente. Como as estratgias tendem a mudar menos do que o cdigo do cliente,
tambm seguimos a ideia de que uma classe deve depender de outras menos provveis de mudar.
Quando No Usar
Semelhante ao padro Simple Factory, o Strategy uma excelente maneira de comear a refatorar
seu cdigo. Mas, devido a sua simplicidade, eventualmente pode ser necessrio partir para solues
mais robustas e evitar que as estratgias cresam sem limite.
Como em qualquer padro, importante entender o contexto do problema para identificar a melhor
soluo. Se o contexto muda, a soluo provavelmente mudar. Existem duas grandes necessidades
de contexto para aplicar o Strategy de maneira efetiva: 1) os fluxos do algoritmo podem ser separados
de maneira independente e 2) uma vez que sabemos qual caminho seguir, ele no muda at o final
da execuo do algoritmo.
Nas sees a seguir vamos comparar o Strategy com os padres Template Method e State, que podem
ajudar quando um dos contextos detalhados anteriormente no puder ser cumprido. No vamos
entrar em detalhes sobre a implementao destes padres, mas recursos com mais detalhes sero
indicados ao final do artigo (veja a seo de Referncias Externas).
O PADRO STRATEGY
18
A ESTRADA A FRENTE
Com os padres apresentados aqui, espero que voc tenha uma ideia melhor das vantagens de utilizlos e dos benefcios que eles proporcionam.
Padres de Projeto so uma excelente ferramenta pois, alm dos benefcios no cdigo, eles tambm
facilitam as conversas dentro do time. Se uma pessoa disser que refatorou aquele cdigo que estavam
trabalhando ontem pra utilizar um Simple Factory, voc j sabe o que foi feito sem precisar entrar
em muitos detalhes de como foi implementado.
Como explorado no comeo do artigo, existem vrios livros que apresentam padres para linguagens
Orientada a Objetos e outros mais especficos para plataformas e linguagens. Procure o material que
melhor se adequa ao seu contexto e continue aprendendo sobre essas solues.
19
21
Espero que o contedo apresentado possa ajudar nos primeiros passos e que tenha lhe motivado a
ir mais longe. No deixe de conferir os recursos indicados no final do texto para ter uma viso mais
aprofundada do contedo e saber quais so os prximos passos.
REFERNCIAS EXTERNAS
http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
Email do Dr. Alan Kay sobre a origiem da Programao Orientada a Objetos
http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
Artigos sobre Princpios de Design Orientado a Objetos no site de Robert C. Martin
http://martinfowler.com/articles/designDead.html
Artigo Is Design Dead no site de Martin Fowler
http://casadocodigo.com.br/products/livro-refatoracao-ruby
Livro Refatorando com padres de projeto de Marcos Brizeno
https://brizeno.wordpress.com/padroes
Exemplos com outros padres da Gangue dos Quatros no site de Marcos Brizeno
22
SOBRE O AUTOR
Cientista da Computao pela Universidade Estadual do Cear e Consultor de Desenvolvimento na
ThoughtWorks Brazil. Apaixonado por Engenharia de Software e Metodologias geis.
Autor do livro Refatorando com Padres de Projetos e com contribuies no Thoughtworks
Antologia Brasil e Prticas e Tendncias em Testes.
Publica regularmente no blog brizeno.wordpress.com e em @marcosbrizeno.
https://www.casadocodigo.com.br/products/livro-refatoracao-ruby
https://www.casadocodigo.com.br/pages/sumario-thoughtworks-antologia
https://info.thoughtworks.com/praticas-e-tendencias-em-teste-ebook.html
https://brizeno.wordpress.com
https://twitter.com/marcosbrizeno
23