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

Domain Driven Design PHP TDC2014

Jun 13, 2015

Download

Technology

Domain Driven Design PHP TDC2014
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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