modernizando a arquitertura de sua aplicação
TRANSCRIPT
modernizando a arquitertura de sua aplicação
Antonio Spinelli @tonicospinelli
tornando o seu código mais robusto e escalável
problema simplesvs
soluções complexas
soluções simples
o objetivo não muda:
resolver problemas para o negócio!
entenda o problema
agregue valor ao negócio
agilidade não é "sobrinhagem"
desenvolvedor
desenvolvedor
automatize tarefas repetidas
peça e faça code review
leia código
Lista de Desejos para Produtos
Eu como um usuário convidado, quero adicionar um produto
indisponível dentro da minha lista de desejos, de modo que eu
receba uma notificação quando este estiver disponível.
Objetivo
reposição de estoque inteligente e
estreitar relacionamento com cliente
user story
php puro
adicionando um item na lista de desejos
php puro
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
}// ...
php puro
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']); }// ...
php puro
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
$stm = $db->prepare('insert new entry (email, product_id)'); $stm->execute([$wishItem['email'], $wishItem['product_id']]); $successmsg = 'Product was added at wish list successfully!';
}// ...
php puro
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
$db->beginTransaction();
try { $stm = $db->prepare('insert new entry (email, product_id)'); $stm->execute([$wishItem['email'], $wishItem['product_id']]); $successmsg = 'Product was added at wish list successfully!'; $db->commit(); } catch (Exception $e) {
$db->rollBack(); $errormsg = 'Product could not be added at wishlist! :('; }}// ..
php puro
// public/wishlist.php// ...<table> <?php foreach ($wishlist as $item): ?> <tr> <td><?php echo $item['id']; ?> </td> <td><?php echo $item['product_name']; ?> </td> <?php if ($item['product_stock'] == 0): ?> <td>Not Available</td> <?php else: ?> <td>Available</td> <?php endif; ?> <td> <?php echo removeUrl($item['id'], ['email' => $email]); ?> </td> </tr> <?php endforeach; ?></table>// ...
php puro
notificar usuário quando o item estiver disponível
php puro
// cli/wishlist_notify.php// ...$query = "find all available products from wishlist";
$stm = $db->prepare($query);$stm->execute();$wishlists = $stm->fetchAll(PDO::FETCH_ASSOC);
php puro
// cli/wishlist_notify.php// ...$query = "find all available products from wishlist";
$stm = $db->prepare($query);$stm->execute();$wishlists = $stm->fetchAll(PDO::FETCH_ASSOC);
foreach ($wishlists as $item) {
mail( $item['email'], "{$item['product_name']} available", $mailBody ); $stm = $db->prepare("define new status for id = ?"); $stm->execute([$item['id']]);
}
php puro
pronto!
funciona!
php puro
quais problemas temos com este código?
atenção
organização pobre
sem verificação de erros
dificuldade para reutilizar o código
php puro
php estruturado
isolando a apresentação
php estruturado
// templates/wishlist/list.php
<table> <?php foreach ($wishlist as $item): ?> <tr> <td><?php echo $item['id']; ?> </td> <td><?php echo $item['product_name']; ?> </td> <?php if ($item['product_stock'] == 0): ?> <td>Not Available</td> <?php else: ?> <td>Available</td> <?php endif; ?> <td> <?php echo removeUrl($item['id'], ['email' => $email]); ?> </td> </tr> <?php endforeach; ?></table>
php estruturado
isolando regra de negócio
php estruturado
// lib/models/wishlist.php
function addItemIntoWishlist(array $data);
function createWishListItem(array $data);
function findAllWishlistsToNotify();
function findAllWishProducts($email);
function isValidWishList(array $data);
function removeWishItem($id);
function wishlistNotified($id);
php estruturado
interagindo
regras de negócio com a apresentação
php estruturado
// public/wishlist.php
require_once __DIR__ . '/../lib/dbconn.php';require_once __DIR__ . '/../lib/functions.php';require_once __DIR__ . '/../lib/wishlist.php';
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
$db->beginTransaction();
try { $stm = $db->prepare('insert new entry (email, product_id)'); $stm->execute([$wishItem['email'], $wishItem['product_id']]); $db->commit(); $successmsg = 'Product was added at wish list successfully!'; } catch (Exception $e) { $db->rollBack(); $errormsg = 'Product could not be added at wishlist! :('; }}// ...
php estruturado
// public/wishlist.php
require_once __DIR__ . '/../lib/dbconn.php';require_once __DIR__ . '/../lib/functions.php';require_once __DIR__ . '/../lib/wishlist.php';
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
$db->beginTransaction();
try { $stm = $db->prepare('insert new entry (email, product_id)'); $stm->execute([$wishItem['email'], $wishItem['product_id']]); $db->commit(); $successmsg = 'Product was added at wish list successfully!'; } catch (Exception $e) { $db->rollBack(); $errormsg = 'Product could not be added at wishlist! :('; }}// ...
structured php
// public/wishlist.php
require_once __DIR__ . '/../lib/dbconn.php';require_once __DIR__ . '/../lib/functions.php';require_once __DIR__ . '/../lib/wishlist.php';
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
if (addItemIntoWishlist($wishItem)) { $successmsg = 'Product was added at wish list successfully!'; } else { $errormsg = 'Product could not be added at wishlist! :('; }}// ...
php estruturado
// public/wishlist.php
require_once __DIR__ . '/../lib/dbconn.php';require_once __DIR__ . '/../lib/functions.php';require_once __DIR__ . '/../lib/wishlist.php';
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
if (addItemIntoWishlist($wishItem)) { $successmsg = 'Product was added at wish list successfully!'; } else { $errormsg = 'Product could not be added at wishlist! :('; }}
$wishlist = findAllWishProducts($_GET['email']);include __DIR__ . '/../templates/wishlists/list.php';
php estruturado
isolando layout
php estruturado
// template/layout.php
<!DOCTYPE html><html> <head> <title><?php echo $title ?></title> </head> <body> <?php echo $content ?> </body></html>
layout padrão
php estruturado
// template/wishlist/list.php
<?php $title = 'My Wish List' ?>
define o título da página
php estruturado
// template/wishlist/list.php
<?php $title = 'My Wish List' ?>
<?php ob_start() ?> <table> <tbody> <?php foreach ($wishlist as $wish): ?> <tr><!-- print all columns --></tr> <?php endforeach; ?> </tbody> </table><?php $content = ob_get_clean() ?>
define o conteúdo da página
php estruturado
// template/wishlist/list.php
<?php $title = 'My Wish List' ?>
<?php ob_start() ?> <table> <tbody> <?php foreach ($wishlist as $wish): ?> <tr><!-- print all columns --></tr> <?php endforeach; ?> </tbody> </table><?php $content = ob_get_clean() ?>
<?php include __DIR__ . '/../layout.php' ?>
extendendo layout padrão
php estruturado
front controller
php estruturado
sem um front controller
GET /[email protected]
com index.php como um front controller
GET /index.php/wishlist/[email protected]
com regras de sobrescrita no servidor web
GET /wishlist/[email protected]
php estruturado
// public/index.php
// route the request internally$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
if (preg_match('/wishlist\/(.*)$', $uri, $matches) && $method == 'GET') {
wishlistListAction($matches[1]);
} elseif ('/index.php/wishlist/add' === $uri && $method == 'POST') {
wishlistAddAction($_GET['email'], $_POST);
} else {
header('HTTP/1.1 404 Not Found'); echo '<html><body><h1>Page Not Found</h1></body></html>';}
php estruturado
// public/index.php
// route the request internally$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
if (preg_match('/wishlist\/(.*)$', $uri, $matches) && $method == 'GET') {
wishlistListAction($matches[1]);
} elseif ('/index.php/wishlist/add' === $uri && $method == 'POST') {
wishlistAddAction($_GET['email'], $_POST);
} else {
header('HTTP/1.1 404 Not Found'); echo '<html><body><h1>Page Not Found</h1></body></html>';}
php estruturado
// public/index.php
// route the request internally$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
if (preg_match('/wishlist\/(.*)$', $uri, $matches) && $method == 'GET') {
wishlistListAction($matches[1]);
} elseif ('/index.php/wishlist/add' === $uri && $method == 'POST') {
wishlistAddAction($_GET['email'], $_POST);
} else {
header('HTTP/1.1 404 Not Found'); echo '<html><body><h1>Page Not Found</h1></body></html>';}
php estruturado
// public/index.php
// route the request internally$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
if (preg_match('/wishlist\/(.*)$', $uri, $matches) && $method == 'GET') {
wishlistListAction($matches[1]);
} elseif ('/index.php/wishlist/add' === $uri && $method == 'POST') {
wishlistAddAction($_GET['email'], $_POST);
} else {
header('HTTP/1.1 404 Not Found'); echo '<html><body><h1>Page Not Found</h1></body></html>';}
php estruturado
autoload
php estruturado
// public/index.php
require_once __DIR__ . '/../config/app.php';
require_once LIBRARY_DIR . '/functions.php';
require_once LIBRARY_DIR . '/wishlist.php';
// include_path is other alternative
ini_set('include_path', __DIR__ . '/../lib');
php estruturadoautoload
php estruturado
{ "name": "tonicospinelli/developing-for-business", "description": "A Quick Project for Talk", "license": "MIT", "autoload": { "files": [ "./lib/dbconn.php", "./lib/functions.php", "./lib/controllers/wishlist.php", "./lib/models/wishlist.php" ] }}
composer
php estruturado
$ composer dump-autoload
// public/index.php
require_once __DIR__ . '/../vendor/autoload.php';
php estruturadoautoload
developing-for-business├── cli│ └── wishlist_notification.php├── composer.json├── config│ └── app.php├── lib│ ├── controllers│ │ └── wishlist.php│ ├── functions.php│ └── models│ └── wishlist.php├── public│ └── index.php├── templates│ └── wishlists└── vendor
estrutura do projeto
php estruturado
php orientado a objetos
código auto explicativo
facilidade no crescimento
testes automatizados
php orientado a objetos
testes automatizados
php orientado a objetos
garantem regras conhecidas
auxiliam na refatoração
não evitam bugs
testes automatizados
php orientado a objetos
PHPUnit 5.4.6 by Sebastian Bergmann and contributors.
................................................... 59 / 59 (100%)
Time: 349 ms, Memory: 6.00MB
OK (59 tests, 126 assertions)
testes automatizados
php orientado a objetos
PHPUnit 5.4.6 by Sebastian Bergmann and contributors.
..................................F................ 59 / 59 (100%)
Time: 374 ms, Memory: 6.00MB
There was 1 failure:
1) ProductTest::testUpdateProductFailedFailed asserting that exception of type "ProductException" is thrown.
FAILURES!Tests: 59, Assertions: 125, Failures: 1.
testes automatizados
php orientado a objetos
não confie em arrays
evite abreviações
php orientado a objetos
/*** Creates a new wish list data.* @param array $data* @return array*/function newWishList(array $data){ return array( 'email' => isset($data['email']) ? $data['email'] : null), 'product_id' => $data['product_id'], 'status' => 'P', );}
php orientado a objetos
objetos de valor
php orientado a objetos
objetos simples
encapsulam tipos primitivos
representam o valor
objetos de valor
php orientado a objetos
class Status{ const PENDING = 'P'; const SENT = 'S';
private $status;
public function __construct($status) { $this->validate($status); $this->status = $status; } // … other methods public function equalsTo(Status $status) { return $status === $this; }}
objetos de valor
php orientado a objetos
entidades
php orientado a objetos
são mutáveis
tem identificador
entidades
php orientado a objetos
class Wishlist{ public function __construct( Id $id, Email email, WishlistItem $item, Status $status ) { $this->id = $id; $this->email = $email; $this->item = $item; $this->status = $status; }}
entidades
php orientado a objetos
class Wishlist{ public function __construct( Id $id, Email email, WishlistItem $item, Status $status ) { $this->id = $id; $this->email = $email; $this->item = $item; $this->status = $status; }}
por que umobjeto Item?
entidades
php orientado a objetos
class Wishlist{ public function __construct( Id $id, Email email, WishlistItem $item, Status $status ) { $this->id = $id; $this->email = $email; $this->item = $item; $this->status = $status; }}
por que umobjeto Item?
Produtos Presente
entidades
php orientado a objetos
interface WishlistItem{ public function getId();}
class WishlistProduct implements WishlistItem{ public function __construct( Id $id, $name, Available $availability ) { $this->id = $id; $this->name = $name; $this->available = $availability; }}
entidades
php orientado a objetos
repositórios
php orientado a objetos
camada de persistência
estratégia de armazenamento
repositórios
php orientado a objetos
interface WishlistRepository{ public function add(Wishlist $wishlist);
public function delete(Wishlist $wishlist);
public function find($id);
public function findAllByEmail($email);
public function findAllToNotify();}
repositórios
php orientado a objetos
namespace Develop\Business\Application\ProductWishlist\Repositories;
class PdoRepository implements WishlistRepository{ public function __construct(\PDO $driver, Factory $factory);
public function findAllByEmail($email) { $query = "find all items by email"; $stm = $this->driver->prepare($query); $stm->execute([$email]);
return $stm->fetchAll( \PDO::FETCH_FUNC, [$this->factory, 'create'] ); }}
repositórios
php orientado a objetos
namespace Develop\Business\Application\ProductWishlist\Repositories;
class RedisRepository implements WishlistRepository{ public function __construct(Predis $driver, Factory $factory);
public function find($id) { $wishlist = $this->driver->get($this->getKey($id));
if (!$wishlist) { throw WishlistNotFoundException::byIdentifier($id); }
return $this->factory->fromJson($wishlist); }}
repositórios
php orientado a objetos
class PdoRepositoryTest extends \PHPUnit_Framework_TestCase{ public function testAddNewRowSuccessful()
{
$wishlist = $this->factory->fromQueryResult(/* args */);
$pdoSpy = new PDOSpy();
(new Repository($pdoSpy))->add($wishlist);
$this->assertTrue($pdoSpy->beginTransactionCalled); $this->assertTrue($pdoSpy->commitCalled);
$this->assertEquals(2, $wishlist->getId()); }}
como testar repositórios?
php orientado a objetos
class PDOSpy extends \PDO{ public function beginTransaction() { $this->beginTransactionCalled = true; }
public function prepare($statement, $options = null) { if ($statement == INSERT INTO wishlists VALUES (?, ?, ?)') { return new WriteStatementStub($this->failureOnWrite); }
throw new \InvalidArgumentException( "None Stub Statement was found for query: {$statement}" ); }}
como testar repositórios?
php orientado a objetos
function wishlistListAction($email){ $db = dbConnect();
$factory = new WishlistFactory();
$repository = new WishlistPdoRepository($db, $factory);
$wishlist = $repository->findAllByEmail($email);
include TEMPLATE_DIR . '/wishlists/list.php';}
repositórios
php orientado a objetos
serviços
php orientado a objetos
camada de operação
orquestra os objetos
define o que fazer
serviços
php orientado a objetos
adicionando um item na lista de desejos
serviços
php orientado a objetos
$db = dbConnect();$factory = new WishlistFactory();$repository = new WishlistRepository($db, $factory);$resolver = new ItemResolver(new ProductRepository($db));
try { $intention = createIntention($request['wish_item']);
$useCase = new AddItemWishlistUseCase( $repository, $factory, $resolver );
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";} catch (\DomainException $e) { $errormsg = $e->getMessage();}
resolvendo dependências
adicionando um item na lista de desejos
php orientado a objetos
$db = dbConnect();$factory = new WishlistFactory();$repository = new WishlistRepository($db, $factory);$resolver = new ItemResolver(new ProductRepository($db));
try { $intention = createIntention($request['wish_item']);
$useCase = new AddItemWishlistUseCase( $repository, $factory, $resolver );
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";} catch (\DomainException $e) { $errormsg = $e->getMessage();}
parsing da requisição
adicionando um item na lista de desejos
php orientado a objetos
$db = dbConnect();$factory = new WishlistFactory();$repository = new WishlistRepository($db, $factory);$resolver = new ItemResolver(new ProductRepository($db));
try { $intention = createIntention($request['wish_item']);
$useCase = new AddItemWishlistUseCase( $repository, $factory, $resolver );
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";} catch (\DomainException $e) { $errormsg = $e->getMessage();}
criandoobjeto de serviço
adicionando um item na lista de desejos
php orientado a objetos
$db = dbConnect();$factory = new WishlistFactory();$repository = new WishlistRepository($db, $factory);$resolver = new ItemResolver(new ProductRepository($db));
try { $intention = createIntention($request['wish_item']);
$useCase = new AddItemWishlistUseCase( $repository, $factory, $resolver );
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";} catch (\DomainException $e) { $errormsg = $e->getMessage();}
executandoo serviço
adicionando um item na lista de desejos
php orientado a objetos
$db = dbConnect();$factory = new WishlistFactory();$repository = new WishlistRepository($db, $factory);$resolver = new ItemResolver(new ProductRepository($db));
try { $intention = createIntention($request['wish_item']);
$useCase = new AddItemWishlistUseCase( $repository, $factory, $resolver );
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";} catch (\DomainException $e) { $errormsg = $e->getMessage();}
mensagem de negócio
adicionando um item na lista de desejos
php orientado a objetos
class AddItemWishlistUseCase{ public function __construct( WishlistRepository $repository, WishlistFactory $factory, ItemResolver $resolver ) { // do something }}
como adicionar um item na lista de desejos
php orientado a objetos
class AddItemWishlistUseCase{ public function execute(AddItemIntention $intention) { $item = $this->resolver->resolve($intention->itemId); try { $wishlist = $this->repository->findOneByEmailAndItem( $email, $item ); throw WishlistException::itemAlreadyExists($wishlist); } catch (WishlistNotFoundException $e) { // do nothing } $wishlist = $this->factory->new($email, $item); return $this->repository->add($wishlist); }}
php orientado a objetoscomo adicionar um item na lista de desejos
class AddItemWishlistUseCase{ public function execute(AddItemIntention $intention) { $item = $this->resolver->resolve($intention->itemId); try { $wishlist = $this->repository->findOneByEmailAndItem( $email, $item ); throw WishlistException::itemAlreadyExists($wishlist); } catch (WishlistNotFoundException $e) { // do nothing } $wishlist = $this->factory->new($email, $item); return $this->repository->add($wishlist); }}
php orientado a objetoscomo adicionar um item na lista de desejos
class AddItemWishlistUseCase{ public function execute(AddItemIntention $intention) { $item = $this->resolver->resolve($intention->itemId); try { $wishlist = $this->repository->findOneByEmailAndItem( $email, $item ); throw WishlistException::itemAlreadyExists($wishlist); } catch (WishlistNotFoundException $e) { // do nothing } $wishlist = $this->factory->new($email, $item); return $this->repository->add($wishlist); }}
php orientado a objetoscomo adicionar um item na lista de desejos
serviços
notificar usuário quando
um item estiver disponível
php orientado a objetos
// cli/wishlist_notify.php
require_once __DIR__ . '/../config/app.php';require_once __DIR__ . '/../vendor/autoload.php';
$factory = new WishlistFactory();
$repository = new WishlistRepository(dbConnect(), $factory);
$notifier = new MailNotifier();
$useCase = (new NotifyItemsUseCase($repository, $notifier);
$useCase->execute(new NotifyItemsIntention(Status::PENDING));
notificar quando um item disponível
resolving dependencies
php orientado a objetos
// cli/wishlist_notify.php
require_once __DIR__ . '/../config/app.php';require_once __DIR__ . '/../vendor/autoload.php';
$factory = new WishlistFactory();
$repository = new WishlistRepository(dbConnect(), $factory);
$notifier = new MailNotifier();
$useCase = (new NotifyItemsUseCase($repository, $notifier);
$useCase->execute(new NotifyItemsIntention(Status::PENDING));
call service
notificar quando um item disponível
php orientado a objetos
class NotifyItemsUseCase{ public function execute(NotifyItemsIntention $intention) { $status = $intention->getStatus();
$wishlists = $this->repository->findAllByStatus($status);
foreach ($wishlists as $wishlist) {
$this->notifier()->send($wishlist);
$wishlist->changeStatusTo(Status::sent());
$this->repository->update($wishlist); } }}
como notificar quando um item disponível?
php orientado a objetos
class NotifyItemsUseCase{ public function execute(NotifyItemsIntention $intention) { $status = $intention->getStatus();
$wishlists = $this->repository->findAllByStatus($status);
foreach ($wishlists as $wishlist) {
$this->notifier()->send($wishlist);
$wishlist->changeStatusTo(Status::sent());
$this->repository->update($wishlist); } }}
como notificar quando um item disponível?
php orientado a objetos
class NotifyItemsUseCase{ public function execute(NotifyItemsIntention $intention) { $status = $intention->getStatus();
$wishlists = $this->repository->findAllByStatus($status);
foreach ($wishlists as $wishlist) {
$this->notifier()->send($wishlist);
$wishlist->changeStatusTo(Status::sent());
$this->repository->update($wishlist); } }}
como notificar quando um item disponível?
php orientado a objetos
injeção de dependência
php orientado a objetos
princípio da inversão de dependência
dependências configuráveis
injeção de dependência
php orientado a objetos
Respect/Config
injeção de dependência
php orientado a objetos
// config/app.ini
[databaseConnection \PDO]__construct = ["sqlite:../data/business.db", null, null]
[factory \WishlistFactory]
[repository WishlistRepository]__construct = [[databaseConnection], [factory]]
[productRepository \ProductRepository]driver = [databaseConnection]
[itemResolver \WishlistItemResolver]product = [productRepository]
injeção de dependência
php orientado a objetos
// public/index.php
require_once __DIR__ . '/../config/app.php';require_once __DIR__ . '/../vendor/autoload.php';
$configFile = __DIR__ . '/../config/app.ini';
$container = new Respect\Config\Container($configFile);
if ('/index.php/wishlist/add' === $uri /* other validations */) { wishlistAddAction($container, $_GET['email'], $_POST);}
injeção de dependência
php orientado a objetos
// public/index.php
require_once __DIR__ . '/../config/app.php';require_once __DIR__ . '/../vendor/autoload.php';
$configFile = __DIR__ . '/../config/app.ini';
$container = new Respect\Config\Container($configFile);
if ('/index.php/wishlist/add' === $uri /* other validations */) { wishlistAddAction($container, $_GET['email'], $_POST);}
injeção de dependência
php orientado a objetos
function wishlistAddAction(Container $container, $email, $request){ try { $intention = createIntention($request['wish_item']);
$useCase = $container->wishlistAddItemWishlistUseCase; $wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!"; } catch (\Exception $e) { $errormsg = $e->getMessage(); }}
injeção de dependência
php orientado a objetos
eventos
php orientado a objetos
mecanismo de inversão de controle
comunicação assíncrona
baixo acoplamento
eventos
php orientado a objetos
symfony/event-dispatcher
eventos
php orientado a objetos
class UpdateProductUseCase{ public function __construct(/* args */, $eventDispatcher);
public function execute(Intention $intention) { $this->repository->update($updatedProduct);
$event = new ProductWasUpdated($updatedProduct); $this->dispatch('product.updated', $event);
return $updatedProduct; }}
eventos
php orientado a objetos
class UpdateProductUseCase{ public function __construct(/* args */, $eventDispatcher);
public function execute(Intention $intention) { $this->repository->update($updatedProduct);
$event = new ProductWasUpdated($updatedProduct); $this->dispatch('product.updated', $event);
if ($this->isStockIncreased($product, $updatedProduct)) { $this->dispatch('product.stock.increased', $event); }
return $updatedProduct; }}
eventos
php orientado a objetos
class StockHasIncreasedListener{ public function __construct(NotifyProductAvailable $useCase);
public function __invoke(ProductStockIncreasedEvent $event) { $productId = $event->getProduct()->getId();
$intention = new NotifyProductIntention($productId);
$this->useCase->execute($intention); }}
events
object oriented php
config/app.ini
[wishlistStockListener StockHasIncreasedListener]useCase = [notifyProductAvailableUseCase]
[eventDispatcher \EventDispatcher]addListener[] = ["product.stock.increased",[wishlistStockListener]]
[productUpdateUseCase \UpdateProductUseCase]__construct = [[repository], [factory], [eventDispatcher]]
eventos
php orientado a objetos
estrutura
php orientado a objetos
business
services
application
webdevices
use
inte
rfac
e
databaseEx
tern
al I
nter
face
s
camadas
php orientado a objetos
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']);
$db->beginTransaction();
try { $stm = $db->prepare('insert new entry (email, product_id)'); $stm->execute([$wishItem['email'], $wishItem['product_id']]); $db->commit();
$successmsg = 'Product was added at wish list successfully!'; } catch (Exception $e) {
$db->rollBack(); $errormsg = 'Product could not be added at wishlist! :('; }}// ..
php puro
// lib/controllers/wishList.php
function wishlistAddAction(Container $container, $email, $request){ try {
$intention = createIntention($request['wish_item']);
$useCase = $container->wishlistAddItemWishlistUseCase;
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";
} catch (\Exception $e) {
$errormsg = $e->getMessage();
}}
php orientado a objetos
developing-for-business
├── cli
│ └── wishlist_notification.php
├── data
│ └── business.db
├── lib
│ ├── dbconn.php
│ └── functions.php
└── public
└── wishlist.php
estrutura php puro
Develop\Business
└── Application
├── Product
│ ├── Controllers
│ └── Repositories
└── ProductWishlist
├── Controllers
├── Resolver
├── Listeners
└── Repositories
Develop\Business
├── Product
│ ├── Events
│ ├── Exceptions
│ ├── Intentions
│ ├── Repositories
│ └── UseCases
└── Wishlist
├── Exceptions
├── Intentions
├── ItemResolver.php
├── Repositories
└── UseCases
estrutura php orientado a objetos
conclusãosaia da zona de conforto
interaja com a comunidade
conclusão
automatize tarefas repetitivas
conclusão
domain driven design
conclusão
domain specific language
conclusão
princípio S.O.L.I.D.
conclusão
Implementing Domain-Driven Design
por Vaughn Vernon
Patterns of Enterprise Application Architecture
por Martin Fowler
Domain-Driven Design
por Eric Evans
DDD in PHP
por Carlos Buenosvinos, Christian Soronellas e Keyvan Akbary
referências
Life's too short for bad softwareLew Cirne, New Relic