POSA Padrões Arquiteturais (POSA I, II e III) Pattern-Oriented Software Architecture POSA I: A System of Patterns POSA II: Patterns for Networked and Concurrent Objects POSA III: Patterns for Resource Management Ao escrever um padrão, veja se você tem bem claro 3 coisas que devem estar contidas na descrição do padrão: Contexto: uma situação que leva a um problema Problema: um problema recorrente que acontece em determinada situação Solução: uma solução comprovada para problema 2 Architectural Patterns (alto nível) Da lama à estrutura Layers Pipes and Filters Blackboard Sistemas Distribuídos Broker 3 Architectural Patterns (alto nível) Sistemas Interativos Model-View-Controller Presentation-Abstraction-Control Sistemas Adaptáveis Microkernel Reflection 4 Design Patterns (nível médio) Decomposição Estrutural Whole-Part Organização de Trabalho Master-Slave Controle de Acesso Proxy 5 Design Patterns (nível médio) Gerenciamento Command Processor View Handler Comunicação Forward-Receiver Client-Dispatch-Server Publisher-Subscriber 6 Idioms (baixo nível) Counted Pointer 7 Padrão de Projeto: Publisher-Subscriber É na verdade o Observer (293) do GoF. O POSA o inclui para descrever variantes interessantes do padrão Problema: em alguns sistemas, os dados mudam em um certo lugar e vários objetos em outras partes do sistema dependem daqueles dados; é necessário então, utilizar algum mecanismo para informar os dependentes das mudanças. poder-se-ia introduzir chamadas explícitas do objeto cujo estado mudou para os seus dependentes, mas esta solução não é flexível nem reutilizável. precisamos de um mecanismo de propagação de mudanças que possa ser aplicado em vários contextos 8 Padrão de Projeto: Publisher-Subscriber A solução tem que equilibrar as seguintes forças: um ou mais objetos tem que ser notificados sobre mudanças em um objeto o número de dependentes não é conhecido a priori e pode até mudar dinamicamente fazer com que os dependentes peguem o estado de tempos em tempos (polling) é muito caro o objeto que provê o dado e aqueles que o consomem não devem ser fortemente acoplados 9 Padrão de Projeto: Publisher-Subscriber Solução: O objeto que contém o dado que interessa é chamado de Publisher (subject no GoF) Os objetos dependentes são chamados de Subscribers (observers no GoF) O publisher mantém uma lista dos objetos registrados que são aqueles interessados em receber notificações sobre as mudanças. O publisher oferece uma interface para manifestação de interesse (subscribe interface) Quando o estado do publisher muda, ele envia uma notificação para todos os objetos que manifestaram interesse. Ao receber uma notificação, o subscriber decide se solicita a informação ao publisher ou não. 10 Padrão Arquitetural para Sistemas Adaptáveis: Microkernel O uso de micronúcleos se aplica a sistemas que precisam ser adaptados para mudanças nos requisitos. Premissa básica do bom programador OO: Design for Change. Exemplo: Sistema operacional hipotético Hydra no qual podemos executar aplicações Windows, UNIX System V ou NeXTSTEP simultaneamente em diferentes janelas. Contexto: Desenvolvimento de várias aplicações que utilizam interfaces programáticas similares baseadas numa mesma funcionalidade. 11 Padrão Arquitetural para Sistemas Adaptáveis: Microkernel Problema: Software básico é utilizado ao longo de muitos anos, às vezes décadas. Ao longo da sua vida, acontecem muitas mudanças no hardware, nos modelos de programação, nos tipos de bibliotecas utilizadas, e nos requisitos das aplicações. O núcleo da funcionalidade do software básico deve ser encapsulado em uma componente que seja o menor possível e que consuma o mínimo possível de recursos computacionais para não prejudicar as aplicações para as quais ele oferece suporte. 12 Padrão Arquitetural para Sistemas Adaptáveis: Microkernel Solução: Encapsule os serviços fundamentais da sua plataforma em uma componente chamada "micronúcleo". O micronúcleo oferece os seus serviços básicos através de sua interface bem definida. Funcionalidade que não é essencial e que não pode ser implementada sem aumentar a complexidade do micronúcleo deve ser implementada em "servidores internos" que estendem a funcionalidade do micronúcleo. Outras componentes chamadas de "servidores externos" utilizam a interface do micronúcleo para prover outros tipos de interfaces baseadas na funcionalidade exportada pelo micronúcleo. Os clientes (aplicações) interagem com o sistema através dos servidores externos. 13 Padrão Arquitetural para Sistemas Adaptáveis: Microkernel Usos conhecidos: Sistemas operacionais baseados em micronúcleos: Mach (CMU, 1986), hoje base do MacOS X Amoeba (Tanenbaum, 92), OS orientado a objetos Windows NT (Microsoft, 93), oferecia 3 servidores externos: OS/2, POSIX e Win32. Banco de Dados basedo em micronúcleo: MKDE (Microkernel DatenBank Engine) de 1996. Diferentes tipos de bancos de dados com interfaces diferentes são implementados em cima de um microkernel básico. Middleware de Comunicação: Isso é suficiente para carregar “incrementalmente” em tempo de execução um middleware para comunicação em sistemas distribuídos, por exemplo, um subconjunto de CORBA. Servidor de Aplicações: JBoss Plataforma para criação de aplicações locais Eclipse 14 Idioms (baixo nível) São padrões de bem baixo nível específicos para um determinada linguagem de programação Explica como implementar um determinado conceito utilizando os mecanismos de uma linguagem Às vezes ao olharmos para um padrão de projeto em uma determinada linguagem, podemos ser levados a uma expressão idiomática. Por exemplo, o padrão Singleton em C++ e Smalltalk podem ser vistos como idioms Os livros Effective C++ and More Effective C++ de Meyers e o livro Effective Java são bons exemplos de livros de expressões idiomáticas. O POSA apresenta apenas um exemplo de expressão idiomática mais elaborada 15 Idioms (baixo nível) Counted Pointer Problema: alocação dinâmica de objetos em C++ causa muitos problemas de vazamento de memória objetos tem que ser destruídos explicitamente e muitas vezes não sabemos o lugar apropriado para destruí-lo (e liberar sua memória em C++ usamos muito passagem de objetos como parâmetro, mas quando fazemos isso, quem deve ser responsável por destruir o objeto? O “chamador” ou o chamado? Forças: passar objetos sempre por valor não é apropriado vários clientes precisam compartilhar um mesmo objeto não podemos permitir referências para objetos que já foram destruídos (dangling references) se um objeto não é mais utilizado, ele deve ser destruído para liberar os recursos a solução não deve exigir muito código adicional e deve ser leve computacionalmente 16 Idioms (baixo nível) Solução introduza contagem de referências utilizando um "apontador contador" ao invés de apontadores simples adicione um contador de referências na classe original crie uma classe Handle que servirá de "apontador inteligente" para o objeto original ver diagrama UML no POSA ver código fonte da implementação no POSA 17 CRC (Class, Responsibility, Collaborator) Exemplo: padrão Layers Class Camada J Responsibility Provê serviços usados pela camada J+1 Delega subtarefas para a camada J-1 Collaborator Camada J-1 Exemplo concreto de uso do padrão: FTP em cima de TCP em cima de IP em cima de Ethernet em cima de cabo de par trançado. 18