SlideShare une entreprise Scribd logo
1  sur  84
Télécharger pour lire hors ligne
Globalcode – Open4education
Trilha – PHP Architecture
Developing for Business
Globalcode – Open4education
apresentação
Antonio Spinelli
@tonicospinelli
tonicospinelli85@gmail.com
Globalcode – Open4education
o propósito sempre é o mesmo:
resolver problema para o negócio!
Globalcode – Open4education
comportamento
problema simples
vs
soluções complexas
Globalcode – Open4education
comportamento
escopo abstrato
=
problema desconhecido
Globalcode – Open4education
comportamento
agregue valor para negócio
entenda a demanda
agilidade não é "sobrinhagem"
Globalcode – Open4education
conhecimento
leia código
peça e faça code review
automatize tarefas repetitivas
Globalcode – Open4education
user story
Lista de Desejos
Eu como usuário convidado, quero adicionar um produto
esgotado em minha lista de desejos para que eu receba uma
notificação quando este estiver disponível.
Objetivo
reposição mais inteligente de produtos
Globalcode – Open4education
php estruturado
Globalcode – Open4education
php estruturado
adicionando um item
na lista de desejos
Globalcode – Open4education
// public/wishlist.php
// ...
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = getWishList($_POST['wish_item']);
$db->beginTransaction();
try {
$stm = $db->prepare(
'INSERT INTO wishlists (email, product_id) VALUES (?, ?)'
);
$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
Globalcode – Open4education
php estruturado
// public/wishlist.php
// ...
<table>
<?php foreach ($wishlist as $wish): ?>
<tr>
<td><?php echo $wish['id']; ?> </td>
<td><?php echo $wish['product_name']; ?> </td>
<?php if ($wish['product_stock'] == 0): ?>
<td>Not Available</td>
<?php else: ?>
<td>Available</td>
<?php endif; ?>
<td>
<?php echo removeUrl($wish['id'], ['email' => $email]); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
// ...
Globalcode – Open4education
php estruturado
notificar usuário que
o item está disponível
Globalcode – Open4education
php estruturado
// 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 $wishlist) {
mail(
$wishlist['email'],
"{$wishlist['product_name']} disponível",
$mailBody
);
$stm = $db->prepare("UPDATE wishlists SET status='S' WHERE id=?");
$stm->execute([$wishlist['id']]);
}
Globalcode – Open4education
php estruturado
Pronto! funciona!
Globalcode – Open4education
php estruturado
quais problemas neste código?
Globalcode – Open4education
php estruturado
organização pobre
sem verificação de erro
dificuldade de reusar código
Globalcode – Open4education
php estruturado
isolando a apresentação
Globalcode – Open4education
php estruturado
// templates/wishlist/list.php
<table>
<?php foreach ($wishlist as $wish): ?>
<tr>
<td><?php echo $wish['id']; ?> </td>
<td><?php echo $wish['product_name']; ?> </td>
<?php if ($wish['product_stock'] == 0): ?>
<td>Not Available</td>
<?php else: ?>
<td>Available</td>
<?php endif; ?>
<td>
<?php echo removeUrl($wish['id'], ['email' => $email]); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
Globalcode – Open4education
php estruturado
isolando regras de negócio
Globalcode – Open4education
php estruturado
function isValidWishList(array $data);
function getWishList(array $data);
function findAllWishProducts($email);
function addWishItem(array $data);
function removeWishItem($id);
function findAllWishlistsToNotify();
function wishlistNotified($id);
Globalcode – Open4education
php estruturado
interagindo com
regra de negócio e apresentação
Globalcode – Open4education
php estruturado
public/wishlist.php
require_once __DIR__ . '/../lib/functions.php';
require_once __DIR__ . '/../lib/models/wishlist.php';
require_once __DIR__ . '/../lib/dbconn.php';
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = getWishList($_POST['wish_item']);
if (addWishItem($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';
Globalcode – Open4education
php estruturado
isolando layout
Globalcode – Open4education
php estruturado
// template/layout.php
<!DOCTYPE html>
<html>
<head>
<title><?php echo $title ?></title>
</head>
<body>
<?php echo $content ?>
</body>
</html>
Globalcode – Open4education
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' ?>
Globalcode – Open4education
php estruturado
front controller
Globalcode – Open4education
php estruturado
Without a front controller
GET /wishlist.php?email=email@test.com
With index.php as the front controller
GET /index.php/wishlist/email@test.com
Globalcode – Open4education
php puro front controller
// public/index.php
// load function files
// 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>';
}
Globalcode – Open4education
php estruturado
autoload
Globalcode – Open4education
php estruturado autoload
// public/index.php
require_once __DIR__ . '/../config/app.php';
require_once LIBRARY_DIR . '/functions.php';
require_once LIBRARY_DIR . '/models/wishlist.php';
require_once LIBRARY_DIR . '/controllers/wishlist.php';
// include_path is other alternative
ini_set('include_path', __DIR__ . '/../lib');
Globalcode – Open4education
php estruturado composer
{
"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"
]
}
}
Globalcode – Open4education
php estruturado projeto
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
Globalcode – Open4education
php business
Globalcode – Open4education
php business
clareza no código
facilidade de crescimento
testes automatizados
Globalcode – Open4education
php business
testes automatizados
Globalcode – Open4education
php business testes automatizados
garantem regras conhecidas
auxiliam refatoração
não evitam bugs
Globalcode – Open4education
php business phpunit
PHPUnit 5.4.6 by Sebastian Bergmann and contributors.
................................................... 59 / 59 (100%)
Time: 349 ms, Memory: 6.00MB
OK (59 tests, 126 assertions)
Globalcode – Open4education
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::testUpdateProductFailed
Failed asserting that exception of type "ProductException" is
thrown.
FAILURES!
Tests: 59, Assertions: 125, Failures: 1.
php business phpunit
Globalcode – Open4education
php business
não confie em arrays
evite abreviações
Globalcode – Open4education
/**
* 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 business array, não confie!
Globalcode – Open4education
php business
objetos de valor
Globalcode – Open4education
php business objetos de valor
são objetos simples
encapsulam tipos primitivos
representam o valor
Globalcode – Open4education
class Status
{
const PENDING = 'P';
const SENT = 'S';
public function __construct($status)
{
$this->validate($status);
$this->status = $status;
}
// … other methods
public function equalsTo(Status $status)
{
return $status === $this;
}
}
php business objetos de valor
Globalcode – Open4education
php business
entidades
Globalcode – Open4education
php business entidades
são mutáveis
possuem identificador
Globalcode – Open4education
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;
}
}
php business entidades
Globalcode – Open4education
class WishlistItem
{
public function __construct(
Id $id,
$name,
Available $isAvailable
) {
$this->id = $id;
$this->name = $name;
$this->available = $isAvailable;
}
}
php business entidades
Globalcode – Open4education
php business
repositórios
Globalcode – Open4education
php business repositórios
camada de persistência
estratégia de armazenamento
Globalcode – Open4education
interface WishlistRepository
{
public function find($id);
public function findAllByEmail($email);
public function add(Wishlist $wishlist);
public function delete(Wishlist $wishlist);
public function findAllToNotify();
}
php business repositórios
Globalcode – Open4education
namespace DevelopBusinessApplicationProductWishlistRepositories;
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']
);
}
}
php business repositórios
Globalcode – Open4education
namespace DevelopBusinessApplicationProductWishlistRepositories;
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);
}
}
php business repositórios
Globalcode – Open4education
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());
}
}
php business repositórios
Globalcode – Open4education
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}"
);
}
}
php business repositórios
Globalcode – Open4education
function wishlistListAction($email)
{
$db = dbConnect();
$factory = new WishlistFactory();
$repository = new WishlistPdoRepository($db, $factory);
$wishlist = $repository->findAllByEmail($email);
include TEMPLATE_DIR . '/wishlists/list.php';
}
php business repositórios
Globalcode – Open4education
php business
serviços
Globalcode – Open4education
php business serviços
camada de operações
orquestram os objetos
definem o que fazer
Globalcode – Open4education
$db = dbConnect();
$factory = new WishlistFactory();
$repository = new WishlistRepository($db, $factory);
$resolver = new ItemResolver(new ProductRepository($db));
try {
$intention = getIntention($request['wish_item']);
$useCase = new AddItemWishlistUseCase(
$repository, $factory, $resolver
);
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";
} catch (Exception $e) {
$errormsg = $e->getMessage();
}
php business serviços
Globalcode – Open4education
class AddItemWishlistUseCase
{
public function execute(AddItemIntention $intention)
{
$item = $this->resolver->resolve($intention->itemId);
try {
$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 business serviços
Globalcode – Open4education
// 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();
$intention = new NotifyProductsAvailableIntention($pending);
$useCase = new NotifyProductsAvailableUseCase($repository, $notifier);
$useCase->execute($intention);
php business serviços
Globalcode – Open4education
class NotifyProductsAvailableUseCase
{
public function __construct($repository, $notifier)
public function execute(NotifyProductsIntention $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);
}
}
}
php business serviços
Globalcode – Open4education
php business
injeção de dependências
Globalcode – Open4education
php business injeção de dependência
princípio da inversão de dependência
dependências configuráveis
Globalcode – Open4education
php business injeção de dependência
Respect/Config
Globalcode – Open4education
// 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]
php business injeção de dependência
Globalcode – Open4education
// public/index.php
require_once __DIR__ . '/../config/app.php';
require_once __DIR__ . '/../vendor/autoload.php';
$configFile = __DIR__ . '/../config/app.ini';
$container = new RespectConfigContainer($configFile);
if ('/index.php/wishlist/add' === $uri /* other validation */) {
wishlistAddAction($container, $_GET['email'], $_POST);
}
php business injeção de dependência
Globalcode – Open4education
function wishlistAddAction(Container $container, $email, $request)
{
try {
$intention = getIntention($request['wish_item']);
$useCase = $container->wishlistAddItemWishlistUseCase;
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";
} catch (Exception $e) {
$errormsg = $e->getMessage();
}
}
php business injeção de dependência
Globalcode – Open4education
php business
eventos
Globalcode – Open4education
php business eventos
mecanismo de inversão de controle
comunicação assíncrona
baixo acoplamento
Globalcode – Open4education
php business eventos
symfony/event-dispatcher
Globalcode – Open4education
class UpdateProductUseCase
{
public function __construct($repository, $factory, $eventDispatcher);
public function execute(Intention $intention)
{
// do something
$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;
}
}
php business eventos
Globalcode – Open4education
class StockListener
{
public function __construct(NotifyProductAvailable $useCase);
public function __invoke(ProductStockIncreasedEvent $event)
{
$productId = $event->getProduct()->getId();
$intention = new NotifyProductIntention($productId);
$this->useCase->execute($intention);
}
}
php business eventos
Globalcode – Open4education
config/app.ini
[wishlistStockListener StockHasIncreasedListener]
useCase = [notifyProductAvailableUseCase]
[eventDispatcher EventDispatcher]
addListener[] = ["product.stock.increased", [wishlistStockListener]]
[productUpdateUseCase UpdateProductUseCase]
__construct = [[repository], [factory], [eventDispatcher]]
php business eventos
Globalcode – Open4education
php business
estrutura
Globalcode – Open4education
camadas
business
use cases
application
web
devices
useinterface
database
ExternalInterfaces
Globalcode – Open4education
// public/wishlist.php
// ...
if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) {
$wishItem = getWishList($_POST['wish_item']);
$db->beginTransaction();
try {
$stm = $db->prepare(
'INSERT INTO wishlists (email, product_id) VALUES (?, ?)'
);
$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
Globalcode – Open4education
function wishlistAddAction(Container $container, $email, $request)
{
try {
$intention = getIntention($request['wish_item']);
$useCase = $container->wishlistAddItemWishlistUseCase;
$wishlist = $useCase->execute($intention);
$successmsg = "{$wishlist->getItemName()} added!";
} catch (Exception $e) {
$errormsg = $e->getMessage();
}
}
php business
Globalcode – Open4education
estrutura inicial
developing-for-business
├── cli
│ ├── create_tables.php
│ └── wishlist_notification.php
├── data
│ └── business.db
├── lib
│ ├── dbconn.php
│ └── functions.php
└── public
├── product.php
└── wishlist.phpw
Globalcode – Open4education
estrutura de negócio
developing-for-business
└── src
└── Application
├── Product
│ ├── Controllers
│ └── Repositories
└── ProductWishlist
├── Controllers
├── Listeners
└── Repositories
developing-for-business
└── src
├── Product
│ ├── Events
│ ├── Exceptions
│ ├── Intentions
│ ├── Repositories
│ └── UseCases
└── Wishlist
├── Exceptions
├── Intentions
├── Repositories
└── UseCases
Globalcode – Open4education
conclusão
saia da zona de conforto
testes automatizados
domain driven design
domain specific language
princípio solid
Globalcode – Open4education
Life's too short for bad software
Lew Cirne, New Relic
Globalcode – Open4education
Implementing Domain-Driven Design
by Vaughn Vernon
Patterns of Enterprise Application Architecture
by Martin Fowler
Domain-Driven Design
by Eric Evans
DDD in PHP
by Carlos Buenosvinos, Christian Soronellas and Keyvan Akbary
referências
Globalcode – Open4education
Obrigado
tonicospinelli/developing-for-business
https://joind.in/talk/ad6a7

Contenu connexe

Tendances

PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesMarcello Duarte
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using CodeceptionJeroen van Dijk
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2Kacper Gunia
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...Rafael Dohms
 
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)Michael Wales
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2Curso Symfony - Clase 2
Curso Symfony - Clase 2Javier Eguiluz
 
So S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeSo S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeNeil Crookes
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowKacper Gunia
 
Top 5 Magento Secure Coding Best Practices
Top 5 Magento Secure Coding Best PracticesTop 5 Magento Secure Coding Best Practices
Top 5 Magento Secure Coding Best PracticesOleksandr Zarichnyi
 
Storytelling By Numbers
Storytelling By NumbersStorytelling By Numbers
Storytelling By NumbersMichael King
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4Javier Eguiluz
 
Zf2 how arrays will save your project
Zf2   how arrays will save your projectZf2   how arrays will save your project
Zf2 how arrays will save your projectMichelangelo van Dam
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Colin O'Dell
 

Tendances (19)

PhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examplesPhpSpec 2.0 ilustrated by examples
PhpSpec 2.0 ilustrated by examples
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Zero to SOLID
Zero to SOLIDZero to SOLID
Zero to SOLID
 
November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2November Camp - Spec BDD with PHPSpec 2
November Camp - Spec BDD with PHPSpec 2
 
What's new with PHP7
What's new with PHP7What's new with PHP7
What's new with PHP7
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
 
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Curso Symfony - Clase 2
Curso Symfony - Clase 2Curso Symfony - Clase 2
Curso Symfony - Clase 2
 
So S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better CodeSo S.O.L.I.D Fu - Designing Better Code
So S.O.L.I.D Fu - Designing Better Code
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
 
Top 5 Magento Secure Coding Best Practices
Top 5 Magento Secure Coding Best PracticesTop 5 Magento Secure Coding Best Practices
Top 5 Magento Secure Coding Best Practices
 
Storytelling By Numbers
Storytelling By NumbersStorytelling By Numbers
Storytelling By Numbers
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4
 
Zf2 how arrays will save your project
Zf2   how arrays will save your projectZf2   how arrays will save your project
Zf2 how arrays will save your project
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016
 

En vedette

TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcadostdc-globalcode
 
TDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital TransformationTDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital Transformationtdc-globalcode
 
Software
SoftwareSoftware
SoftwareITLA
 
Hemorragia uterina anormal revision sistemica
Hemorragia uterina anormal   revision sistemicaHemorragia uterina anormal   revision sistemica
Hemorragia uterina anormal revision sistemicaAlejandro Erazo
 
Infoirme 04-2015CEN/MAS.
Infoirme 04-2015CEN/MAS. Infoirme 04-2015CEN/MAS.
Infoirme 04-2015CEN/MAS. Tania Roja
 
Planificación de examen
Planificación de examenPlanificación de examen
Planificación de examenBruno Torterolo
 
Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.
Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.
Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.Txai Wieser
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcadostdc-globalcode
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcadostdc-globalcode
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcadostdc-globalcode
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcadostdc-globalcode
 
TDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital TransformationTDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital Transformationtdc-globalcode
 
TDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital TransformationTDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital Transformationtdc-globalcode
 
TDC2016SP - Trilha DevOps Java
TDC2016SP - Trilha DevOps JavaTDC2016SP - Trilha DevOps Java
TDC2016SP - Trilha DevOps Javatdc-globalcode
 

En vedette (20)

TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcados
 
TDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital TransformationTDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital Transformation
 
Software
SoftwareSoftware
Software
 
X& Y Part I
X& Y  Part  IX& Y  Part  I
X& Y Part I
 
Hemorragia uterina anormal revision sistemica
Hemorragia uterina anormal   revision sistemicaHemorragia uterina anormal   revision sistemica
Hemorragia uterina anormal revision sistemica
 
cotidiafonos
cotidiafonoscotidiafonos
cotidiafonos
 
Vassiliades (1)
Vassiliades (1)Vassiliades (1)
Vassiliades (1)
 
D1024242018
D1024242018D1024242018
D1024242018
 
Infoirme 04-2015CEN/MAS.
Infoirme 04-2015CEN/MAS. Infoirme 04-2015CEN/MAS.
Infoirme 04-2015CEN/MAS.
 
Ciencias
CienciasCiencias
Ciencias
 
Drones joshua
Drones joshuaDrones joshua
Drones joshua
 
Planificación de examen
Planificación de examenPlanificación de examen
Planificación de examen
 
Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.
Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.
Gerenciamento de Memória em Swift - The Weak, the Strong, and the Unowned.
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcados
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcados
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcados
 
TDC2016SP - Trilha Embarcados
TDC2016SP - Trilha EmbarcadosTDC2016SP - Trilha Embarcados
TDC2016SP - Trilha Embarcados
 
TDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital TransformationTDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital Transformation
 
TDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital TransformationTDC2016SP - Trilha Digital Transformation
TDC2016SP - Trilha Digital Transformation
 
TDC2016SP - Trilha DevOps Java
TDC2016SP - Trilha DevOps JavaTDC2016SP - Trilha DevOps Java
TDC2016SP - Trilha DevOps Java
 

Similaire à TDC2016SP - Trilha Developing for Business

Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Michelangelo van Dam
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkBo-Yi Wu
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsClinton Dreisbach
 
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Mike Schinkel
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Michelangelo van Dam
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastMichelangelo van Dam
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Michelangelo van Dam
 
PHP and Databases
PHP and DatabasesPHP and Databases
PHP and DatabasesThings Lab
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applicationschartjes
 
Gail villanueva add muscle to your wordpress site
Gail villanueva   add muscle to your wordpress siteGail villanueva   add muscle to your wordpress site
Gail villanueva add muscle to your wordpress sitereferences
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress DeveloperJoey Kudish
 
WordPress Plugin development
WordPress Plugin developmentWordPress Plugin development
WordPress Plugin developmentMostafa Soufi
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)Oleg Zinchenko
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Yevhen Kotelnytskyi
 

Similaire à TDC2016SP - Trilha Developing for Business (20)

Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP Applications
 
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfast
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
 
PHP and Databases
PHP and DatabasesPHP and Databases
PHP and Databases
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Gail villanueva add muscle to your wordpress site
Gail villanueva   add muscle to your wordpress siteGail villanueva   add muscle to your wordpress site
Gail villanueva add muscle to your wordpress site
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress Developer
 
WordPress Plugin development
WordPress Plugin developmentWordPress Plugin development
WordPress Plugin development
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Lecture9_OOPHP_SPring2023.pptx
Lecture9_OOPHP_SPring2023.pptxLecture9_OOPHP_SPring2023.pptx
Lecture9_OOPHP_SPring2023.pptx
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)
 
Fatc
FatcFatc
Fatc
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?
 

Plus de tdc-globalcode

TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidadeTDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidadetdc-globalcode
 
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...tdc-globalcode
 
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de SucessoTDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de Sucessotdc-globalcode
 
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPATDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPAtdc-globalcode
 
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVinoTDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVinotdc-globalcode
 
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...tdc-globalcode
 
TDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devicesTDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devicestdc-globalcode
 
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca PublicaTrilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publicatdc-globalcode
 
Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#tdc-globalcode
 
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case EasylocusTDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case Easylocustdc-globalcode
 
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?tdc-globalcode
 
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em GolangTDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em Golangtdc-globalcode
 
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QATDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QAtdc-globalcode
 
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendenciaTDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendenciatdc-globalcode
 
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR ServiceTDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Servicetdc-globalcode
 
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NETTDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NETtdc-globalcode
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8tdc-globalcode
 
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...tdc-globalcode
 
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#tdc-globalcode
 
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net CoreTDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Coretdc-globalcode
 

Plus de tdc-globalcode (20)

TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidadeTDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
 
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
 
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de SucessoTDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
 
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPATDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
 
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVinoTDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
 
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
 
TDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devicesTDC2019 Intel Software Day - Inferencia de IA em edge devices
TDC2019 Intel Software Day - Inferencia de IA em edge devices
 
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca PublicaTrilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
 
Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#Trilha .Net - Programacao funcional usando f#
Trilha .Net - Programacao funcional usando f#
 
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case EasylocusTDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Go - Case Easylocus
 
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
 
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em GolangTDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - Clean architecture em Golang
 
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QATDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
 
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendenciaTDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
 
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR ServiceTDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
 
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NETTDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
 
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
 
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
 
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - .NET funcional com F#
 
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net CoreTDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor  em .Net Core
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
 

Dernier

Mastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory InspectionMastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory InspectionSafetyChain Software
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxGaneshChakor2
 
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptxSOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptxiammrhaywood
 
mini mental status format.docx
mini    mental       status     format.docxmini    mental       status     format.docx
mini mental status format.docxPoojaSen20
 
Paris 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityParis 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityGeoBlogs
 
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Krashi Coaching
 
The basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxThe basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxheathfieldcps1
 
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...EduSkills OECD
 
Separation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesSeparation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesFatimaKhan178732
 
Student login on Anyboli platform.helpin
Student login on Anyboli platform.helpinStudent login on Anyboli platform.helpin
Student login on Anyboli platform.helpinRaunakKeshri1
 
Grant Readiness 101 TechSoup and Remy Consulting
Grant Readiness 101 TechSoup and Remy ConsultingGrant Readiness 101 TechSoup and Remy Consulting
Grant Readiness 101 TechSoup and Remy ConsultingTechSoup
 
“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...
“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...
“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...Marc Dusseiller Dusjagr
 
Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...
Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...
Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...RKavithamani
 
URLs and Routing in the Odoo 17 Website App
URLs and Routing in the Odoo 17 Website AppURLs and Routing in the Odoo 17 Website App
URLs and Routing in the Odoo 17 Website AppCeline George
 
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions  for the students and aspirants of Chemistry12th.pptxOrganic Name Reactions  for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions for the students and aspirants of Chemistry12th.pptxVS Mahajan Coaching Centre
 
How to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptxHow to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptxmanuelaromero2013
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdfQucHHunhnh
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfsanyamsingh5019
 

Dernier (20)

Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
Mattingly "AI & Prompt Design: Structured Data, Assistants, & RAG"
 
Mastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory InspectionMastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory Inspection
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptx
 
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptxSOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
SOCIAL AND HISTORICAL CONTEXT - LFTVD.pptx
 
mini mental status format.docx
mini    mental       status     format.docxmini    mental       status     format.docx
mini mental status format.docx
 
Paris 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activityParis 2024 Olympic Geographies - an activity
Paris 2024 Olympic Geographies - an activity
 
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
Kisan Call Centre - To harness potential of ICT in Agriculture by answer farm...
 
The basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptxThe basics of sentences session 2pptx copy.pptx
The basics of sentences session 2pptx copy.pptx
 
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
Presentation by Andreas Schleicher Tackling the School Absenteeism Crisis 30 ...
 
Separation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and ActinidesSeparation of Lanthanides/ Lanthanides and Actinides
Separation of Lanthanides/ Lanthanides and Actinides
 
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdfTataKelola dan KamSiber Kecerdasan Buatan v022.pdf
TataKelola dan KamSiber Kecerdasan Buatan v022.pdf
 
Student login on Anyboli platform.helpin
Student login on Anyboli platform.helpinStudent login on Anyboli platform.helpin
Student login on Anyboli platform.helpin
 
Grant Readiness 101 TechSoup and Remy Consulting
Grant Readiness 101 TechSoup and Remy ConsultingGrant Readiness 101 TechSoup and Remy Consulting
Grant Readiness 101 TechSoup and Remy Consulting
 
“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...
“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...
“Oh GOSH! Reflecting on Hackteria's Collaborative Practices in a Global Do-It...
 
Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...
Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...
Privatization and Disinvestment - Meaning, Objectives, Advantages and Disadva...
 
URLs and Routing in the Odoo 17 Website App
URLs and Routing in the Odoo 17 Website AppURLs and Routing in the Odoo 17 Website App
URLs and Routing in the Odoo 17 Website App
 
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions  for the students and aspirants of Chemistry12th.pptxOrganic Name Reactions  for the students and aspirants of Chemistry12th.pptx
Organic Name Reactions for the students and aspirants of Chemistry12th.pptx
 
How to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptxHow to Make a Pirate ship Primary Education.pptx
How to Make a Pirate ship Primary Education.pptx
 
1029-Danh muc Sach Giao Khoa khoi 6.pdf
1029-Danh muc Sach Giao Khoa khoi  6.pdf1029-Danh muc Sach Giao Khoa khoi  6.pdf
1029-Danh muc Sach Giao Khoa khoi 6.pdf
 
Sanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdfSanyam Choudhary Chemistry practical.pdf
Sanyam Choudhary Chemistry practical.pdf
 

TDC2016SP - Trilha Developing for Business

  • 1. Globalcode – Open4education Trilha – PHP Architecture Developing for Business
  • 2. Globalcode – Open4education apresentação Antonio Spinelli @tonicospinelli tonicospinelli85@gmail.com
  • 3. Globalcode – Open4education o propósito sempre é o mesmo: resolver problema para o negócio!
  • 5. Globalcode – Open4education comportamento escopo abstrato = problema desconhecido
  • 6. Globalcode – Open4education comportamento agregue valor para negócio entenda a demanda agilidade não é "sobrinhagem"
  • 7. Globalcode – Open4education conhecimento leia código peça e faça code review automatize tarefas repetitivas
  • 8. Globalcode – Open4education user story Lista de Desejos Eu como usuário convidado, quero adicionar um produto esgotado em minha lista de desejos para que eu receba uma notificação quando este estiver disponível. Objetivo reposição mais inteligente de produtos
  • 10. Globalcode – Open4education php estruturado adicionando um item na lista de desejos
  • 11. Globalcode – Open4education // public/wishlist.php // ... if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) { $wishItem = getWishList($_POST['wish_item']); $db->beginTransaction(); try { $stm = $db->prepare( 'INSERT INTO wishlists (email, product_id) VALUES (?, ?)' ); $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
  • 12. Globalcode – Open4education php estruturado // public/wishlist.php // ... <table> <?php foreach ($wishlist as $wish): ?> <tr> <td><?php echo $wish['id']; ?> </td> <td><?php echo $wish['product_name']; ?> </td> <?php if ($wish['product_stock'] == 0): ?> <td>Not Available</td> <?php else: ?> <td>Available</td> <?php endif; ?> <td> <?php echo removeUrl($wish['id'], ['email' => $email]); ?> </td> </tr> <?php endforeach; ?> </table> // ...
  • 13. Globalcode – Open4education php estruturado notificar usuário que o item está disponível
  • 14. Globalcode – Open4education php estruturado // 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 $wishlist) { mail( $wishlist['email'], "{$wishlist['product_name']} disponível", $mailBody ); $stm = $db->prepare("UPDATE wishlists SET status='S' WHERE id=?"); $stm->execute([$wishlist['id']]); }
  • 15. Globalcode – Open4education php estruturado Pronto! funciona!
  • 16. Globalcode – Open4education php estruturado quais problemas neste código?
  • 17. Globalcode – Open4education php estruturado organização pobre sem verificação de erro dificuldade de reusar código
  • 18. Globalcode – Open4education php estruturado isolando a apresentação
  • 19. Globalcode – Open4education php estruturado // templates/wishlist/list.php <table> <?php foreach ($wishlist as $wish): ?> <tr> <td><?php echo $wish['id']; ?> </td> <td><?php echo $wish['product_name']; ?> </td> <?php if ($wish['product_stock'] == 0): ?> <td>Not Available</td> <?php else: ?> <td>Available</td> <?php endif; ?> <td> <?php echo removeUrl($wish['id'], ['email' => $email]); ?> </td> </tr> <?php endforeach; ?> </table>
  • 20. Globalcode – Open4education php estruturado isolando regras de negócio
  • 21. Globalcode – Open4education php estruturado function isValidWishList(array $data); function getWishList(array $data); function findAllWishProducts($email); function addWishItem(array $data); function removeWishItem($id); function findAllWishlistsToNotify(); function wishlistNotified($id);
  • 22. Globalcode – Open4education php estruturado interagindo com regra de negócio e apresentação
  • 23. Globalcode – Open4education php estruturado public/wishlist.php require_once __DIR__ . '/../lib/functions.php'; require_once __DIR__ . '/../lib/models/wishlist.php'; require_once __DIR__ . '/../lib/dbconn.php'; if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) { $wishItem = getWishList($_POST['wish_item']); if (addWishItem($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';
  • 24. Globalcode – Open4education php estruturado isolando layout
  • 25. Globalcode – Open4education php estruturado // template/layout.php <!DOCTYPE html> <html> <head> <title><?php echo $title ?></title> </head> <body> <?php echo $content ?> </body> </html>
  • 26. Globalcode – Open4education 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' ?>
  • 27. Globalcode – Open4education php estruturado front controller
  • 28. Globalcode – Open4education php estruturado Without a front controller GET /wishlist.php?email=email@test.com With index.php as the front controller GET /index.php/wishlist/email@test.com
  • 29. Globalcode – Open4education php puro front controller // public/index.php // load function files // 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>'; }
  • 30. Globalcode – Open4education php estruturado autoload
  • 31. Globalcode – Open4education php estruturado autoload // public/index.php require_once __DIR__ . '/../config/app.php'; require_once LIBRARY_DIR . '/functions.php'; require_once LIBRARY_DIR . '/models/wishlist.php'; require_once LIBRARY_DIR . '/controllers/wishlist.php'; // include_path is other alternative ini_set('include_path', __DIR__ . '/../lib');
  • 32. Globalcode – Open4education php estruturado composer { "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" ] } }
  • 33. Globalcode – Open4education php estruturado projeto 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
  • 35. Globalcode – Open4education php business clareza no código facilidade de crescimento testes automatizados
  • 36. Globalcode – Open4education php business testes automatizados
  • 37. Globalcode – Open4education php business testes automatizados garantem regras conhecidas auxiliam refatoração não evitam bugs
  • 38. Globalcode – Open4education php business phpunit PHPUnit 5.4.6 by Sebastian Bergmann and contributors. ................................................... 59 / 59 (100%) Time: 349 ms, Memory: 6.00MB OK (59 tests, 126 assertions)
  • 39. Globalcode – Open4education 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::testUpdateProductFailed Failed asserting that exception of type "ProductException" is thrown. FAILURES! Tests: 59, Assertions: 125, Failures: 1. php business phpunit
  • 40. Globalcode – Open4education php business não confie em arrays evite abreviações
  • 41. Globalcode – Open4education /** * 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 business array, não confie!
  • 42. Globalcode – Open4education php business objetos de valor
  • 43. Globalcode – Open4education php business objetos de valor são objetos simples encapsulam tipos primitivos representam o valor
  • 44. Globalcode – Open4education class Status { const PENDING = 'P'; const SENT = 'S'; public function __construct($status) { $this->validate($status); $this->status = $status; } // … other methods public function equalsTo(Status $status) { return $status === $this; } } php business objetos de valor
  • 45. Globalcode – Open4education php business entidades
  • 46. Globalcode – Open4education php business entidades são mutáveis possuem identificador
  • 47. Globalcode – Open4education 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; } } php business entidades
  • 48. Globalcode – Open4education class WishlistItem { public function __construct( Id $id, $name, Available $isAvailable ) { $this->id = $id; $this->name = $name; $this->available = $isAvailable; } } php business entidades
  • 49. Globalcode – Open4education php business repositórios
  • 50. Globalcode – Open4education php business repositórios camada de persistência estratégia de armazenamento
  • 51. Globalcode – Open4education interface WishlistRepository { public function find($id); public function findAllByEmail($email); public function add(Wishlist $wishlist); public function delete(Wishlist $wishlist); public function findAllToNotify(); } php business repositórios
  • 52. Globalcode – Open4education namespace DevelopBusinessApplicationProductWishlistRepositories; 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'] ); } } php business repositórios
  • 53. Globalcode – Open4education namespace DevelopBusinessApplicationProductWishlistRepositories; 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); } } php business repositórios
  • 54. Globalcode – Open4education 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()); } } php business repositórios
  • 55. Globalcode – Open4education 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}" ); } } php business repositórios
  • 56. Globalcode – Open4education function wishlistListAction($email) { $db = dbConnect(); $factory = new WishlistFactory(); $repository = new WishlistPdoRepository($db, $factory); $wishlist = $repository->findAllByEmail($email); include TEMPLATE_DIR . '/wishlists/list.php'; } php business repositórios
  • 57. Globalcode – Open4education php business serviços
  • 58. Globalcode – Open4education php business serviços camada de operações orquestram os objetos definem o que fazer
  • 59. Globalcode – Open4education $db = dbConnect(); $factory = new WishlistFactory(); $repository = new WishlistRepository($db, $factory); $resolver = new ItemResolver(new ProductRepository($db)); try { $intention = getIntention($request['wish_item']); $useCase = new AddItemWishlistUseCase( $repository, $factory, $resolver ); $wishlist = $useCase->execute($intention); $successmsg = "{$wishlist->getItemName()} added!"; } catch (Exception $e) { $errormsg = $e->getMessage(); } php business serviços
  • 60. Globalcode – Open4education class AddItemWishlistUseCase { public function execute(AddItemIntention $intention) { $item = $this->resolver->resolve($intention->itemId); try { $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 business serviços
  • 61. Globalcode – Open4education // 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(); $intention = new NotifyProductsAvailableIntention($pending); $useCase = new NotifyProductsAvailableUseCase($repository, $notifier); $useCase->execute($intention); php business serviços
  • 62. Globalcode – Open4education class NotifyProductsAvailableUseCase { public function __construct($repository, $notifier) public function execute(NotifyProductsIntention $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); } } } php business serviços
  • 63. Globalcode – Open4education php business injeção de dependências
  • 64. Globalcode – Open4education php business injeção de dependência princípio da inversão de dependência dependências configuráveis
  • 65. Globalcode – Open4education php business injeção de dependência Respect/Config
  • 66. Globalcode – Open4education // 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] php business injeção de dependência
  • 67. Globalcode – Open4education // public/index.php require_once __DIR__ . '/../config/app.php'; require_once __DIR__ . '/../vendor/autoload.php'; $configFile = __DIR__ . '/../config/app.ini'; $container = new RespectConfigContainer($configFile); if ('/index.php/wishlist/add' === $uri /* other validation */) { wishlistAddAction($container, $_GET['email'], $_POST); } php business injeção de dependência
  • 68. Globalcode – Open4education function wishlistAddAction(Container $container, $email, $request) { try { $intention = getIntention($request['wish_item']); $useCase = $container->wishlistAddItemWishlistUseCase; $wishlist = $useCase->execute($intention); $successmsg = "{$wishlist->getItemName()} added!"; } catch (Exception $e) { $errormsg = $e->getMessage(); } } php business injeção de dependência
  • 70. Globalcode – Open4education php business eventos mecanismo de inversão de controle comunicação assíncrona baixo acoplamento
  • 71. Globalcode – Open4education php business eventos symfony/event-dispatcher
  • 72. Globalcode – Open4education class UpdateProductUseCase { public function __construct($repository, $factory, $eventDispatcher); public function execute(Intention $intention) { // do something $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; } } php business eventos
  • 73. Globalcode – Open4education class StockListener { public function __construct(NotifyProductAvailable $useCase); public function __invoke(ProductStockIncreasedEvent $event) { $productId = $event->getProduct()->getId(); $intention = new NotifyProductIntention($productId); $this->useCase->execute($intention); } } php business eventos
  • 74. Globalcode – Open4education config/app.ini [wishlistStockListener StockHasIncreasedListener] useCase = [notifyProductAvailableUseCase] [eventDispatcher EventDispatcher] addListener[] = ["product.stock.increased", [wishlistStockListener]] [productUpdateUseCase UpdateProductUseCase] __construct = [[repository], [factory], [eventDispatcher]] php business eventos
  • 75. Globalcode – Open4education php business estrutura
  • 76. Globalcode – Open4education camadas business use cases application web devices useinterface database ExternalInterfaces
  • 77. Globalcode – Open4education // public/wishlist.php // ... if (isset($_POST['submit']) && isValidWishList($_POST['wish_item'])) { $wishItem = getWishList($_POST['wish_item']); $db->beginTransaction(); try { $stm = $db->prepare( 'INSERT INTO wishlists (email, product_id) VALUES (?, ?)' ); $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
  • 78. Globalcode – Open4education function wishlistAddAction(Container $container, $email, $request) { try { $intention = getIntention($request['wish_item']); $useCase = $container->wishlistAddItemWishlistUseCase; $wishlist = $useCase->execute($intention); $successmsg = "{$wishlist->getItemName()} added!"; } catch (Exception $e) { $errormsg = $e->getMessage(); } } php business
  • 79. Globalcode – Open4education estrutura inicial developing-for-business ├── cli │ ├── create_tables.php │ └── wishlist_notification.php ├── data │ └── business.db ├── lib │ ├── dbconn.php │ └── functions.php └── public ├── product.php └── wishlist.phpw
  • 80. Globalcode – Open4education estrutura de negócio developing-for-business └── src └── Application ├── Product │ ├── Controllers │ └── Repositories └── ProductWishlist ├── Controllers ├── Listeners └── Repositories developing-for-business └── src ├── Product │ ├── Events │ ├── Exceptions │ ├── Intentions │ ├── Repositories │ └── UseCases └── Wishlist ├── Exceptions ├── Intentions ├── Repositories └── UseCases
  • 81. Globalcode – Open4education conclusão saia da zona de conforto testes automatizados domain driven design domain specific language princípio solid
  • 82. Globalcode – Open4education Life's too short for bad software Lew Cirne, New Relic
  • 83. Globalcode – Open4education Implementing Domain-Driven Design by Vaughn Vernon Patterns of Enterprise Application Architecture by Martin Fowler Domain-Driven Design by Eric Evans DDD in PHP by Carlos Buenosvinos, Christian Soronellas and Keyvan Akbary referências