Padrões de Projeto Aspectos Avançados em Engenharia de Software Fernanda Campos UFJF/DCC Aula 8 O problema Software: • • • Os custos de projeto estão crescendo O prazo está se tornando mais curto Custo de manutenção é maior Hardware: • • Os custos, relativos, estão diminuindo O tempo de desenvolvimento está encurtando O problema Custos em projeto de software por fase de desenvolvimento: Etapa de Trabalho % Análise de requisitos 3 Projeto 8 Programação 7 Testes 15 Manutenção 67 Fonte: Butler Bloor Introdução problemas de software + crescente taxa de mudanças nos requisitos Introdução Categorias básicas de projeto: • • • Bem-sucedidos: resultam em funcionalidade plena no prazo adequado (16,2%); Contestados: requerem tempo e orçamento maiores do que o proposto (52,7%); Refutados: são cancelados durante a fase de desenvolvimento (31,1%). O que o cliente deseja Uma solução que: • • • Atenda as necessidades funcionais; Adapte-se ao ambiente de rápidas mudanças dos negócios; Enquadre-se às limitações de run-time [tempo / espaço]. Um software que: • • • Seja de fácil manutenção; Seja desenvolvido dentro dos recursos propostos; Tenha uma longevidade apropriada. Motivação Vamos observar dois profissionais de marcenaria: construir gavetas. Motivação Carpinteiro 1: • Como você acha que deveríamos construir essas gavetas? Motivação Carpinteiro 2: • • • “Bem, acho que devemos fazer o canto cortado reto a madeira e então cortando-a de volta em 45 graus... ...indo depois reto de volta para baixo e aí de volta para cima, no outro sentido, em 45 graus; depois, indo reto de volta para baixo e, então,... ..até que você termina com uma junta encaixada. Motivação Carpiteiro 1: • Devo usar uma junta encaixada ou uma de meia esquadria? É uma solução mais complexa É insensível à temperatura e à umidade É independente do sistema de fixação Esteticamente mais bonita É uma solução mais simples É fraca Não é aparente Motivação Vantagens: • Reutilizar soluções; • Estabelecer terminologia comum; • Ter uma perspectiva de mais alto nível acerca dos problemas e do processo de projeto: abstração. Motivação Christopher Alexander Alexander investigou: • “A qualidade é objetiva?” • “Como reconhecer e diferenciar um projeto de boa qualidade em relação a um de baixa qualidade?” Motivação Alexander descobriu: • As estruturas estão diretamente ligadas com o problema que tentam resolver; • Padrões: similaridades entre projetos de alta qualidade. Definição 1979 por Alexander: “Cada padrão descreve um problema que ocorre repetidamente no nosso ambiente e, portanto, descreve o cerne da solução desse problema, de tal forma que você pode utilizar essa solução um milhão de vezes repetidas, sem nunca fazêla de duas vezes do mesmo modo.” Definição Padrão: “descreve uma solução para um problema em um determinado contexto”. Descrição De acordo com Alexander: • O nome do padrão; • O propósito do padrão; • Como podemos utilizar o padrão; • Restrições e motivos a serem considerados. O início 1990 – Desenvolvedores imaginavam: • Existem problemas em software que poderiam ser resolvidos da mesma maneira? • Seria possível projetar software em termos de padrões? O início A GOF publicou o livro de maior influência: • Design Patterns: Elements of Reusable Object-Oriented Software O início Os propósitos do livro eram: • • • • Aplicar a idéia de padrões de projeto a projeto de software; Descrever uma estrutura para catalogar e descrever padrões de projeto; Identificar e catalogar estes padrões (23); Postular estratégias e enfoques orientados a objetos baseados nesses padrões de projeto. Padrões para Projetos Quando especialistas trabalham na solução de um problema é raro criarem soluções totalmente novas, em geral buscam problemas similares que já tenham sido resolvidos e reutilizam a essência da resolução na solução do novo problema (Budchman et al, 1996). “Um padrão é uma idéia que foi utilizada num contexto prático e que provavelmente será utilizada por outros” (Fowler, 1997). Desta forma muitas experiências em criação de modelos para projetos e a repetição contínua desses problemas apresentados levam à especificação dos padrões. Padrões para Projetos Padrões documentam experiências de projetos e não são inventados ou criados artificialmente. Uma característica importante dos padrões é disponibilizar para muitos um conhecimento adquirido. O esquema da solução é especificado pela descrição dos componentes, suas funções e relacionamentos e as formas de colaboração entre eles (Budchman et al., 1996). Padrões para Projetos A construção de padrões é um processo social interativo de coleta, compartilhamento e amplificação de experiência e conhecimento distribuídos (Lea 1994 in Vasconcelos Junior, 1997). Os padrões ajudam na redução da complexidade de muitas situações na vida real e podem fornecer combinações de ações que levam à solução de problemas (Pree, 1995). Para Buschmann et al. (1996), os padrões demonstram as prováveis soluções de uma forma facilmente disponível e se possível, bem escrita. Padrões para Projetos “O emprego de padrões tem sido, portanto, no sentido de disseminar soluções incorporando, além de soluções, informações tais como descrições do problema e contexto de aplicação” (Vasconcelos Junior, 1997). O formato dos padrões é, a partir desta conceituação, uma técnica de representação do conhecimento sobre problemas e suas soluções. A inovação que esta técnica introduz é a forma sistemática de documentar e descrever os padrões de forma a facilitar a sua aplicação e uso. Padrões para Projetos Segundo Fowler (1997) padrões conceituais, incluídos os design patterns, são aqueles que representam a maneira como as pessoas pensam, mais do que a maneira como um sistema é planejado. O modelo conceitual é um privilégio humano de modo que o que buscamos é a sua aplicabilidade. Design Patterns complementam métodos existentes e buscam soluções para os problemas recorrentes num alto nível de abstração. Podem envolver desde um conjunto simples de regras e relações até elaboradas guidelines, envolvendo complexas relações daí derivadas (Lyardet et al., 1998). Padrões para Projetos Existem alguns elementos que são considerados essenciais para um padrão, entre eles podemos citar (Gamma et al., 1995): O nome: usado para descrever o problema, sua solução e conseqüências em uma ou duas palavras; O problema: descreve quando usar o padrão, explica o problema e o seu contexto. Algumas vezes inclui uma lista de condições que devem ser satisfeitas antes da aplicação do padrão; A solução: descreve os elementos que compõem o projeto, seus relacionamentos, responsabilidades e colaborações. É uma descrição abstrata do design do projeto e como um conjunto de elementos o resolve; As conseqüências: são os resultados e comprometimentos da aplicação do padrão. As conseqüências são críticas para avaliar as alternativas e para entender custos e benefícios para aplicação de padrões. Padrões para Projetos Considerando a literatura sobre padrões, Vasconcellos Junior (1997) apresentou um conjunto básico de informações importantes para registrar padrões de forma a facilitar a consulta: Identificação: um nome, ou frase, descritivo, curto e familiar, normalmente sendo mais indicativo da solução do que do problema ou contexto; Exemplo: um ou mais casos ilustrando o emprego de padrões; Contexto: delineamento de situações em que os padrões são aplicáveis (geralmente inclui informações de suporte, discussões sobre a necessidade de existência do padrão e evidências de sua generalidade); Problema: uma descrição das forças e restrições relevantes e como interagem; Solução: uma representação da solução do problema, descrita de forma a ser útil, já que esta é a parte reutilizável. Soluções podem se referenciar e se relacionar com outros padrões de maior ou menor nível; Conseqüência: uma descrição das implicações da aplicação do padrão, como restrições e comprometimentos; Padrões relacionados: outros padrões que tem alguma relação com este. Por, exemplo, aqueles que podem ser usados em conjunto ou que são semelhantes. Padrões para Projetos Fowler (1997), entretanto, descreve quatro partes essenciais que os padrões devem ter, ressaltando a forma como muitos autores vem descrevendo seus padrões. Para o autor esta forma é importante porque ela sustenta a definição de um padrão como a solução de um problema num contexto. São elas: uma afirmação do contexto onde o padrão é utilizado; o problema que ele busca solucionar; as forças que atuam na formação da solução; e a solução que resolve as forças. Padrões para Projetos Buschmann et al. (1996) adotam um esquema de três partes para documentar padrões: Contexto: a situação que originou o problema; Problema: o problema que se originou do contexto; Solução: uma resolução comprovada do problema. Padrões para Projetos Contexto O contexto estende a dicotomia problemasolução descrevendo a situação na qual o problema ocorre. Especificar um contexto é uma tarefa difícil e é praticamente impossível prever todas as situações onde um padrão pode ser utilizado. Uma solução apresentada é listar todas as situações conhecidas onde a utilização do padrão pode ser relevante. Padrões para Projetos Problema O problema é a descrição dos problemas que se originam repetitivamente do contexto. Inicia-se com uma especificação geral do problema, capturando a sua essência, que é completada por um conjunto de forças. A idéia de “forças” é introduzida pela lógica fuzzy onde deve-se determinar quais fatores são cruciais para a solução de seu problemas, quais os aspectos relevantes ou não, a indicação da solução de seu problema será fornecida a partir do total de condições, fatores e/ou “forças” cruciais que constam no problema apresentado. O termo “forças” é usado para especificar aspectos do problema que devem ser considerados quando da resolução do problema, tais como: requisitos que a solução deve abordar, obrigações que devem ser consideradas e propriedades que a solução deve ter. Padrões para Projetos Solução Muitos problemas podem ter mais de uma solução, e a adequação da solução ao problema está relacionada ao contexto em que o problema ocorre. Cada solução leva em consideração algumas forças e soluciona umas em detrimento de outras, ou pode mesmo ignorá-las. A solução mais apropriada é a que melhor resolve as forças de mais alta prioridade para o contexto em questão (Meszaros et al., 1998). Padrões para Projetos Os usuários dos padrões esperam que os mesmos contenham determinadas informações que os diferenciem da descrição problema/solução. Meszaros et al. (1998) demonstram o relacionamento entre os elementos de um padrão na figura, destacando os elementos mandatórios que os mesmos deverão conter. USUÁRIOS DE PADRÕES OPERA EM CONTEXTO PRIORIZA TEM FORÇA RESOLVE SOLUCIONA PROBLEMA SOLUÇÃO Sistemas de Padrões Os padrões não existem isoladamente, pois existem muitas interdependências entre eles. Um sistema de padrões agrupa padrões individuais e descreve como eles se conectam e como eles se complementam. Um sistema é mais do que uma coleção de padrões e deve ser organizado de uma forma que facilite a sua utilização e que guie os usuários na seleção dos padrões. Sendo assim, o modelo de descrição dos padrões, para contemplar um sistema, deve evidenciar como o padrão se conecta com os outros padrões, com quais outros padrões ele pode ser conectado, com quais outros padrões ele pode ser refinado e combinado, quais variáveis ele supõe e quais outros padrões resolvem o mesmo problema de maneira diversa da apresentada (Budchman et al, 1996). Sistemas de Padrões Um sistema de padrões deve assegurar a sua evolução uma vez que nem mesmo os sistemas mais maduros permanecerão estáticos (Budchman et al, 1996). Novos padrões devem ser incorporados ao sistema e padrões obsoletos devem ser retirados e, em qualquer caso, os relacionamentos devem ser atualizados Descrição Padrões de Projeto OO Nome: • todos os padrões tem um nome único que os identifica; Intenção: • o propósito do padrão; Problema: • o problema que o padrão está tentando resolver; Solução: • como o padrão provê uma solução para o problema no contexto em que ele aparece; Participantes e colaboradores: • as entidades envolvidas no padrão; Conseqüências: • investiga as forças que nele agem; Implementação: • como o padrão pode ser implementado; Estrutura de design: • Meta-modelo. Classificação Propósito: • • • De criação: criação de objetos; Estrutural: composição de classes ou objetos; Comportamental: maneira pelas quais classes ou objetos interagem e distribuem responsabilidades. Escopo: • • Classe: relacionamento entre classes e sub-classes (estático); Objeto: relacionamento de objetos que podem ser mudados em tempo de execução (dinâmico). Padrões no Projeto Tipos (Pressman) Padrões arquiteturais – definem uma estrutura global o software, indicam oi relacionamento entre subsistemas e componentes do software e definem as regras para especificar relacionamentos entre os elementos (classes, pacotes, componentes, subsistemas ) da arquitetura. Padrões no Projeto Tipos (Pressman) Padrões de projeto – atendem a um elemento específico do projeto tal como uma agregação de componentes para resolver algum problema de projeto, relacionamentos entre componentes ou os mecanismos para efetuar a comunicação componente a componente. Padrões no Projeto Tipos (Pressman) Padrões de código – são padrões específicos da linguagem e geralmente implementam um elemento algorítmico de um componente, um protocolo epecífico de interface, ou um mecanismo para comunicação entre omponentes. Strategy Strategy Strategy Intenção: permitir utilizar diferentes algoritmos, dependendo do contexto em que eles ocorrem; Problema: a seleção de um algoritmo depende do cliente ou dos dados; Solução: separar a seleção de algoritmos da implementação destes. Strategy Conseqüências: • Defini uma família de algoritmos; • Comandos como switch e condicionais • podem ser eliminados; Invoca-se todos os algoritmos da mesma maneira. Implementação: utilizar uma interface e instanciar a derivação especifica para o contexto. Strategy Estrutura: Strategy Exemplo: Applet Bubble sort Estratégia ordena vetor Bidirecional bubble sort Quick sort Strategy Código: context(...) { if(alg == BUBBLE) { b.sort(vec); } else if(alg == BIBUBBLE) { bb.sort(vec); } else { // Q q.sort(vec); } } Strategy Exemplo: algorithm Strategy Código: class SortAlgorithm { ... void sort(int a[]) ... { } ... } Strategy Código: public class QSortAlgorithm extends SortAlgorithm { ... void sort(int a[]) ... { ... } ... } Strategy Código: public class SortItem extends ... implements ... { ... SortAlgorithm algorithm; ... public void init() { String at = getParameter("alg"); ... algName = at + "Algorithm"; ... } ... public void run() { ... algorithm = (SortAlgorithm)Class.forName(algName).newInstance(); ... algorithm.sort(arr); } ... } Strategy Código: <html> ... <applet code=SortItem.class …> <param name="alg" value="BubbleSort"> ... <applet code=SortItem.class …> <param name="alg" value="BidirBubbleSort"> ... <applet code=SortItem.class …> <param name="alg" value="QSort"> ... </html> Strategy Applet: • SortDemo/example1.html Abstract Factory Abstract Factory Abstract Factory Intenção: ter conjuntos de objetos para casos particulares; Problema: objetos relacionados precisam ser instanciados; Solução: coordenar a criação de famílias de objetos. Abstract Factory Conseqüências: isola as regras referentes sobre como utilizar os objetos; Implementação: definir uma classe abstrata que especifica quais objetos devem ser implementados, e a seguir, implementar uma classe concreta para cada família. Abstract Factory Estrutura: Abstract Factory Exemplo: Uma solução alternativa Facade Facade Intenção: simplificar o uso de um sistema através de uma única interface; Facade Facade Estrutura: Facade Exemplo: Composite Intenção:Geralmente temos a necessidade de manipular objetos compostos (composites) exatamente da mesma forma que manipulamos objetos primitivos; Problema:Se precisássemos distinguir entre objetos primitivos e objetos compostos para realizarmos operações nestes dois tipos de objetos, nosso código tornaria-se mais complexo e difícil de implementar, manter e estender; Composite Solução:Compor objetos em uma estrutura de árvore para representar hierarquias parte-todo. Composite permite que os clientes tratem objetos individuais e composições de objetos uniformemente; Conseqüências:Composite é composto de uma coleção de outros componentes abstratos, que podem ser qualquer outro tipo de componente concreto, incluindo o próprio Composite. Todos eles são componentes abstratos e quando um método é invocado de um objeto Composite, ele simplesmente manda requisições seqüencialmente para todos seus componentes “filhos”; Composite Implementação: // This method is a Composite method public void draw() { // Iterate over the components for(int i=0; i < getComponentCount(); ++i) { // Obtain a reference to the component and invoke its draw method Component component = getComponent(i); component.draw(); } } Composite Estrutura: f.operacao(); Composite Exemplo: Observer Intenção: definir uma dependência um-para-muitos entre os objetos, para quando um deles mudar de estado todos os seus dependentes sejam notificados e atualizados automaticamente; Problema: precisa-se notificar uma lista variável de objetos de que um evento ocorreu; Solução: Fazer com que os observadores deleguem a responsabilidade de monitoração de um evento a um objeto central: o sujeito. Observer Conseqüências: sujeitos podem informar à observadores sobre eventos; Implementação: anexar objetos que queiram saber sobre a ocorrência de um evento em um objeto que faz a monitoração do evento. Observer Implementação: public interface Subject { public void addObserver( Observer o ); public void removeObserver( Observer o ); } public interface Observer { public void update( Subject o ); } Observer public class IntegerDataBag implements Subject { private ArrayList list = new ArrayList(); private ArrayList observers = new ArrayList(); public void add( Integer i ) { list.add( i ); notifyObservers(); } public Integer remove( int index ) { if( index < list.size() ) { Integer i = (Integer) list.remove( index ); notifyObservers(); return i; } return null; } Observer private void notifyObservers() { // loop through and notify each observer Iterator i = observers.iterator(); while( i.hasNext() ) { Observer o = ( Observer ) i.next(); o.update( this ); } } } Observer Estrutura: Observer Exemplo: Fórmula cálculo taxas Gráfico de Barras Gráfico de Fatias Conjunto de Dados Sujeito: O conjunto de dados envia notificações a todos aqueles que o estão observando cada vez que seu conteúdo mudar. Observadores: Cada observador envia uma requisição para os dados atualizados. Mediator Intenção: definir um objeto que encapsula como um conjunto de objetos interagem; Problema: projetos orientados a objetos encorajam a distribuição de comportamentos entre os objetos; Solução: encapsular o comportamento coletivo em um objeto separado, que é responsável por controlar e coordenar a interação do grupo de objetos. Mediator Conseqüências: limita subclasses, simplifica protocolos de objetos, abstrai como os objetos cooperam e centraliza o controle; Implementação: os colaboradores tem que comunicar o mediador quando um evento de interesse ocorre. Uma aproximação é uma implementação usando Observer. Mediator Estrutura: Mediator Exemplo: Bridge Intenção: separar abstração da implementação; Problema: as derivações de uma classe abstrata devem usar múltiplas implementações sem causar uma explosão no número de classes; Solução: definir uma interface para todas as implementações a serem usadas e fazer com que as derivações da classe abstrata a usem. Bridge Conseqüências: O desacoplamento entre as implementações e os objetos que as usam aumenta a capacidade de extensão; Implementação: • • Encapsular as implementações em uma classe abstrata; Incluir um apontador para ela na classe-base de abstração. Bridge Estrutura: Bridge Exemplo: Decorator Intenção: anexar, dinamicamente, responsabilidades adicionais a um objeto; Problema: necessidade de acrescentar funcionalidades adicionais à um objeto, antes ou depois da funcionalidade básica; Solução: estender a funcionalidade de um objeto de forma encadeada, sem recorrer à subclassificação. Decorator Conseqüências: a funcionalidade que deve ser adicionada reside em pequenos objetos. A vantagem está na capacidade de adicionar dinamicamente essa função antes ou depois da funcionalidade básica; Implementação: criar uma classe abstrata que represente tanto a classe original como as novas funções a serem adicionadas a ela. Nos decoradores, colocar as novas chamas de função antes ou depois das novas chamadas encadeadas, a fim de obter a ordem correta. Decorator Estrutura: Decorator Exemplo: VisualComponent Draw() TextView Decator Draw() Draw() ScrollDecorator ScrollPosition Draw() ScrollTo() BorderDecorator borderWidth Draw() DrawBorder() MVC Intenção: Uma maneira de quebrar uma aplicação, ou apenas parte dela, em partes, com uma clara separação dos objetos de cada parte; Problema: Aplicações que necessitem Solução: Encapsular os dados junto com seu a capacidade de manter múltiplas views dos mesmos dados; processamento (o modelo), isolando de sua manipulação (o controlador) e apresentação (view); MVC Conseqüências: O desacoplamento modifica desde como os dados são manipulados até como são apresentados ou armazenados, enquanto unifica o código em cada componente. Por causa desta separação, múltiplas views e controladores podem “interfacear” com ou mesmo modelo; MVC Implementação: O MVC é um padrão composto de vários outros padrões, como exemplo: • As views formam um árvores usando Composite; • A relação entre views e modelos é feita via Observer; • Os controladores são estratégias de views (Strategy). MVC Estrutura: Padrões de Projeto • utilizar padrões é: • reutilizar soluções; • produzir código flexível. • documentar em +alto nível o sistema; • “Os padrões fornecem a você uma perspectiva de mais alto nível acerca dos problemas e do processo de orientação a objetos...” UML & Padrões de Projeto • UML sem Padrões • Padrões sem UML • Não obtemos um ferramental completo • UML com Padrões • Atingimos o máximo do potencial que podemos em um desenvolvimento Referências FOWLER, Martin; SCOTT, Kendall. UML Essencial. Bookman, 2000. LARMAN, Craig. Utilizando UML e Padrões. Bookman, 2000. LEE, Richard C.; TEPFENHART, William M. UML e C++. Makron Books, 2002. SHALLOWAY, Alan; TROTT James R. Explicando Padrões de Projeto. Bookman, 2004. Sun Microsystems. Core J2EE Patterns. Campus, 2002 http://inf.unisinos.br/~crespo http://dei.unicap.br/~sergio http://www.netobjectives.com/design.htm#Design_patterns_are http://www.cmcrossroads.com/bradapp/docs/patterns-nutshell.html