Mostrando postagens com marcador Design Patterns. Mostrar todas as postagens
Mostrando postagens com marcador Design Patterns. Mostrar todas as postagens

terça-feira, 19 de março de 2013

Entenda o Domain Driven Design


Olá amigos e amigas tudo bem? Hoje vou resumir de uma forma mais "Mamão com açucar" O que é o DDD e imaginar exemplos utilizando o DDD para como resolver um determinado problema ok?

Provavelmente vc se lembra daqueles 3 gordinhos da Embratel não é? "pegue o seu d d dedo e disque o nu número da embratel, antes do ddd é 021..." Pois bem, eles não tem nada haver com o que eu vou explicar, mas fica ai como imagem de apresentação.


Existem duas maneiras de vc ter caído aqui no meu blog, a é vc conhecer meu blog e veio aqui para ver novos artigos(a grande menoria). A é pq vc está pesquisando sobre DDD e encontra muito artigo cheio de filosofia e acaba não absorvendo muito bem, e provavelmente vc não tem muito tempo para lêr o livro do Evans então chegas mais que vou resumir essa parada pra vc!

Antes de mais nada vamos ao entendimento básico, Domain Driven Design significa entre outras palavras Projeto Orientado a Domínio. Que veio do título do livro do Eric Evans. O livro do Evans é basicamente um catálogo de padrões baseados em experiências do próprio Evans ao longo de mais de 20 anos de desenvolvimento de software utilizando técnicas de Orientação a Objetos.

O DDD é basicamente o uso ideal da Orientação a Objetos(PRONTO ACABEI DE EXPLICAR TUDO PODE IR EMBORA).

Não fique bravo(a) comigo pois essencialmente é isso mesmo, DDD é o uso inteligente da orientação a objetos para resolver diversos problemas.

Vamos lá open your mind.


Os decoradores(entende-se pessoas que decoram) de Orientação a Objetos tem um problema grave com isso pois quando se fala em OO as primeiras coisas que vem na mente são "classes, herança, polimorfismo, encapsulamento, lalala...". Mas essa são as regras básicas e técnicas da OO, a grande sacada dela está em independência de tecnologia, mínimo de acoplamento, reutilização de código, alinhamento do código com o negócio, coerência em problemas reais... Olha só, agora sim estamos falando de OO resolvendo problemas reais e essa é a essencia campeonato(entende-se campeão).
 


Vamos ter um papo sério sem muita filosofia esse não é um artigo é mais uma conversa ok? Então vamos pensar, o Projeto Orientado a Domínio é essencialmente entendermos o negócio e tornar o código lógico a esse negócio, coeso a esse negócio, aquele papo de entity não pode ter lógica é justamente o OPOSTO do DDD pois sim vamos ter uma camada de domínio cujo qual minhas entidades são inteligentes! Separar a lógica em serviços que manipulam as entidades muitas vezes torna o reuso impossivel e é basicamente dizer eu sou um macaco que batuco o teclado com a intenção de gerar código....

O DDD não vai exatamente te impor como vc faz a arquitetura do seu software mas sim te abrir a mente sobre como dar funções para quem realmente merece afinal, vc não mandaria um engenheiro fazer uma cirurgia plástica não é?

Veja um exemplo do DDD por "cima":




Interface de Usuário – parte responsável pela exibição de informações do sistema ao usuário e também por interpretar comandos do usuário;

Aplicação – essa camada não possui lógica de negócio. Ela é apenas uma camada fina, responsável por conectar a Interface de Usuário às camadas inferiores;

Domínio – representa os conceitos, regras e lógicas de negócio. Todo o foco de DDD está nessa camada. Nosso trabalho, daqui para frente, será aperfeiçoar e compreender profundamente essa parte;

Infra-estrutura – fornece recursos técnicos que darão suporte às camadas superiores. São normalmente as partes de um sistema responsáveis por persistência de dados, conexões com bancos de dados, envio de mensagens por redes, gravação e leitura de discos, etc.


O DDD basicamente começa por essa premissa básica de conhecer de fato o domínio, mas ele é muito mais amplo e mais complexo por isso eu tentei aqui dar a introdução desse mundo partindo do principio de entender essa ideia.

Existem alguns pontos importantes abordados no DDD que são o uso da mesma linguagem, evitar traduções indevidas, quebrar o problema em camadas, entender entidades, agregados, objetos de valor, fábricas, serviços, repositórios, módulos entre outros.


Segue aqui a primeira versão de um slide da minha palestra sobre Domain Driven Design



Caso vc queira se aprofundar nos estudos então é melhor ler o livro do Evans 
http://www.informit.com/store/domain-driven-design-tackling-complexity-in-the-heart-9780321125217



Até a próxima.


terça-feira, 2 de outubro de 2012

Design Pattern Builder no PHP

Olá amigos tudo bem? Vamos "filosofar" um pouco? Vamos falar sobre o Builder um design pattern que "deriva" do Factory mas tem suas particularidades.

ANNTISiSS DE INICIAR O ARTIGO VOU DAR UM AVISO AOS NAVEGANTES:
    Não use um design pattern pq simplesmente ele é "elegante" ou então pq vc quer aprender e para isso vai jogar em código de produção para testar.
   Use os patterns quando vc REALMENTE PRECISAR, vou repetir... REALMENTE PRECISAR! Muitas vezes as pessoas tornam algo simples em algo absurdamente complexo por não saber usar ou usar os os patterns em hora errada, se vc tem dúvidas se usa ou não o pattern procure entender melhor o problema e a solução que ele propõe antes de fazer uma tremenda de uma porcaria no código. Ok? :)


Como o próprio nome já diz ele é um pattern construtor(builder), otimo para quando vc precisa criar objetos completos que atendam uma certa complexidade. No Pattern Builder um temos um diretor e um construtor trabalhando juntos para construir um objeto. O diretor controla a construção e especifica quais partes e variações entram em um objeto. O construtor sabe como montar a especificação do determinado objeto. Em resumo a intenção do padrão Construtor(Builder), é separar a construção de um objeto complexo, de modo que o mesmo processo de construção possa criar várias representações diferentes.

Veja um exemplo claro de diagrama mostrando a implementação:
O diagrama é a mesma coisa que dizer que:
A classe Builder especifica uma interface abstrata para a criação de partes de um objeto Product.
O ConcreteBuilder constrói e reúne peças do produto pela implementação da interface Builder. Ele define e mantém o controle da representação que cria e fornece uma interface para guardar o produto
A classe Director constrói o objeto complexo usando a interface do Construtor
A Product representa o objeto complexo que está sendo construído.

Veja um exemplo classico de implementação:
BUILDER
  1. <?php
  2. class Fabrica {
  3.     public function Construir($oVeiculo) {
  4.         $oVeiculo->Iniciar();
  5.         $oVeiculo->construirPortas();
  6.         $oVeiculo->construirMotor();
  7.         $oVeiculo->construirPneus();
  8.     }
  9. }
  10. abstract class ConstrutorVeiculo {
  11.     protected $Veiculo;
  12.     abstract public function Iniciar();
  13.     abstract public function construirMotor();
  14.     abstract public function construirPortas();
  15.     abstract public function construirPneus();
  16. }
  17. class Carro extends ConstrutorVeiculo {
  18.     public $Veiculo;
  19.     public function Iniciar() {
  20.         $this->Veiculo = new Veiculo('Carro');
  21.     }
  22.     public function construirPortas() {
  23.         $this->Veiculo->aPartes['Portas'] = 4;
  24.     }
  25.     public function construirMotor() {
  26.         $this->Veiculo->aPartes['Motor'] = 1;
  27.     }
  28.     public function construirPneus() {
  29.         $this->Veiculo->aPartes['Pneus'] = 4;
  30.     }
  31. }
  32. class Moto extends ConstrutorVeiculo {
  33.     public $Veiculo;
  34.     public function Iniciar() {
  35.         $this->Veiculo = new Veiculo('Moto');
  36.     }
  37.     public function construirPortas() {
  38.         $this->Veiculo->aPartes['Portas'] = 0;
  39.     }
  40.     public function construirMotor() {
  41.         $this->Veiculo->aPartes['Motor'] = 1;
  42.     }
  43.     public function construirPneus() {
  44.         $this->Veiculo->aPartes['Pneus'] = 2;
  45.     }
  46. }
  47. class Veiculo {
  48.     private $sTipo = NULL;
  49.     public $aPartes = array();
  50.     public function __construct($sTipo) {
  51.         $this->sTipo = $sTipo;
  52.     }
  53.     public function ObterInformacoes() {
  54.         printf("--------------------------\n");
  55.         printf("Veículo: %s \n", $this->sTipo);
  56.         printf("Motor:   %s \n", $this->aPartes['Motor']);
  57.         printf("Portas:  %s \n", $this->aPartes['Portas']);
  58.         printf("Pneus:   %s \n", $this->aPartes['Pneus']);
  59.     }
  60. }
  61. $Fabrica = new Fabrica;
  62. $Carro = new Carro;
  63. $Moto = new Moto;
  64. $Fabrica->Construir($Carro);
  65. $Carro->Veiculo->ObterInformacoes();
  66. $Fabrica->Construir($Moto);
  67. $Moto->Veiculo->ObterInformacoes();
  68. ?>


A explicação acima fala por si só não é? Mesmo assim qualquer dúvida... Fui

terça-feira, 5 de junho de 2012

Observer - Design Patterns

Design Patterns Observer

Neste artigo abordaremos a modelagem e prática de um padrão de projeto (Design Patterns) bastante importante do GoF (Gang of Four) que é o Padrão Observer.

A essência desse padrão está na possibilidade de uma classe poder fazer uma 'notificação' a um conjunto de classes associadas de que o Estado (Conjunto de Atributos) dela foi alterado por algum motivo. A definição do padrão observer descrita pelos criadores é a seguinte:
"Definir uma dependência um-para-muitos entre objetos para que quando um objeto mudar de estado, todos os seus dependentes sejam notificados e atualizados automaticamente." [GoF]
Você deve estar pensando "Eu posso fazer essa notificação manualmente ou até mesmo utilizando eventos como actionPerformed para fazer a notificação através de chamas a métodos de cada instância (ufaa)". Porém dessa maneira você estará criado um sistema com alto acoplamento e de difícil manutenabilidade.
Utilizando o padrão Observer conseguimos reduzir o uso do relacionamento bidirecional por meio de interfaces e classes abstratas, separando a abstração para ter um alto nível de coesão e baixo acoplamento.
Para ficar mais intuitivo vamos fazer o uso de exemplos. Imagine um operário de obras que esta trabalhando em uma construção junto com seus 'companheiros'.. O fato de uma sirene tocar implica em uma mudança (mudança de estado), que pode ser um sinal para a hora do almoço, pode ser o final do expediente e etc.
Temos então o seguinte ambiente, o objeto observável (Sirene) e os observadores (Operários). Quando o objeto observável alterar o seu estado, enviará um sinal sonoro (mensagem) alertando os objetos observadores.
Padrões de Projeto - Observer








Vamos definir as abstrações, chamaremos de Operário a interface do operário e Sirene a interface da sirene como mostrado abaixo:
Padrões de Projeto - Observer Interface
Perceba que as duas abstrações se relacionam entre si, relacionamento entre interfaces, ou seja, estamos deixando nossa aplicação mais independente separando-as das classes concretas
Na interface Sirene nós especificamos parte do que ela poderá fazer, no caso adicionar ou retirar um observador, da mesma maneira seguiremos com o Operário, sendo que, no mais alto nível de abstração, o mínimo que um observador irá sofrer é o fato de ser notificado (atualizar). Se o operário vai ou não responder ao chamado não cabe a interface.
Com as interfaces em mãos podemos montar nosso diagrama, criaremos duas classes que vão implementar essas interfaces, sendo elas SireneConcreta e OperarioConcreto, conforme vemos abaixo:
Diagrama de Classe Observer
Na classe SireneConcreta criaremos todos os outros métodos necessários para o bom funcionamento da sirene e o método notificarObservadores que ira "varrer" o ArrayList que contem uma lista de observadores.
A classe concreta não foge a regra, irá implementar além do método atualizar todos os métodos dos operários.
Tendo toda a estrutura diagramatizada você poderá utilizar o próprio programa de modelagem (se estiver disponível) para gerar o código da nossa estrutura. Eu estou utilizando para esse fim o Enterprise Architect, porém qualquer um com suporte a UML 2.0 (de preferência) poderá ser usado, seja Netbeans, ArgoUML, ou plugins para eclipse..
Implementando nossas interfaces, teremos,
Interface Sirene:
 
public interface Sirene {
 
 public void adicionarObservador( Operario o );
 public void removerObservador( Operario o );
 
}
 
Interface Operario:
 
public interface Operario {
 
 public void atualizar(Sirene s);
 
}
 
Com as nossas abstrações prontas, podemos dar inicio a construção das classes concretas, teremos,
Classe SireneConcreta:
 
import java.util.ArrayList;
import java.util.Iterator;
 
public class SireneConcreta implements Sirene {
 
 private Boolean alertaSonoro = false;
 private ArrayList observadores = new ArrayList();
 
 public void alterarAlerta(){
  if(alertaSonoro)
   alertaSonoro = false;
  else
   alertaSonoro = true;
  notificarObservadores();
 }
 
 public Boolean getAlerta(){
  return alertaSonoro;
 }
 
 public void adicionarObservador(Operario o) {
  observadores.add(o);
 }
 
 public void removerObservador(Operario o) {
  observadores.remove(o);
 }
 
 private void notificarObservadores(){
  Iterator i = observadores.iterator();
  while(i.hasNext()){
   Operario o = (Operario) i.next();
   o.update(this);
  }
 }
}
 
Perceba que chamamos o método notificarObservadores exatamente quando o objeto SireneConcreta altera seu estado. Na implementação do método notificarObservadores nos fazemos uma varredura simples e informando a cada instância dele mesmo que o objeto que estava sendo observado mudou seu estado. Repare que estamos trabalhando sempre com as Interfaces ao invés das classes concretas.
Classe OperarioConcreto:
 
public class OperarioConcreto implements Operario {
 
 private SireneConcreta objetoObservado;
 
 public OperarioConcreto(SireneConcreta o){
  this.objetoObservado = o;
  objetoObservado.adicionarObservador(this);
 }
 
 public void atualizar(Sirene s) {
  if(s == objetoObservado){
   System.out.println("[INFO] A Sirene mudou seu
estado para: " + objetoObservado.getAlerta());
  }
 }
}
 
Com o construtor dessa maneira podemos ao passo de criar o observador e já setar como parâmetro o objeto observado, logo abaixo podemos chamar o método adicionarObservador que passa por referência a sua própria instância!. Interessante, não?
Quando o método atualizar é chamado nós precisamos checar se a sirene que alterou o estado é a mesma que estamos observando.
Com toda estrutura implementada é hora de testar, para tal vamos criar a classe GerenciadorSirene:
 
public class GerenciadorSirene {
 
 public static void main(String[] args) {
 
  SireneConcreta sirene = new SireneConcreta();
  // Sirete ja começa com valor default false
 
  OperarioConcreto obs1 = new OperarioConcreto(sirene);
  OperarioConcreto obs2 = new OperarioConcreto(sirene);
  // Já passando a sirene como parametro
 
  sirene.alterarAlerta();
  // Nesse momento é chamado o método atualizar
  // das instâncias obs1 e obs2, saída:
  // [INFO] A Sirene mudou seu estado para: true
  // [INFO] A Sirene mudou seu estado para: true
 
  sirene.alterarAlerta();
  //[INFO] A Sirene mudou seu estado para: false
  //[INFO] A Sirene mudou seu estado para: false
 
  // Obs: 2 saídas porque temos 2 observadores
 }
}
 
É possível dar nomes aos observadores criando um atributo String dentro de OperatorConcreto e passando seu nome para o construtor como segundo parâmetro, para ficar mais fácil diferenciá-los.

Artigo original de: http://blog.rafaelcapucho.com/