domain driven design php tdc2014

35
pen4education Domain-Driven Design Paulo Victor L. L. Gomes Projeto Orientado a Domínio com PHP

Upload: paulo-victor-gomes

Post on 13-Jun-2015

844 views

Category:

Technology


2 download

DESCRIPTION

Domain Driven Design PHP TDC2014

TRANSCRIPT

Page 1: Domain Driven Design PHP TDC2014

pen4education

Domain-Driven Design

Paulo Victor L. L. Gomes

Projeto Orientado a Domínio com PHP

Page 2: Domain Driven Design PHP TDC2014

pen4education

Domain-Driven Design?

Domain-Driven Design é uma abordagem para o Desenvolvimento de Software que estabelece uma forte ligação entre a implementação e o modelo evolutivo dos conceitos de negócio. Implementação X Negócios

Page 3: Domain Driven Design PHP TDC2014

pen4education

Fundamentação

Onde colocar aregra de negócio?

Page 4: Domain Driven Design PHP TDC2014

pen4education

Fundamentação

“Vai escrevendo código ai, quando precisar coloque na camada de apresentação, no banco de dados nos controles, modelos, na configuração do webserver e não esquece do xml e aquele if maroto no APPLICATION_ENV”

Page 5: Domain Driven Design PHP TDC2014

pen4education

Fundamentação

Encapsule, Daniel San

Page 6: Domain Driven Design PHP TDC2014

pen4education

Encapsulamento

Encapsule a regra de negócio! Fazendo isso, garantimos consistência e simplicidade.

Page 7: Domain Driven Design PHP TDC2014

pen4education

Orientação a Objetos?

Page 8: Domain Driven Design PHP TDC2014

pen4education

Orientação a Objetos

Meu framework já usa Orientação a Objetos.

Esse papo é muito antigo e eu já superei esse problema.

Page 9: Domain Driven Design PHP TDC2014

pen4education

Orientação a ObjetosOlha meu código...public function imagodAction() {

$local=VdModel::getLocalStorageAdapter();$items=$purchase->getItemCollection()->getItems();$Items=$this-

>cart->getItems();$index=array();$catalogHelper=newGodHelper();$quantityCartByidentifier=array();

$itemsRemove=array();foreach($itemsas$salespurchaseItem){$quantityCartByidentifier[$salespurchaseItem-

>getidentifier()]=(isset($quantityCartByidentifier[$salespurchaseItem->getidentifier()])?

$quantityCartByidentifier[$salespurchaseItem->getidentifier()]+1:1);foreach($itemsas$salespurchaseItem){if

($salespurchaseItem->getBundleidentifier()&&!isset($index[$salespurchaseItem->getBundleidentifier()]))

{'uniqueAttributes'=>CatalogHelper::getSimpleUniqueAttributes($product,$salespurchaseItem-

>getidentifier()),'color_cart'=>isset($product['meta']['color_family'])?$product['meta']

['color_family']:'','shipment_delivery_time'=>$salespurchaseItem->getShipmentTotalDeliveryTime(),)),

'bundleproducts'=>array($simples[$salespurchaseItem->getidentifier()]=>(isset($simples[$salespurchaseItem-

>getidentifier()])?$simples[$salespurchaseItem->getidentifier()]+1:1)),);$bundleproduct=$local->get

('product',(strstr($salespurchaseItem->getBundleidentifier(),'-',true)));

//resolveproducturable$product=$local->get('product',($simples[$salespurchaseItem->getidentifier()]));

$simple=$product['simples'][$salespurchaseItem->getidentifier()];$identifierHandle=$salespurchaseItem-

>getBundleidentifier();if(isset($bundleproduct['products'][$simples[$salespurchaseItem->getidentifier()]]

['quantity_items'])){$quantityItems=$bundleproduct['products'][$simples[$salespurchaseItem-

>getidentifier()]]['quantity_items'];}else{$quantityItems=1;$itemsRemove[]=$salespurchaseItem-

>getBundleidentifier();}$index[$identifierHandle]['salespurchaseItem']->setShipmentTotalDeliveryTime(max

($index[$identifierHandle]['salespurchaseItem']->getShipmentTotalDeliveryTime(),$salespurchaseItem-

>getShipmentTotalDeliveryTime()));$index[$identifierHandle]['stock']=min($simple['meta']['quantity'],$index

[$identifierHandle]['stock']);$index[$identifierHandle]['cart_rule_discount']+=$salespurchaseItem-

>getCartRuleDiscount();if(isset($index[$identifierHandle]['bundleproducts'][$simples[$salespurchaseItem-

>getidentifier()]])){if($index[$identifierHandle]['bundleproducts'][$simples[$salespurchaseItem-

>getidentifier()]]<$quantityItems){$index[$identifierHandle]['salespurchaseItem']->setUnitPrice($index

[$identifierHandle]['salespurchaseItem']->getUnitPrice()+$salespurchaseItem->getUnitPrice());$index

[$identifierHandle]['salespurchaseItem']->setPaidPrice($index[$identifierHandle]['salespurchaseItem']-

>getPaidPrice()+$salespurchaseItem->getPaidPrice());$index[$identifierHandle]['salespurchaseItem']-

>setOriginalUnitPrice($index[$identifierHandle]['salespurchaseItem']->getOriginalUnitPrice()

+$salespurchaseItem->getOriginalUnitPrice());}$index[$identifierHan}; if($salespurchaseItem[‘ai’][‘meu’]

[‘deus’][‘eu’][‘sou’][‘o’][‘cara’][‘da’][‘programacao’][‘ever’] == 234 && ..

Page 10: Domain Driven Design PHP TDC2014

pen4education

Orientação a Objetos

Quando pensamos em POO logo pensamos em Classes, Encapsulamento, Polimorfismo, Herança...

POO é mais que isso, a essência da POO é alinhamento do código com o negócio, reutilização, mínimo de acoplamento, linguagem natural...

Page 11: Domain Driven Design PHP TDC2014

pen4education

Domain Driven Design

Como eu uso? De onde eu começo?

sudo apt-get install ddd (#sqn)

Page 12: Domain Driven Design PHP TDC2014

pen4education

O desafio proposto...

Comunicação entre equipe de produto e desenvolvimento

Page 13: Domain Driven Design PHP TDC2014

pen4education

O mundo como ele é...

Page 14: Domain Driven Design PHP TDC2014

pen4education

Linguagem Ubíqua

Definições de Ubíqua

“O termo foi usado pela primeira vez pelo cientista Norte-Americano Mark Weiser em 1988 e publicado em 1991 no seu artigo The Computer for the 21st Century”

“termo usado para descrever a onipresença da informática no cotidiano das pessoas”

“Computação ubíqua tem como objetivo tornar a interação homem computador invisível, ou seja, integrar a informática com as ações e comportamentos naturais das pessoas”

Para que um software atenda um domínio, é necessário que se estabeleça, em primeiro lugar, uma linguagem Ubíquia ou seja, linguagem comum, com termos bem definidos, que fazem parte do domínio do negócio e que são usados por todas as pessoas que fazem parte do processo de desenvolvimento.

Page 15: Domain Driven Design PHP TDC2014

pen4education

Model Driven Design

Projeto Dirigido pelo Modelo (Model Driven Design – MDD). A ideia por trás de MDD é a de que o seu modelo abstrato deve ser uma representação perfeita do seu domínio.

O MDD defende o processo ágil, o trabalho em equipe ou seja, especialistas em negócio, desenvolvedores e arquitetos trabalhando juntos.

Diagramas da UML ajudam o entedimento do domínio.

Page 16: Domain Driven Design PHP TDC2014

pen4education

Blocos de ConstruçãoEncapsulando o modelo de domínio.

Interface de Usuário – Interação com o 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 compreenderprofundamente 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, etc.

Page 17: Domain Driven Design PHP TDC2014

pen4education

Entidades

Muitos objetos não são fundamentalmente definidos por seus atributos, mas sim por uma linha de continuidade e identidade

Page 18: Domain Driven Design PHP TDC2014

pen4education

Entidades<?php

class Exercicio_Negocio_Exercicio {

private $id; private $nome; private $descricao; private $exercicioMercanismo; private $autocorreção;

public function getExercicioMercanismo() {

if ($this->exercicioMecanismo == null && $this->entidadeValida()) { $elementDAO = Exercicio_Infraestrutura_Model_Dao_ExercicioDAOFactory::getInstance()->getExercicioDAO(); $this->exercicioMecanismo = $elementDAO->getMecanismoExercicio($this); }

return $this->exercicioMercanismo;

}

public function gravar() { $exercicioDAO = Exercicio_Infraestrutura_Model_Dao_ExercicioDAOFactory::getInstance()->getExercicioDAO(); return $exercicioDAO->persist($this); }

public function getExercicioConteudo(\ACS\Negocio\Nucleo\Usuario $usuario) { return Exercicio_Negocio_ExercicioConteudo::buscarPorUsuarioExercicio($this, $usuario); }

private function entidadeValida() {

$entidadeValida = false; if ($this->getId() != null) { $entidadeValida = true; }

return $entidadeValida; }}

Page 19: Domain Driven Design PHP TDC2014

pen4education

Objetos de valor

Muitos objetos não possuem nenhuma identidade conceitual. Esses objetos descrevem alguma característica de alguma coisa.

Page 20: Domain Driven Design PHP TDC2014

pen4education

Objetos de valor<?php

namespace Product\Model\Vo;

class Price{

Const CURRENCY = 'R$';

private $price; private $discountPercentage; private $discount;

// get's and set's

public function getPrice() { // business rules to return price }

public function setSpecialPrice($setSpecialPrice) { if ($specialPrice >= $this->getPrice()) { $specialPrice = null; } $this->specialPrice = $specialPrice; }

public function setSpecialPriceComparison($specialPriceComparison) { $this->specialPriceComparison = $specialPriceComparison; if ($this->verifyPriceComparison()) { $this->setSpecialPrice($specialPriceComparison); } }

private function verifyPriceComparison() { // verify channels... }}

Page 21: Domain Driven Design PHP TDC2014

pen4education

Serviços

Ás vezes, a situação simplesmente não se trata de alguma coisa. Em algums casos, um design mais limpo e mais pragmático inclui operações que não pertencem conceitualmente a nenhum objeto. Em vez de forçar a questão, podemos seguir os limites naturais do espaço do problema e incluir SERVIÇOS explicitamente no modelo.

Page 22: Domain Driven Design PHP TDC2014

pen4education

Serviços<?php

namespace Product\Service;

class Catalog {

Const BALANCE_STANDARD_STOCK = 0;

protected $catalogRepo;

public function __construct(RepositoryInterface $catalogRepo) { $this->catalogRepo = $catalogRepo; }

public function getBalanceStock(Item $item) { $balanceStock = self::BALANCE_STANDARD_STOCK; $stockReserved = $this->catalogRepo->getQuantityReservedStock($item);

$currentBalance = (int) ($item->getQuantity() - $stockReserved);

if ($currentBalance > $balanceStock) { $balanceStock = $currentBalance; }

return $balanceStock; }}

Page 23: Domain Driven Design PHP TDC2014

pen4education

Agregados

O design detalhado de associações ajuda a simplificar um comportamento de um objeto mas, em diversos casos, existe a necessidade de explorar a modelagem se adequando com o domínio complexo.

Page 24: Domain Driven Design PHP TDC2014

pen4education

Agregados<?php

namespace Product\Model\Aggregate;

class Product extents AbstractProduct{ /** @var Product\Model\Vo\Price */ protected $price;

/** @var Product\Model\Collection\Item */ protected $itemCollection;

public function getItemCollection() { if ($this->hasItemCollection() && $this->getIdentification()) { $this->setItemCollection($this->getProductService()->getItemCollectionByIdentification($this->getIdentification())); } }

public function hasItemCollection() { $hasItemCollection = false;

if ($this->ItemCollection) { if ($this->ItemCollection instanceof Product\Model\Collection\Item) { $hasItemCollection = true; } }

}

public function getQuantity() { $quantity = 0; if (($this->hasItemCollection()) && ($this->ItemCollection->count() >= 1)) { $quantity = $this->calculateQuantity(); }

return $quantity; }

}

Page 25: Domain Driven Design PHP TDC2014

pen4education

Fábricas

Quando a criação de um objeto ou um AGREGADO inteiro se torna complicada ou revela uma grande parte de estrutura interna, as FÁBRICAS fornecem o encapsulamento.

Page 26: Domain Driven Design PHP TDC2014

pen4education

Fábricas

class OrderFactory{ public static function createOrder(ICustomer $customer, ProductCollection $productCollection) {

$order = new Order($customer, $productCollection); $customerPayment = PaymentFactory::createCustomerPayment($customer);

if ($customerPayment->hasRecurrent()) { $order->setPayment($customerPayment) }

return $order; } }

Page 27: Domain Driven Design PHP TDC2014

pen4education

Repositórios

Associações nos permitem achar um objeto baseado em sua relação com outro objeto. Mas é preciso ter um ponto de partida para uma travessia até uma ENTIDADE ou um VALOR no meio do seu ciclo de vida.

Page 28: Domain Driven Design PHP TDC2014

pen4education

Repositórios<?php

namespace Application\Model;

class ConfigurationRepository implements RepositoryInterface{

protected $dataMapper = null;

protected $entityContext;

public function __constuct(DataMapper $dataMapper) { $this->dataMapper = $dataMapper; $this->dataMapper->entityContext($this->getEntityContext()); }

public function findAll() { return $this->dataMapper->listAll(); }

public function findById($id) { $configurationEntity = false; $configurations = $this->dataMapper->findBy(array('id' => $id)); if ($configurations) { $configurationEntity = $configurations->current(); }

return $configurationEntity; }

}

Page 29: Domain Driven Design PHP TDC2014

pen4education

Tijolos de construção

Page 30: Domain Driven Design PHP TDC2014

pen4education

MagiZ, a Plataforma Educacional Online completa, configurável e fácil de usar.www.magiz.com.br

Page 31: Domain Driven Design PHP TDC2014

pen4education

Page 32: Domain Driven Design PHP TDC2014

pen4education

Minha última experiência

Page 34: Domain Driven Design PHP TDC2014

pen4education

Perguntas?

Page 35: Domain Driven Design PHP TDC2014

pen4education

Referência