Padrão Variações Protegidas
Como atribuir responsabilidades a objetos, subsistemas e sistemas, de modo que as variações ou a instabilidade nesses elementos não tenham um impacto indesejável sobre outros elementos?
Identifique pontos de variação ou instabilidade prevista; atibua responsabilidades para criar uma interface estável em torno deles
EXTREME PROGRAMMING
Extreme Programming (XP) é um processo de desenvolvimento que possibilita a criação de software de alta qualidade, de maneira ágil, econômica e flexível. Vem sendo adotado com enorme sucesso na Europa, nos Estados Unidos e, mais recentemente, no Brasil.
Cada vez mais as empresas convivem com ambientes de negócios que requerem mudanças freqüentes em seus processos, as quais afetam os projetos de software. Os processos de desenvolvimento tradicionais são caracterizados por uma grande quantidade de atividades e artefatos que buscam proteger o software contra mudanças, o que faz pouco ou nenhum sentido, visto que os projetos devem se adaptar a tais mudanças ao invés de evitá-las.
O XP concentra os esforços da equipe de desenvolvimento em atividades que geram resultados rapidamente na forma de software intensamente testado e alinhado às necessidades de seus usuários. Além disso, simplifica e organiza o trabalho combinando técnicas comprovadamente eficazes e eliminando atividades redundantes. Por fim, reduz o risco dos projetos desenvolvendo software de forma iterativa e reavaliando permanentemente as prioridades dos usuários.
Destina-se a profissionais da área de informática, gerentes e diretores de tecnologia da informação, bem como a estudantes e professores universitários.
Artigo: http://novatec.com.br/livros/extreme/capitulo8575220470.pdf
Padrão Invenção Pura
Problema: A quem atribuir responsabilidades quando qua do as classes do domínio não são adequadas e não se quer violar os princípios da Coesão Alta e do Acoplamento Fraco ? Como criar componentes de software conectáveis ?
Solução: Atribuir um conjunto de responsabilidades altamente coeso a uma classe artificial – que não representa nada no domínio do problema. Tal classe é construída especialmente para melhorar a coesão e diminuir o acoplamento, facilitando reutilização (uma invenção da imaginação).
Exemplo:
Se for necessário salvar instâncias de Venda em um banco de dados relacional, considerando o padrão Expert, esta responsabilidade pode ser atribuída à própria classe Venda.
Porém há as seguintes implicações:
-Grande número de operações voltadas ao banco de dados- diminuição da coesão
-A classe Venda tem que ser acoplada com a interface do banco de dados relacional aumento do acoplamento
–Salvar objetos é uma tarefa geral, necessária em muitas classes – duplicação de código, baixa reutilização.
-Nesse caso, a solução é criar uma nova classe que é unicamente responsável por salvar objetos em algum tipo de meio de armazenamento persistente, como um banco de dados relacional.
-Chamamos esta solução de PersistentStorageBroker.
Esta classe é uma Invenção Pura.
Padrão Indireção
Problema: Quem irá evitar o acoplamento direto? Como desacoplar objetos de maneira
a apoiar o Acoplamento Fraco e manter o alto potencial de reutilização?
Solução: Atribuir a responsabilidade a um objeto intermediário que faz a mediação
entre outros componentes ou serviços, de modo que eles não estejam diretamente acoplados.
Exemplo:
O exemplo de uma Invenção Pura de desacoplar Venda dos serviços de banco de dados relacionais, também é um exemplo de Indireção. O PersistentStorageBroker atua como um intermediário entre Venda e o banco de dados.
Link: http://www.inf.ufg.br/~juliano/ensino/especializacao/ProjSw2007/ProjetoOO.pdf
Padrão Polimorfismo
Problema: Como tratar alternativas com base no tipo ? Como criar componentes de software conectáveis ?
Solução: Atribuir responsabilidade pelo comportamento, aos tipos para os quais o comportamento varia, usando operações polimórficas.
Corolário: não teste o tipo de um objeto nem use condições lógicas no código para executar alternativas que variam com base no tipo.
O Polimorfismo significa "existindo em muitas formas". Ele permite que referências de tipos de classes mais abstratas representem o comportamento das classes concretas que referenciam. Assim, um mesmo método pode apresentar várias formas, de acordo com seu contexto.
O objetivo principal do polimorfismo é:
- Evitar a condição IF e ELSE;
- Usar polimorfismo melhorar a conectividade dos componentes.
Ferramentas:
Framework: é um conjunto de classes com objetivo de reutilização de um design, provendo um guia para uma solução de arquitetura em um domínio específico de software.
Framework se diferencia de uma simples biblioteca (toolkit), pois esta se concentra apenas em oferecer implementação de funcionalidades, sem definir a reutilização de uma solução de arquitetura (design).
ToolKit: ferramenta que não obriga o desenvolvedor a seguir um roteiro pré-definido, podendo ser alterado conforme a necessidade de cada aplicação.
Injeção de dependência: é um padrão de desenvolvimento de programas de computadores utilizado quando é necessário manter baixo o nível de acoplamento entre diferentes módulos de um sistema. Nesta solução as dependências entre os módulos não são definidas programaticamente, mas sim pela configuração de uma infraestrutura de software que é responsável por "injetar" em cada componente suas dependências declaradas.
Inversão de controle ou Inversão de controlo: (IOC) é o nome dado ao padrão de desenvolvimento de programas de computadores onde a sequência (controle) de chamadas dos métodos não é determinada pelo programador. Este controle é delegado a uma infraestrutura de software muitas vezes chamada de container. Esta é uma característica comum aos frameworks.
Hibernate
Torna a aplicação maleável a mais de um tipo de banco de dados, em poucos minutos de uma reconfiguração básica do framework. Ele também deixa transparente as operações básicas de inserção, recuperação, atualização e remoção de dados. A principal característica está no paradigma de Orientação a Objetos para banco de dados.
Referência: http://www.ezlemonpierecipes.info/pt/Polimorfismo
Exercícios:
1º) Um objeto "A" precisa executar um método quando o estado do objeto "B" for alterada. Qual o padrão GOF deve ser usado? Qual o papel do objeto "B" e do objeto "A" nesse padrão?
Resposta
2º) Qual o padrão GOF deve ser usado quando necessitamos executar diversas ações de forma atômica?
Resposta
3º) Uma classe de conexão só pode ter, no máximo, 10 instâncias. Qual o padrão GOF a usar?
Resposta
4º) Duas classes "B" e "B" tem iterfaces distintas. Qual o padrão deve ser usado se a classe "B" precisar um método da classe "A" ?
Resposta
5º) Voçê deseja que uma classe de terceiros use um método de sua classe. Qual o melhor padrão?
Resposta
MVC
O MVC é um padrão que serve para organizar as iterações entre os componentes da camada de apresentação.
Esse padrão define três tipos de componentes:
View são componentes que geram a parte da aplicação visível ao usuário do
sistema. Pode ser uma pagina JSP, uma Janela Swing, um arquivo XML, entre
outros.
A View deve implementar o padrão Observer em cima dos objetos do Model. Sempre que um objeto do Model mudar isso deve ser refletido nas Views que possam estar associadas ao referido objeto e conseqüentemente, nos dados que são mostrados ao usuário.
Model são os componentes que contém as informações que vão ser mostradas na View. Pode ser o próprio objeto do modelo da aplicação ou apenas uma interface para os objetos do modelo.
Controler são os componentes responsáveis por capturar solicitações vindas da View e as despacha para o Model. Além de atualizar a View apropriadamente. Para sistemas simples, onde a camada de aplicação não possui muitas funcionalidades, o Controler acaba as implementando.
O que o MVC possibilita:
Evita a utilização e proliferação de Spaghetti-Code tão frequentemente existente nas camadas de apresentação;
Desacopla a lógica de negócio da apresentação. Isto permite que uma única view tenha múltiplos controladores. Os controladores definem o comportamento de uma view, assim se uma view requere comportamento diverso, a implementação desses comportamentos deverá residir nos controladores.
Uma vez que o controlador é uma classe separada da view, este pode ser trocado quer em design time quer em runtime.
Se um novo tipo de utilizador for criado que requeira diferente comportamento ou estamos a providenciar uma nova plataforma na nossa aplicação, adicionar um novo controlador para cada view afectada pelas alterações é muito mais fácil do que modificar as próprias views, ou pior ainda ter de criar novas views para endereçar o problema.
Possibilita uma clara distinção entre o trabalho de cada programador ou mesmo equipa. Os designers têm claramente o seu espaço definido nas views, os especialistas do negócio trabalham nos models. Estes dois encontram-se apenas nos controllers.
Potencia a utilização de interfaces e facilidade de utilização de herança em qualquer das camadas minimizando efeitos adversos.
Padrão COMMAND
Objetivo:
Encapsular uma solicitação como um objeto, permitindo desta forma parametrizar clientes com diferentes solicitações, enfileirar ou fazer o registro (log) de solicitações e suportar operações que podem ser desfeitas.
Também conhecido como: Action ou Transaction.
Motivação:
As vezes precisamos executar uma operação sem se preocupar com qual objeto que vai realiza-la ou simplesmente não conhecemos qual objeto vai receber a delegação para executar tal operação.
Em uma aplicação Client/Servidor geralmente temos o componente Menu que é composto de
vários itens. Cada item do menu eqüivale uma operação, como salvar um arquivo, ler arquivo, apagar arquivo, selecionar a paleta de cores e etc..
Quando selecionamos um item do menu uma operação deve ser realizada. Esta operação pode ser encapsulada em um objeto, assim reduziremos o acoplamento entre o objeto menu e o objeto que executa a operação.
Um outro cenário que podemos ter. Em uma aplicação Web de três camadas, podemos fazer uma requisição para processar dos dados de um formulário esta requisição é delegada para um objeto.
Esta operação pode ser encapsulada em um objeto, assim reduziremos o acoplamento entre o as camadas.
Aplicação:
Use o padrão Command quando você precisa:
-Parametrizar objetos por uma ação a ser executada.
-Especificar, enfileirar e executar solicitações em tempos diferentes. Um objeto Command poder ter o ciclo de vida independente da requisição do cliente.
-Suporte para desfazer operações. A operação "execute" do Command, pode armazenar
estados para reverter seus efeitos no próprio comando. Basta acrescentar na interface
Command uma operação chamada "Unexecute", que terá a responsabilidade de desfazer a
operação realizada pelo "execute". Os comandos realizados podem ser armazenados em lista histórica.
-Estruturar um sistema em torno de operações de alto nível, como transações por
exemplo. Uma transação encapsula um conjunto de mudanças nos dados. O padrão
Command provê uma maneira de modelar transações. O Command tem uma interface comum,
assim podemos chamar todas as transações do mesmo jeito.
-Reduzir acoplamento entre as requisições dos clientes e o objetos que as executam.
Aplicabilidade:
Use o padrão Command para:
Parametrizar objetos por uma ação a ser executada
Tal parametrização pode ser expressada numa linguagem procedural através de uma função callback, ou seja, uma função que é registrada em algum lugar para ser chamada em um momento mais adiante.
Os Commands são uma substituição orientada a objetos para callbacks.
Especificar, enfileirar e executar solicitações em tempos diferentes.
Um objeto Command pode ter um tempo de vida independente da solicitação original.
Se o receptor de uma solicitação pode ser representado de uma maneira independente do espaço de endereçamento, então é possível transferir um objeto command para a solicitação para um processo diferente e lá atender a solicitação.
Suportar desfazer operações.
A operação execute(), de Command, pode armazenar estados para reverter seus efeitos no próprio comando.
A interface de Command pode ter acrescentada uma operação unexecute(), que reverte os efeitos de uma chamada anterior de execute().
Os comandos executados são armazenados em uma lista histórica.
O nível ilimitado de desfazer e refazer operações é obtido percorrendo esta lista para trás e para frente, chamando operações unexecute() e execute(), respectivamente.
Suportar o registro (logging) de mudanças de maneira que possam ser reaplicadas no caso de uma queda de sistema.
Ao aumentar a interface de Command com as operações carregar() e armazenar(), pode-se manter um registro (log) persistente das mudanças.
A recuperação de uma queda de sistema envolve a recarga dos comandos registrados a partir do disco e sua reexecução com a operação execute().
Estruturar um sistema em torno de operações de alto nível construídas sobre operações primitivas.
Tal estrutura é comum em sistemas de informação que suportam transações.
Uma transação encapsula um conjunto de mudanças nos dados.
O padrão Command fornece uma maneira de modelar transações.
Os Commands têm uma interface comum, permitindo invocar todas as transações da mesma maneira.
O padrão também torna mais fácil estender o sistema com novas transações.
EXEMPLO:
public class DvdName {
private String titleName;
public DvdName(String titleName) {
this.setTitleName(titleName);
}
public final void setTitleName(String titleNameIn) {
this.titleName = titleNameIn;
}
public final String getTitleName() {
return this.titleName;
}
public void setNameStarsOn() {
this.setTitleName(this.getTitleName().replace(' ','*'));
}
public void setNameStarsOff() {
this.setTitleName(this.getTitleName().replace('*',' '));
}
public String toString() {
return ("DVD: " + this.getTitleName());
}
}
public abstract class CommandAbstract {
public abstract void execute();
}
public class DvdCommandNameStarsOn extends CommandAbstract {
private DvdName dvdName;
public DvdCommandNameStarsOn(DvdName dvdNameIn) {
this.dvdName = dvdNameIn;
}
public void execute() {
this.dvdName.setNameStarsOn();
}
}
public class DvdCommandNameStarsOff extends CommandAbstract {
private DvdName dvdName;
public DvdCommandNameStarsOff(DvdName dvdNameIn) {
this.dvdName = dvdNameIn;
}
public void execute() {
this.dvdName.setNameStarsOff();
}
}
class TestCommand {
public static void main(String[] args) {
DvdName jayAndBob =
new DvdName("Jay and Silent Bob Strike Back");
DvdName spongeBob =
new DvdName("Sponge Bob Squarepants - " +
"Nautical Nonsense and Sponge Buddies");
System.out.println("as first instantiated");
System.out.println(jayAndBob.toString());
System.out.println(spongeBob.toString());
CommandAbstract bobStarsOn =
new DvdCommandNameStarsOn(jayAndBob);
CommandAbstract bobStarsOff =
new DvdCommandNameStarsOff(jayAndBob);
CommandAbstract spongeStarsOn =
new DvdCommandNameStarsOn(spongeBob);
CommandAbstract spongeStarsOff =
new DvdCommandNameStarsOff(spongeBob);
bobStarsOn.execute();
spongeStarsOn.execute();
System.out.println(" ");
System.out.println("stars on");
System.out.println(jayAndBob.toString());
System.out.println(spongeBob.toString());
spongeStarsOff.execute();
System.out.println(" ");
System.out.println("sponge stars off");
System.out.println(jayAndBob.toString());
System.out.println(spongeBob.toString());
}
}
UML do Exempo:
Link Referência
Padrão OBSERVER
Aplicação dos Design Patterns de forma simplificada!
O padrão Observer, é utilizado para quando você precisa encapsular objetos que você não conhece, dentro de um outro e notificá-los após uma determinada ação.
Pré-Requisitos:
Entendimento de orientação à objetos;
Capacidade de abstração;
Situações
Você precisa de um log de ações no seu sistema administrativo;
Você precisa saber quando alguém executou os comandos do seu WebService;
Quando um visitante do seu site fizer cadastro, deve inicializar todas as tabelas relacionadas;
Motivações
Tradicionalmente, aconselha-se o uso de padrões de projeto, pois são uma maneira unificada de falar de um determinado algoritmo;
Segundo estudos, é um padrão com nível máximo de uso;
O .NET Framework utiliza em seus componentes;
Encapsulamento e entendimento simples e fácil;
Utilização correta da orientação à objetos;
Para utilizar o padrão observer, você deve pensar que um objeto, que chamarei de "Subject", irá executar uma ação que outros deverão capturar, que chamarei de "Observer". Veja a demonstração na UML abaixo:
Quando usar o padrão Observer?
Quando uma abstração tem dois aspectos, um dependente do outro. Encapsular tais aspectos em objetos separados permite que variem e sejam reusados separadamente
Quando uma mudança a um objeto requer mudanças a outros e você não sabe quantos outros objetos devem mudar
Quando um objeto deve ser capaz de avisar outros sem fazer suposições sobre quem são os objetos.
Em outras palavras, sem criar um acoplamento forte entre os objetos.
Link Referência
Padrão Singleton
1) Singleton, é um padrão de projeto de software (do inglês Design Pattern). Este padrão garante a existência de apenas uma instância de uma classe, mantendo um ponto global de acesso ao seu objeto.
2) Singleton é um design pattern (padrão de projeto) que tem o objetivo garantir que existe apenas uma instancia de uma certa classe a qualquer instante e em qualquer ponto de um sistema.
Um singleton é um objeto e como tal é o encapsulamento de dados e comportamento. Não é possivel substituir singleton por nenhum outro padrão de projeto. Mas talvez você não esteja precisando de um objeto único e sim de uma forma global de acessar a ele ou uma forma de garantir que só é instanciado uma única vez.
Muitos projetos necessitam que algumas classes tenham apenas uma instância. Por exemplo, em uma aplicação que precisa de uma infraestrutura de log de dados, pode-se implementar uma classe no padrão singleton. Desta forma existe apenas um objeto responsável pelo log em toda a aplicação que é acessível unicamente através da classe singleton.
Exemplo:
public class SingleSpoon
{
private Soup soupLastUsedWith;
private static SingleSpoon theSpoon;
private static boolean theSpoonIsAvailable = true;
private SingleSpoon() {}
public static SingleSpoon getTheSpoon() {
if (theSpoonIsAvailable) {
if (theSpoon == null) {
theSpoon = new SingleSpoon();
}
theSpoonIsAvailable = false;
return theSpoon;
} else {
return null;
//spoon not available,
// could throw error or return null (as shown)
}
}
public String toString() {
return "Behold the glorious single spoon!";
}
public static void returnTheSpoon() {
theSpoon.cleanSpoon();
theSpoonIsAvailable = true;
}
public Soup getSoupLastUsedWith() {
return this.soupLastUsedWith;
}
public void setSoupLastUsedWith(Soup soup) {
this.soupLastUsedWith = soup;
}
public void cleanSpoon() {
this.setSoupLastUsedWith(null);
}
}
class TestSingleSpoon {
public static void main(String[] args) {
System.out.println("First person getting the spoon");
SingleSpoon spoonForFirstPerson =
SingleSpoon.getTheSpoon();
if (spoonForFirstPerson != null)
System.out.println(spoonForFirstPerson);
else
System.out.println("No spoon was available");
System.out.println("");
System.out.println("Second person getting a spoon");
SingleSpoon spoonForSecondPerson = SingleSpoon.getTheSpoon();
if (spoonForSecondPerson != null)
System.out.println(spoonForSecondPerson);
else
System.out.println("No spoon was available");
System.out.println("");
System.out.println("First person returning the spoon");
spoonForFirstPerson.returnTheSpoon();
spoonForFirstPerson = null;
System.out.println("The spoon was returned");
System.out.println("");
System.out.println("Second person getting a spoon");
spoonForSecondPerson = SingleSpoon.getTheSpoon();
if (spoonForSecondPerson != null)
System.out.println(spoonForSecondPerson);
else
System.out.println("No spoon was available");
}
}
Link Referência
Padrão ADAPTER
A função do Padrão ADAPTER é fazer com que a interface de uma classe possa ser "adaptada" à interface de uma outra para que essas possam trabalhar juntas. É a melhor forma de se ligar classes que tenham interfaces imcompatíveis. Podemos usar o Adapter caso seja necessário modificar a interface de uma classe em função de um novo requisito.
O padrão de projeto Adapter é necessário quando possuímos dois objetos que precisam se comunicar mas as suas interfaces são diferentes. O adaptador é responsável por "converter" uma interface em outra tornando possível a comunicação entre os objetos.
EXEMPLO:
public void TomadaTresPinos {
public void fornecerEnergia ();
}
public interface TomadaDoisPinos {
public void fornecerEnergia ();
}
public interface PlugueTresPinos {
public void conectar (TomadaTresPinos tomada) ;
}
public void PlugueDoisPinos {
public void conectar (TomadaDoisPinos) ;
}
public class TomadaEuropeia implements TomadaTresPinos {
public void fornecerEnergia() {
System.out.println("[TOMADA] Fornecendo energia para um plugue de três pinos!");
}
}
public class PlugueEuropeu implements PlugueTresPinos {
public void conectar(TomadaTresPinos tomada) {
System.out.println("[PLUGUE] Pegando energia elétrica de uma tomada de três pinos.");
tomada.fornecerEnergia();
}
}
public class PlugueComum implements PlugueDoisPinos {
public void conectar(TomadaDoisPinos tomada) {
System.out.println("[PLUGUE] Pegando energia elétrica de uma tomada de dois pinos.");
tomada.fornecerEnergia();
}
}
public class Adaptador implements TomadaTresPinos {
private TomadaDoisPinos tomada;
public Adaptador(TomadaDoisPinos tomada) {
this.tomada = tomada;
}
public void fornecerEnergia() {
tomada.fornecerEnergia();
}
}
public class Main {
public static void main(String[] args) {
TomadaDoisPinos tomada = new TomadaComum();
PlugueTresPinos plugue = new PlugueEuropeu();
Adaptador adapter = new Adaptador(tomada);
plugue.conectar(adapter);
}
}
Link Referência
...::: Padrões GOF :::...
História
O conceito de padrão de projeto foi criado na década de 70 pelo arquiteto Christopher Alexander . Em seus livros Notes on the Synthesis of Form, The Timeless Way of Building e A Pattern Language.
Além da definição das características de um padrão, Alexander definiu o formato que a descrição de um padrão deve ter. Ele estabeleceu que um padrão deve ser descrito em cinco partes:
Nome: uma descrição da solução, mais do que do problema ou do contexto.
Exemplo: uma ou mais figuras, diagramas ou descrições que ilustrem um protótipo de aplicação.
Contexto: a descrição das situações sob as quais o padrão se aplica.
Problema: uma descrição das forças e restrições envolvidos e como elas interagem.
Solução: relacionamentos estáticos e regras dinâmicas descrevendo
como construir artefatos de acordo com o padrão, freqüentemente citando
variações e formas de ajustar a solução segundo as circunstâncias.
Inclui referências a outras soluções e o relacionamento com outros
padrões de nível mais baixo ou mais alto.
O movimento ao redor de padrões de projeto ganhou popularidade com o livro Design Patterns: Elements of Reusable Object-Oriented Software , publicado em 1995 .
Os autores desse livro são Erich Gamma , Richard Helm , Ralph Johnson e John Vlissides , conhecidos como a "Gangue dos Quatro" (Gang of Four) ou simplesmente
"GoF". Posteriormente, vários outros livros do estilo foram publicados, como Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development.
Introdução:
Os padrões de projeto de software ou padrões de desenho de software , também muito conhecido pelo termo original em inglês : Design Patterns , descrevem soluções para problemas recorrentes no desenvolvimento de sistemas de software orientados a objetos.
Um padrão de projeto estabelece um nome e define o problema, a solução, quando aplicar esta solução e suas conseqüências.
Os padrões de projeto visam facilitar a reutilização de soluções de desenho - isto é, soluções na fase de projeto do software, sem considerar reutilização de código. Também acarretam um vocabulário comum de desenho, facilitando comunicação, documentação e aprendizado dos sistemas de software.
...::: Padrões GOF :::...
Os padrões "GoF" são organizados em famílias de padrões: de criação, estruturais e comportamentais. Os padrões de criação são relacionados à criação de objetos, os estruturais tratam das associações entre classes e objetos e os comportamentais das interações e divisões de responsabilidades entre as classes ou objetos.
Um padrão "GoF" também é classificado segundo o seu escopo; de classe ou de objeto. Nos padrões com escopo de classe os relacionamentos que definem este padrão são definidos através de herança e em tempo de compilação . Nos padrões com escopo de objeto o padrão é encontrado no relacionamento entre os objetos definidos em tempo de execução.
Padrão Controller
Model-view-controller (MVC) é um padrão de arquitetura de software. Com o aumento da complexidade das aplicações desenvolvidas torna-se fundamental a separação entre os dados (Model) e o layout (View). Desta forma, alterações feitas no layout não afectam a manipulação de dados, e estes poderão ser reorganizados sem alterar o layout.
O model-view-controller resolve este problema através da separação das tarefas de acesso aos dados e lógica de negócio, lógica de apresentação e de interacção com o utilizador, introduzindo um componente entre os dois: o Controller. MVC é usado em padrões de projeto de software, mas MVC abrange mais da arquitetura de uma aplicação do que é típico para um padrão de projeto.
Lida com o tratamento de mensagens ou eventos de sistema.
Atribuir a responsabilidade de tratar eventos do sistema a uma classe que representeuma das seguintes opções:
▪Representa o sistema como um todo, um dispositivo ou um subsistema (umcontrolador fachada);
▪Representa um caso de uso em que o evento de sistema ocorre (controlador de casode uso ou sessão).
A arquitetura MVC - (Modelo Visualização Controle) fornece uma maneira de dividir a funcionalidade envolvida na manutenção e apresentação dos dados de uma aplicação.
A arquitetura MVC não é nova e foi originalmente desenvolvida para mapear as tarefas tradicionais de entrada , processamento e saída para o modelo de interação com o usuário.
Usando o padrão MVC fica fácil mapear esses conceitos no domínio de aplicações Web multicamadas.
Na arquitetura MVC o modelo representa os dados da aplicação e as regras do negócio que governam o acesso e a modificação dos dados.
O modelo mantém o estado persistente do negócio e fornece ao controlador a capacidade de acessar as funcionalidades da aplicação encapsuladas pelo próprio modelo.
Vantagens do modelo MVC :
Como o modelo MVC gerencia múltiplos visualizadores usando o mesmo modelo é fácil manter , testar e atualizar sistemas múltiplos
É muito simples incluir novos clientes apenas incluindo seus visualizadores e controles
Torna a aplicação escalável
É possível ter desenvolvimento em paralelo para o modelo , visualizador e controle pois são independentes.
Desvantangens do modelo MVC:
Requer uma quantidade maior de tempo para analizar e modelar o sistema
Requer pessoal especializado
Não é aconselhável para pequenas aplicações
Acoplamento de Controle
Um controlador é um objeto responsável por tratar um evento de sistema (caso de uso), mas que pertence à camada de domínio.
Problema:
Que objeto, fora da camada de apresentação, deve receber e coordenar a solicitação da execução de uma operação?
Solução:
Uma classe que representa uma das seguintes opções:
– Representa o ”sistema”, todo o negócio ou organização (Controlador fachada);
– Representa todo o negócio e
– Representa algo do mundo real que é ativo e envolvido na tarefa (Controlador de papel);
– Representa um “tratador artificial” dos eventos de sistema de um caso de uso (Controlador de caso de uso)
O controlador é o primeiro objeto fora da camada de interface com o usuário a receber ou tratar uma mensagem para o sistema.
Existem duas alternativas possíveis para o objeto controlador:
- Um objeto Controlador para todo o sistema
- Um objeto Controlador por Caso de Uso
Os benefícios do padrão controlador são:
--- Diminui a sensibilidade da camada de apresentação em relação à lógica de domínio
--- Oportunidade para controlar o estado do caso de uso.
» Evita que objetos da camada apresentação tratem as operações do sistema;
» Aumenta o potencial de reutilização;
» Possibilita o controle de seqüência de operações do sistema.
Padrão Baixo Acoplamento:
O padrão baixo acomplamento tem como objetivo a redução e miniminização da conexão de um objeto com outros. Esta conexão esta relacionada a ter conhecimento sobre os outros objetos ou simplemente depender de outros objetos. De forma sujacente manter o acoplamento baixo significa redizir o impacto de mudança já que ao se alterar um objeto um mínimo de outros objetos serão afetados.
Problema: Como aumentar independência dos objetos de forma a possibilitar a sua reutilização?
Solução: Atribuindo responsabilidades de maneira que o acoplamento permaneça fraco.
Resulta num acoplamento geral mais fraco entre as classes:
»Resulta em classes mais independentes;
»Reduz o impacto de mudanças;
»Aumenta o potencial de reutilização;
»Não deve ser utilizado isolado dos outros padrões.
public class Produto
{
private integer idProduto;
private string descrição;
private double valorUnitário;
public string getdescrição(){
return dscrição;
} public void setDescrição(string valor)
{ descrição=valor;
}
public class ItemVenda {
private double qtde;
private Produto p;
public void setP (Produto p) {
this.p = p;
}
public class Venda {
private Set
private Date dataVenda;
private integer idvenda;
public criar Itemvenda (Produto P, double qtde)
{
Itemvenda i =new ItemVenda();
i.setP(p);
i.setQtde(qtde);
itemVendaList.add(i);
}
Atribui à classe "A" a responsabilidade de instanciar a classe B caso algumas destas condições sejam verdadeiras (quanto mais alternativas sejam verdadeiras melhor).
Padrão Criador
Problema: Quem deveria ser responsável pela criação de uma nova instância de classe?
Solução: Atribuir à classe B a responsabilidade de criar uma instância da classe A se uma das seguintes condições for verdadeira:
– B agrega objetos A;
– B contém objetos A;
– B registra instâncias de objetos A;
– B usa de maneira muito próxima objetos A;
– B tem os dados de inicialização de A (B é expert em
relação à criação de A.
Acoplamento
O acoplamento é uma medida de quão fortemente uma classe está conectada a outras classes, tem conhecimento das mesmas ou depende delas.
Problema: Como aumentar independência dos objetos de forma a possibilitar a sua reutilização?
Solução: Atribuindo responsabilidades de maneira que o acoplamento permaneça fraco.
Alta Coesão
Coesão é a medida de quão fortemente relacionadas e focalizadas são as responsabilidades de uma classe.
Problema: Como manter a complexidade de um sistema ou objeto sob controle?
Solução: Atribuindo responsabilidades de maneira que a coesão permaneça alta.
Acoplamento fraco e coesão alta são princípios a serem seguidos durante todas as decisões de projeto; são objetivos adjacentes a serem levados em conta continuamente.
Uma classe com coesão baixa faz muitas coisas não relacionadas, ou executa demasiado trabalho.
»Coesão funcional alta especialização das classes;
»Uma classe com Coesão alta tem um número relativamente pequeno de métodos, com funcionalidades altamente relacionadas;
»A manutenção e as melhorias do sistema são facilitadas;
»Reduz o impacto de mudanças;
»Aumenta o potencial de reutilização;
»Não deve ser utilizado isolado dos outros padrões.
Um sistema O.O. é composto por vários objetos que colaboram entre si, trocando "mensagens" para satisfazer aos requisitos do sistema proposto, o planejamento de como dividir as responsabilidades entre os objetos é essencial para obter um sistema fácil de entender, robusto, reutilizável e extensível.
GRASP: ajuda a definir as responsabilidades, o seu estudo possibilita entender os princípios de um bom projeto O.O.
Responsabilidades: São as descrições do que os objetos tem de fazer, os métodos são as implementações das responsabilidades.
Obs: nem sempre uma responsabilidade é satisfeita somente por um método, grandes responsabilidades são divididas para manter a coesão da Classe.
Os principais padrões GRASP:
- Especialista
- Criador
- Coesão alta
- Acoplamento fraco
- Controlador
Especialista na Informação:
Problema: Qual é o princípio geral para a atribuição de responsabilidades aos objetos?
Solução: Atribua a responsabilidade ao especialista: a classe que tem as informações necessárias para assumir a responsabilidade.
Benefícios: O encapsulamento da informação é mantido uma vez que os objetos usam seus próprios dados para realizar as tarefas.
Isto normalmente leva a um baixo acoplamento entre as classes.
O comportamento do sistema é distribuído entre as classes que têm as informações, encorajando a definição de classes mais "leves", mais fáceis de entender e de manter.
Contradição: Em algumas situações, a solução sugerida pelo especialista pode ser indesejada, por às vezes causar baixa coesão.
Padrões GRASP - (General Responsibility Assignment Software Patterns)
Os padrões GRASP fornecem uma abordagem sistemática para a atribuição de responsabilidades às classes do projeto.
As responsabilidades estão relacionadas às obrigações de um objeto em termos do seu comportamento.
Elas são de dois tipos:
-- Conhecer
-- Fazer
As responsabilidades de fazer de um objeto incluem:
- Fazer algo ele próprio
- Iniciar ações em outros objetos
- Controlar e coordenar atividades em outros objetos
As responsabilidades do conhecer de um objeto incluem:
- Conhecer dados privados encapsulados
- Conhecer objetos relacionados
- Conhecer coisas que ele pode derivar ou calcular
Exemplos:
• Uma Venda tem a responsabilidade de criar linha de detalhe (fazer algo).
• Uma Venda tem a responsabilidade de saber sua data (conhecer algo).
Granularidade
Uma responsabilidade pode envolver um único método (ou poucos).
Exemplo: Criar uma linha de detalhe.
Uma reponsabilidade pode envolver dezenas de classes e métodos.
Exemplo: Responsabilidade de fornecer acesso a um BD.
Uma responsabilidade não é igual a um método.
Mas métodos são usados para implementar responsabilidades.
Uma responsabilidade não é a mesma coisa que um método.
Os métodos são implementados para satisfazer responsabilidades.
As responsabilidades são implementadas usando métodos que agem sozinhos ou colaboram com outros métodos e objetos.
Referências:
LINK 1
LINK 2
Diagrama de Sequência:
O diagrama de seqüência dá ênfase à ordenação temporal das mensagens e as principais características que o diferencia do diagrama de colaboração são: possui linha de vida do objeto que é uma linha tracejada que representa a existência de um objeto em um período de tempo e também existe o foco de controle que é um retângulo alto e estreito que mostra o período durante o qual o objeto está desempenhando uma ação, diretamente ou por meio de um procedimento subordinado, enquanto que o diagrama de colaboração possui um caminho para identificar se o objeto é global, local etc e possui também um número de seqüência que indica a ordem temporal de uma mensagem.
Exemplo:
Diagrama de Colaboração:
O diagrama de colaboração dá ênfase à organização estrutural dos objetos que enviam a recebem mensagens. O diagrama de colaboração é formado colocando-se primeiro os objetos que participam da interação como os vértices de um gráfico, depois, representa-se os vínculos que conectam esses objetos como os arcos dos gráficos e finalmente, adorna-se esses vínculos com as mensagens que os objetos enviam e recebem.
Exemplo:
Obs: Os diagramas de seqüência e colaboração são semanticamente equivalentes, sendo assim, o diagrama de uma forma pode ser convertido no outro sem qualquer perda de informação, entretanto, isso não significa que os dois diagramas visualizarão as mesmas informações explicitamente.
Link Referência Bibliográfica
Projeto Orientado a Objeto:
Objetivo: Projetar sistemas usando objetos auto-contidos e classes de objetos.
Análise vs Projeto
Análise: é modelar um problema, é uma atividade de investigação. "O que deve ser feito", ou seja, entender.
Projeto: é a modelagem da solução, se dedica a desenvolver um modelo orientado a objeto de um sistema de software para implementar os requisitos.
Durante a Análise OO, a ênfase está em achar e descrever objetos (ou conceitos) no domínio do problema.
Durante o Projeto orientado a objeto, a ênfase está em achar objetos lógicos de software que poderão ser eventualmente implementados usando uma linguagem de programação OO. Esses objetos podem ter atributos ou métodos.
Continua....
