Introdução SISMO - Sistemas e Mobilidade http://www.sismo.deinf.ufma.br Departamento de Informática / UFMA Junho de 2008
Compõem uma disciplina da Engenharia de Software voltada para a resolução de problemas baseada na documentação de melhores práticas e de lições adquiridas com a experiência
Objetivos do uso Criar uma base documental para ajudar na solução de problemas recorrentes em atividades de desenvolvimento Disseminar o uso de uma linguagem comum para compartilhar idéias e experiências sobre esses problemas e suas soluções
Qual a melhor maneira de fazer um pedido na lanchonete? Um cheesburguer, por favor! Uma fatia de carne bovina moída grelhada na chapa coberta com folhas de alface, uma fatia de derivado de leite sólido, salgado e quente, tudo isso envolvido em duas fatias de pão redondo coberto com sementes de gergelim (ufa!), por favor! Figura: nhammm!!!!
Um pouco de história... Livros do arquiteto Christopher Alexander relacionados a planejamento urbano e arquitetura de edifícios (1964, 1975, 1977, 1979) Ward Cunningham and Kent Beck artigo apresentado no OOPSLA 87, Orlando, Florida, USA - Using Pattern Languages for Object-Oriented Programs (OOPSLA - Object-Oriented Programming, Systems, Languages, and Applications)
Um pouco de história... Jim Coplien publica em 1991 um catálogo de idioms de C++ (um tipo de padrão específico de uma linguagem), Advanced C++ Programming Styles and Idioms Workshops da OOPSLA relevantes para o amadurecimento dos padrões de software: 1990-1993 1995 - Livro Design Patterns: Elements of Reusable Object-Oriented Software. Erich Gamma, Richard Helm, Ralph Johnson, e John Vlissides (referidos como the Gang of Four ou GoF) 2000 - Pattern-Oriented Software Architecture: A System of Pattern (the POSA book). Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, e Michael Stal
Tipos de Padrões Padrões de análise (Martin Fowler) Padrões organizacionais Padrões arquiteturais Padrões de projeto Idioms
Padrões Arquiteturais expressam uma organização estrutural fundamental ou esquema de sistemas de software provêem um conjunto de subsistemas predefinidos, suas responsabilidades e regras para organização do relacionamento entre eles Exemplo: MVC (Model, View, Controller)
Padrões de Projeto provêem um esquema para refinar subsistemas ou componentes de um sistema de software, ou o relacionamento entre eles descrevem estruturas recorrentes de componentes conectados que resolvem um problema geral de projeto dentro de um contexto particular
Idioms um idiom é um padrão de baixo nível específico de uma linguagem de programação idioms descrevem como implementar aspectos específicos de componentes ou de seus relacionamentos usando características de uma determinada linguagem exemplos interfaces, classes parametrizadas e reflexão em java templates em C++
Padrões não são algoritmos algoritmos e estruturas de dados resolvem geralmente problemas computacionais de granularidade mais fina (e.g., ordenação e busca) Padrões são relacionados tipicamente com problemas arquiteturais mais abrangentes com efeitos em mais larga escala. Por exemplo, os padrões de projeto no livro da GoF tratam problemas como manutenibilidade, reusabilidade e variações de encapsulamento
Padrões não são Frameworks um arcabouço de software é um conjunto de classes cooperantes que constituem um projeto reutilizável para um tipo específico de software exemplo: Swing do java
Padrões não são Frameworks II um arcabouço pode ser visto como a implementação de um sistema de padrões de projeto contudo, um arcabouço é software executável, enquanto padrões de projeto representam conhecimento e experiência sobre software
Tipos de Padrões de Projeto Padrões de Criação - Se preocupam com o proceso de criação de projetos Padrões Estruturais - Lidam com a composição de classes ou de objetos Padrões Comportamentais - Caracterizam a maneira pelas quais classes ou objetos interagem e distribuem responsabilidades
Uma pausa para respirar... Figura: antes dos problemas...
Um Problema A empresa do Zé está desenvolvendo um jogo de combate e ele recebeu a tarefa de criar uma hierarquia de classes para os combatentes. Suponha que ele criou a seguinte hierarquia inical de classes: Figura: Diagrama de Classes de Combatentes
Tudo ia muito bem, mas... A concorrência não dá moleza; e os executivos da empresa, depois de um estafante fim de semana num hotel de luxo, resolveram que o zé tinha que adicionar novas funcionalidades ao jogo. Ai ele teve uma idéia genial: Reutlização de Código via Herança - inserir os novos poderes na classe Combatente, que seriam herdados por todos os outros soldados Figura: Classe Combatente revisada
Novos Problemas ô sua anta, quem já viu soldado mergulhar no deserto?. Figura: Cuidado! Chefe doido Zé não percebeu que nem todo soldado precisa (ou pode) mergulhar! Ele poderia sobrescrever os métodos mergulhar e nadar, mas e se pedirem para adicionar um combatente astronauta? Provavelmente ele terá que sobrescrever esses métodos também...e continuar sobrescrevendo, a cada nova classe derivada de combatente. Eternamente...
O que aconteceu??? A grande idéia do Zé era usar herança com o propósito de reutilizar o código. Mas acabou criando problemas de manutenção. Quais as principais desvantagens no uso da herança no caso dos combatentes? duplicação de código nas subclasses é difícil mudar comportamento dos objetos em tempo de execução as mudanças podem afetar outros combatentes de modo não intencional
Outra grande idéia Porém o Zé foi informado que novas mudanças viriam a cada trimestre. A herança iria causar um pesadelo de manutenção. Dai, o Zé teve outra grande idéia... E se eu criasse uma interface aquática? Assim eu não teria combatentes nadando no deserto eheh. Eu sou muito esperto!!! Figura: Usando interfaces
Ai é que está o busílis (O X do problema) De fato, não temos mais combatentes nadando no deserto... Mas em contrapartida, a reutilização do código para os métodos nadar e mergulhar foi pelo ralo!!! O Zé trocou um problema de manutenção por outro. Figura: Chefe Mais Irado O problema é que mudanças são uma constante em software e precisamos desenvolver aplicações pensando nesse problema.
Princípio OO: Encapsulamento Identifique os aspectos variantes na sua aplicação e os encapsule. Posteriormente, você pode estender ou alterar as partes que variam sem afetar as que não o fazem Essa abordagem resultará em: menos surpresas inesperadas em razão de alterações no código e sistemas mais flexíveis e fáceis de manter
Aplicando o princípio do Encapsulamento ao problema Possíveis novas classes de combatentes precisarão nadar, mergulhar e até mesmo flutuar. (combatentes astronautas, por exemplo), enquanto outras não Esse tipo de comportamento (mais variável) deve ser separado da hierarquia da classe Combatente para promover independência e flexibilidade. Esse princípio está na base da maioria dos padrões de projeto orientados a objetos Todo padrão provê um meio de deixar uma das partes de um sistema variar independentemente das outras partes
Separando o que muda do que permanece Pelo que vimos até agora, os métodos mais sensíveis a mudanças são exatamente nadar, mergulhar e (o novo método) flutuar A hierarquia de classes Combatente deve continuar a mesma, isto é, com as mesmas subclasses, mas vamos tirar dela os métodos que representam comportamentos mais afetados por mudanças Vamos criar novas hierarquias de classes para representar esses comportamentos
Criando hierarquia separada de comportamentos Figura: Hierarquias de comportamentos
Implementação das Interfaces de Comportamento I Figura: Comportamento Aquático
Implementação das Interfaces de Comportamento II Figura: Comportamento Aéreo
Princípio OO: Programar para Interface Programe para uma Interface, não para uma implementação Podemos implementar novos comportamentos aquático e aéreo, criando novas classes que implementem essas interfaces A classe Combatentes não precisa conhecer detalhes de implementação desses comportamentos Outros objetos, além dos Combatentes, podem usar os comportamentos aquático e aéreo, porque eles não estão escondidos na classe combatente
Refatorando a Classe Combatente
Refatorando subclasses O Comportamento da classe Caveira é definido pelas classes que implementam as interfaces AcaoAerea e AcaoAquatica Figura: Especializando um tipo de Combatente (Caveira)
Integrando as Hierarquias Figura: Visão do Conjunto
Adicionando Comportamento Dinamicamente Figura: Aplicação Exemplo
Princípio OO: Composição Prefira Composição em vez de Herança a Composição permitiu encapsular comportamento (algoritmos) em seu próprio conjunto de clases e permitiu mudar o comportamento dos objetos dinamicamente (em tempo de execução)
Padrão Strategy Parabéns! Você acabou de ser apresentado na prática ao padrão Strategy Segundo o Livro da GoF, a intenção do Padrão Strategy é: Definir uma família de algoritmos, encapsular cada um deles e torná0los intercambiávies. Strategy permite que o algoritmo varie independentemente dos clientes que o utilizam
Padrão Strategy: Classificação e Motivação Propósito: Comportamental Escopo: Objetos Motivação: clientes que necessitam de diferentes algoritmos se tornam mais complexos se os incluirem em seu código diferentes algoritmos são adequados em diferentes situações na resolução de um mesmo problema
Padrão Strategy: Classificação e Motivação Figura: Exemplo de Motivação
Padrão Strategy: Aplicabilidade Use Strategy quando: muitas classes relacionadas diferem somente no seu comportamento você necessita de variantes de um algoritmo um algoritmo usa dados sobre os quais o cliente não precisa ter conhecimento comandos condicionais relacionados para escolher entre muitos comportamentos de uma classe podem ser movidos para sua própria classe Strategy
Padrão Strategy: Estrutura Figura: Estrutra do Padrão
Padrão Strategy: Colaborações Strategy e Context interagem para implementar o algoritmo escolhido os clientes usualmente criam e passam um objeto ConcreteStrategy para o contexto e passam a interagir diretamente com o contexto
Padrão Strategy: Consequências famílias de algoritmos relacionados uma alternativa ao uso de subclasses possibilidade de escolha de implementações os clientes devem conhecer diferentes estratégias custo de comunicação entre Strategy e Context aumento do número de objetos