modernizando a arquitertura de sua aplicação
-
Upload
antonio-oertel-spinelli -
Category
Technology
-
view
247 -
download
2
Transcript of modernizando a arquitertura de sua aplicação
![Page 1: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/1.jpg)
modernizando a arquitertura de sua aplicação
Antonio Spinelli @tonicospinelli
tornando o seu código mais robusto e escalável
![Page 2: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/2.jpg)
problema simplesvs
soluções complexas
![Page 3: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/3.jpg)
soluções simples
![Page 4: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/4.jpg)
o objetivo não muda:
resolver problemas para o negócio!
![Page 5: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/5.jpg)
entenda o problema
agregue valor ao negócio
agilidade não é "sobrinhagem"
desenvolvedor
![Page 6: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/6.jpg)
desenvolvedor
automatize tarefas repetidas
peça e faça code review
leia código
![Page 7: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/7.jpg)
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
![Page 8: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/8.jpg)
php puro
![Page 9: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/9.jpg)
adicionando um item na lista de desejos
php puro
![Page 10: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/10.jpg)
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
}// ...
php puro
![Page 11: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/11.jpg)
// public/wishlist.php// ...if (isset($_POST['submit']) && isValid($_POST['wish_item'])) {
$wishItem = createWishListItem($_POST['wish_item']); }// ...
php puro
![Page 12: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/12.jpg)
// 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
![Page 13: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/13.jpg)
// 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
![Page 14: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/14.jpg)
// 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
![Page 15: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/15.jpg)
notificar usuário quando o item estiver disponível
php puro
![Page 16: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/16.jpg)
// 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
![Page 17: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/17.jpg)
// 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
![Page 18: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/18.jpg)
pronto!
funciona!
php puro
![Page 19: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/19.jpg)
quais problemas temos com este código?
atenção
![Page 20: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/20.jpg)
organização pobre
sem verificação de erros
dificuldade para reutilizar o código
php puro
![Page 21: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/21.jpg)
php estruturado
![Page 22: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/22.jpg)
isolando a apresentação
php estruturado
![Page 23: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/23.jpg)
// 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
![Page 24: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/24.jpg)
isolando regra de negócio
php estruturado
![Page 25: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/25.jpg)
// 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
![Page 26: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/26.jpg)
interagindo
regras de negócio com a apresentação
php estruturado
![Page 27: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/27.jpg)
// 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
![Page 28: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/28.jpg)
// 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
![Page 29: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/29.jpg)
// 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
![Page 30: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/30.jpg)
// 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
![Page 31: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/31.jpg)
isolando layout
php estruturado
![Page 32: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/32.jpg)
// template/layout.php
<!DOCTYPE html><html> <head> <title><?php echo $title ?></title> </head> <body> <?php echo $content ?> </body></html>
layout padrão
php estruturado
![Page 33: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/33.jpg)
// template/wishlist/list.php
<?php $title = 'My Wish List' ?>
define o título da página
php estruturado
![Page 34: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/34.jpg)
// 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
![Page 35: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/35.jpg)
// 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
![Page 36: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/36.jpg)
front controller
php estruturado
![Page 37: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/37.jpg)
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
![Page 38: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/38.jpg)
// 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
![Page 39: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/39.jpg)
// 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
![Page 40: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/40.jpg)
// 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
![Page 41: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/41.jpg)
// 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
![Page 42: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/42.jpg)
autoload
php estruturado
![Page 43: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/43.jpg)
// 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
![Page 44: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/44.jpg)
php estruturado
![Page 45: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/45.jpg)
{ "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
![Page 46: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/46.jpg)
$ composer dump-autoload
// public/index.php
require_once __DIR__ . '/../vendor/autoload.php';
php estruturadoautoload
![Page 47: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/47.jpg)
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
![Page 48: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/48.jpg)
php orientado a objetos
![Page 49: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/49.jpg)
código auto explicativo
facilidade no crescimento
testes automatizados
php orientado a objetos
![Page 50: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/50.jpg)
testes automatizados
php orientado a objetos
![Page 51: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/51.jpg)
garantem regras conhecidas
auxiliam na refatoração
não evitam bugs
testes automatizados
php orientado a objetos
![Page 52: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/52.jpg)
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
![Page 53: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/53.jpg)
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
![Page 54: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/54.jpg)
não confie em arrays
evite abreviações
php orientado a objetos
![Page 55: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/55.jpg)
/*** 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
![Page 56: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/56.jpg)
objetos de valor
php orientado a objetos
![Page 57: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/57.jpg)
objetos simples
encapsulam tipos primitivos
representam o valor
objetos de valor
php orientado a objetos
![Page 58: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/58.jpg)
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
![Page 59: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/59.jpg)
entidades
php orientado a objetos
![Page 60: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/60.jpg)
são mutáveis
tem identificador
entidades
php orientado a objetos
![Page 61: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/61.jpg)
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
![Page 62: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/62.jpg)
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
![Page 63: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/63.jpg)
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
![Page 64: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/64.jpg)
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
![Page 65: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/65.jpg)
repositórios
php orientado a objetos
![Page 66: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/66.jpg)
camada de persistência
estratégia de armazenamento
repositórios
php orientado a objetos
![Page 67: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/67.jpg)
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
![Page 68: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/68.jpg)
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
![Page 69: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/69.jpg)
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
![Page 70: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/70.jpg)
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
![Page 71: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/71.jpg)
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
![Page 72: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/72.jpg)
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
![Page 73: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/73.jpg)
serviços
php orientado a objetos
![Page 74: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/74.jpg)
camada de operação
orquestra os objetos
define o que fazer
serviços
php orientado a objetos
![Page 75: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/75.jpg)
adicionando um item na lista de desejos
serviços
php orientado a objetos
![Page 76: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/76.jpg)
$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
![Page 77: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/77.jpg)
$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
![Page 78: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/78.jpg)
$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
![Page 79: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/79.jpg)
$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
![Page 80: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/80.jpg)
$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
![Page 81: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/81.jpg)
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
![Page 82: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/82.jpg)
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
![Page 83: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/83.jpg)
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
![Page 84: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/84.jpg)
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
![Page 85: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/85.jpg)
serviços
notificar usuário quando
um item estiver disponível
php orientado a objetos
![Page 86: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/86.jpg)
// 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
![Page 87: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/87.jpg)
// 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
![Page 88: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/88.jpg)
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
![Page 89: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/89.jpg)
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
![Page 90: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/90.jpg)
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
![Page 91: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/91.jpg)
injeção de dependência
php orientado a objetos
![Page 92: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/92.jpg)
princípio da inversão de dependência
dependências configuráveis
injeção de dependência
php orientado a objetos
![Page 93: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/93.jpg)
Respect/Config
injeção de dependência
php orientado a objetos
![Page 94: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/94.jpg)
// 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
![Page 95: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/95.jpg)
// 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
![Page 96: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/96.jpg)
// 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
![Page 97: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/97.jpg)
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
![Page 98: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/98.jpg)
eventos
php orientado a objetos
![Page 99: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/99.jpg)
mecanismo de inversão de controle
comunicação assíncrona
baixo acoplamento
eventos
php orientado a objetos
![Page 100: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/100.jpg)
symfony/event-dispatcher
eventos
php orientado a objetos
![Page 101: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/101.jpg)
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
![Page 102: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/102.jpg)
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
![Page 103: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/103.jpg)
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
![Page 104: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/104.jpg)
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
![Page 105: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/105.jpg)
estrutura
php orientado a objetos
![Page 106: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/106.jpg)
business
services
application
webdevices
use
inte
rfac
e
databaseEx
tern
al I
nter
face
s
camadas
php orientado a objetos
![Page 107: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/107.jpg)
// 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
![Page 108: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/108.jpg)
// 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
![Page 109: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/109.jpg)
developing-for-business
├── cli
│ └── wishlist_notification.php
├── data
│ └── business.db
├── lib
│ ├── dbconn.php
│ └── functions.php
└── public
└── wishlist.php
estrutura php puro
![Page 110: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/110.jpg)
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
![Page 111: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/111.jpg)
conclusãosaia da zona de conforto
![Page 112: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/112.jpg)
interaja com a comunidade
conclusão
![Page 113: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/113.jpg)
automatize tarefas repetitivas
conclusão
![Page 114: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/114.jpg)
domain driven design
conclusão
![Page 115: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/115.jpg)
domain specific language
conclusão
![Page 116: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/116.jpg)
princípio S.O.L.I.D.
conclusão
![Page 117: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/117.jpg)
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
![Page 118: modernizando a arquitertura de sua aplicação](https://reader033.fdocument.pub/reader033/viewer/2022052915/58731ee91a28ab673e8b7023/html5/thumbnails/118.jpg)
Life's too short for bad softwareLew Cirne, New Relic