modernizando a arquitertura de sua aplicação

Preview:

Citation preview

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 /wishlist.php?email=email@test.com

com index.php como um front controller

GET /index.php/wishlist/email@test.com

com regras de sobrescrita no servidor web

GET /wishlist/email@test.com

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

Recommended