Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Evoluindo sua aplicação - Arquitetura Hexagonal
Search
Hugo Henrique
October 10, 2017
Programming
300
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Evoluindo sua aplicação - Arquitetura Hexagonal
Apresentado no dia 08/10/2017 no PHPeste em Fortaleza-CE
Hugo Henrique
October 10, 2017
More Decks by Hugo Henrique
See All by Hugo Henrique
CommandBus
hugohenrique
0
67
Background Jobs - Ao infinito e além
hugohenrique
1
200
Other Decks in Programming
See All in Programming
アクセシビリティから考える情報設計
high_g_engineer
0
380
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
140
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
0
1.3k
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
120
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
3
340
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
240
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
0
540
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
200
スマート反転とウェブアクセシビリティ
camiha
0
210
Claude Codeを組織的に動かして月400PRを実現した話
happy_ryo
0
280
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
180
Security issues being discussed on Web Platforms
petamoriken
0
940
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
699
190k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
Become a Pro
speakerdeck
PRO
31
6.3k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
58k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.5k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
330
Crafting Experiences
bethany
1
340
Unsuck your backbone
ammeep
672
58k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
850
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
Visualization
eitanlees
152
17k
Transcript
&70-6*/%046""1-*$"ª§0 "326*5&563")&9"(0/"- !IVHPIFOSJRVF
)6(0)&/3*26& !IVHPIFOSJRVF
"4"1-*$"ª¸&4/03."-.&/5& $0.&ª".&..6/%01&3'&*50
None
$&/¥3*0$0.6.%"$3*"ª§0%&6.40'58"3& 4&(6/%00.6/%0%"445"35614
.7$
None
4$3*15.6*50$0.6.1"3"*/*$*"36.130+&50 %&40'58"3&/0$&/¥3*045"3561 &4$0-)&36.'3".&803, */45"-"36.130+&50&426&-&50 3&.07&3$0*4"4%&%&.0/453"ª§0 $3*"3&/5*%"%&4
"650(&/&3"5& $3*"3$36%$0/530--&3`4 "650(&/&3"5&
1 <?php 2 namespace App\Http; 3 4 use MyLovedFramework\Controller; 5
use MyLovedFramework\Request; 6 7 class BookController extends Controller 8 { 9 // ... 10 public function purchaseAction(Request $request) 11 { 12 if ($bookId = $request->query->get('bookId')) { 13 throw new \InvalidArgumentException(sprintf('The book %s cannot be found', $bookId)); 14 } 15 16 try { 17 $this->entityManager->beginTransaction(); 18 19 $book = $this->bookRepository->find($bookId); 20 21 $buyer = $this->currentSession()->user(); 22 $buyer->purchase($book); 23 24 $this->userRepository->persist($buyer); 25 26 $this->logger->log('info', sprintf('The book %s was purchased by user %s', $bookId, $buyer->getId())); 27 28 $this->mailer->send( 29 $buyer->getEmailAddress(), 30 'Your purchase is being processed', 31 'template_purchase.html' 32 ); 33 34 $this->entityManager->commit(); 35 36 return new Response(200, 'You purchase has been processed!'); 37 } catch (\Exception $e) { 38 $this->entityManager->rollback(); 39 $this->logger->log('error', $e->getMessage()); 40 return new Response(500, 'Problem to processing request'); 41 } 42 } 43 }
$0.1-&9*%"%& "-50"$01-".&/50 .*4563"%&$0/$&*504 %*'°$*-."/65&/*#*-*%"%&
$0/530--&3%3*7&/%&4*(/
5&45&4$0.1-&904&-&/504 10326&04'3".&803,4+¥/§03&40-7&&44&130#-&."
'3".&803,4 &/$"146-".&/50
<?php $content = file_get_contents('php://input'); $contentType = $_SERVER['CONTENT_TYPE']; if ($contentType ===
'application/json') { $data = json_decode($content, true); } else if ($contentType === 'application/xml') { $data = simplexml_load_string($requestContent); } // ... -08-&7&-"1*
<?php $data = $serializer->deserialize( $request->getContent(), $request->getContentType() ); &4$0/%&%&5"-)&4 &7*5"%61-*$*%"%&
-08-&7&-"1* $stmt = $db->prepare('SELECT * FROM Customer c WHERE c.age
>= ?'); $stmt->bindValue(1, 18); $stmt->execute(); $raw = $stmt->fetch(PDO::FETCH_ASSOC); $customer = Customer::fromArray($raw);
&4$0/%&04%&5"-)&4%&*.1-&.&/5"ª§0 $customer = $repository->createQueryBuilder('c') ->where('c.age >= :age') ->setParameter('age', 18) ->getQuery()
->getResult();
&4$0/%&04%&5"-)&4%&*.1-&.&/5"ª§0 $customers = $repository->olderAge();
0'0$0%&7&4&3/"4'6/$*0/"-*%"%&4 $03@*/&44%0."*/
&4$0-)&36.'3".&803, */45"-"36.130+&50&426&-&50 3&.07&3$0*4"4%&%&.0/453"ª§0 $3*"3&/5*%"%&4 "650(&/&3"5&
$3*"3$36%$0/530--&3`4 "650(&/&3"5&
1 <?php 2 namespace App\Http; 3 4 use MyLovedFramework\Controller; 5
use MyLovedFramework\Request; 6 7 class BookController extends Controller 8 { 9 // ... 10 public function purchaseAction(Request $request) 11 { 12 if ($bookId = $request->query->get('bookId')) { 13 throw new \InvalidArgumentException(sprintf('The book %s cannot be found', $bookId)); 14 } 15 16 try { 17 $this->entityManager->beginTransaction(); 18 19 $book = $this->bookRepository->find($bookId); 20 21 $buyer = $this->currentSession()->user(); 22 $buyer->purchase($book); 23 24 $this->userRepository->persist($buyer); 25 26 $this->logger->log('info', sprintf('The book %s was purchased by user %s', $bookId, $buyer->getId())); 27 28 $this->mailer->send( 29 $buyer->getEmailAddress(), 30 'Your purchase is being processed', 31 'template_purchase.html' 32 ); 33 34 $this->entityManager->commit(); 35 36 return new Response(200, 'You purchase has been processed!'); 37 } catch (\Exception $e) { 38 $this->entityManager->rollback(); 39 $this->logger->log('error', $e->getMessage()); 40 return new Response(500, 'Problem to processing request'); 41 } 42 } 43 }
1 <?php 2 namespace App\Http; 3 4 use MyLovedFramework\Controller; 5
use MyLovedFramework\Request; 6 7 class BookController extends Controller 8 { 9 // ... 10 public function purchaseAction(Request $request) 11 { 12 if ($bookId = $request->query->get('bookId')) { 13 throw new \InvalidArgumentException(sprintf('The book %s cannot be found', $bookId)); 14 } 15 16 try { 17 $this->entityManager->beginTransaction(); 18 19 $book = $this->bookRepository->find($bookId); 20 21 $buyer = $this->currentSession()->user(); 22 $buyer->purchase($book); 23 24 $this->userRepository->persist($buyer); 25 26 $this->logger->log('info', sprintf('The book %s was purchased by user %s', $bookId, $buyer->getId())); 27 28 $this->mailer->send( 29 $buyer->getEmailAddress(), 30 'Your purchase is being processed', 31 'template_purchase.html' 32 ); 33 34 $this->entityManager->commit(); 35 36 return new Response(200, 'You purchase has been processed!'); 37 } catch (\Exception $e) { 38 $this->entityManager->rollback(); 39 $this->logger->log('error', $e->getMessage()); 40 return new Response(500, 'Problem to processing request'); 41 } 42 } 43 } $¶%*(0$0.#"*9"$0&4§0&6. "-50"$01-".&/50"0'3".&803,
3&64"#*-*%"%&%&$¶%*(0¬*.1044°7&- 8&# 'VODJPOBMJEBEF $PNQSBSVN-JWSP $-* $PNNBOE-JOF
1 <?php 2 namespace App\Http; 3 4 use MyLovedFramework\Controller; 5
use MyLovedFramework\Request; 6 7 class BookController extends Controller 8 { 9 // ... 10 public function purchaseAction(Request $request) 11 { 12 if ($bookId = $request->query->get('bookId')) { 13 throw new \InvalidArgumentException(sprintf('The book %s cannot be found', $bookId)); 14 } 15 16 try { 17 $this->entityManager->beginTransaction(); 18 19 $book = $this->bookRepository->find($bookId); 20 21 $buyer = $this->currentSession()->user(); 22 $buyer->purchase($book); 23 24 $this->userRepository->persist($buyer); 25 26 $this->logger->log('info', sprintf('The book %s was purchased by user %s', $bookId, $buyer->getId())); 27 28 $this->mailer->send( 29 $buyer->getEmailAddress(), 30 'Your purchase is being processed', 31 'template_purchase.html' 32 ); 33 34 $this->entityManager->commit(); 35 36 return new Response(200, 'You purchase has been processed!'); 37 } catch (\Exception $e) { 38 $this->entityManager->rollback(); 39 $this->logger->log('error', $e->getMessage()); 40 return new Response(500, 'Problem to processing request'); 41 } 42 } #"*9"$0&4§0
4:.'0/: %0$53*/& 3&"$5+4 3"##*5.2 "11-*$"5*0/
&44&/$*"- %&5"-)&4 %&5"-)&4
5)&)&"350'40'58"3&*4*54"#*-*5:5040-7& %0."*/3&-"5&%130#-&.4'03*5464&3z &3*$&7"/4 %0."*/%3*7&/%&4*(/
"11 */'3"4536$563& 8&##3084&3 %"5"#"4& 5&3.*/"- '*-&4:45&. 06530 06530
$"."%"4
$0.6/*$"ª§0 A
.&/4"(&. .6/%0&95&3/0 "11 8&#)5551 305"4 .&/4"(&. "1*3&45'6- .&/4"(&. $-*
.&/4"(&. 8&#)5551 305"4 .&/4"(&. "1*3&45'6- .&/4"(&. $-*
Http Request Controller Form Repository Entity Value Object
l10354"/%"%"15&34z "326*5&563")&9"(0/"-
$0.."/%#64 $0.."/% )"/%-&3
."4"'*/"-026&¬6.$0.."/%
5*104%&.&/4"(&/4 *.1&3"5*7"4 $0.."/% */5&330("5*7" 26&3: */'03."5*7" &7&/5
5*104%&.&/4"(&/4 *.1&3"5*7"4 $0.."/% */5&330("5*7" 26&3: */'03."5*7" &7&/5
6.$0."/%0¬6."4*.1-&4.&/4"(&.*.1&3"5*7" 26&0#3*("503*".&/5&%&7&4&34*.1-&4
6.$0."/%0%&7&*/%*$"30$0.1035".&/5026& 6.646¥3*006$-*&/5&&41&3"%0"1-*$"5*70
3FHJTUFS6TFS 1VSDIBTF#PPL 4UBSU%JTDVTTJPO 4JHO6Q
%&7&$0/5&340.&/5&"4*/'03."ª¸&4 1"3"3&"-*;"346"5"3&'" <?php final class PurchaseBook { private $bookId; private
$readerId; public function __construct(BookId $bookId, ReaderId $readerId) { $this->bookId = $bookId; $this->readerId = $readerId; } }
*.65¥7&- <?php final class PurchaseBook { private $bookId; private $readerId;
public function __construct(BookId $bookId, ReaderId $readerId) { $this->bookId = $bookId; $this->readerId = $readerId; } public function bookId() : BookId { return $this->bookId; } public function readerId() : ReaderId { return $this->readerId; } }
4&3"6507"-*%"%" <?php final class PurchaseBook { private $bookId; private $readerId;
public function __construct(BookId $bookId, ReaderId $readerId) { Assertion::notNull($bookId); Assertion::notNull($readerId); $this->bookId = $bookId; $this->readerId = $readerId; } public function bookId() : BookId { return $this->bookId; } public function readerId() : ReaderId { return $this->readerId; } }
$0.."/%*44*.1-&"%50 %"5"53"/4'&30#+&$5 1 <?php 2 namespace App\Domain\Member; 3 4 class
RegisterMember 5 { 6 private $emailAddress; 7 private $password; 8 9 public function __construct(string $emailAddress, string $password) 10 { 11 $this->emailAddress = $emailAddress; 12 $this->password = $password; 13 } 14 15 public function emailAddress() : string 16 { 17 return $this->emailAddress; 18 } 19 20 public function password() : string 21 { 22 return $this->password; 23 } 24 }
$0.0*/5&313&5"304$0."/%04 $0.."/%)"/%-&3
<?php namespace App\Handler; class PuchaseBookHandler { public function __invoke(PurchaseCommand $command)
: void { try { $this->entityManager->beginTransaction(); $buyer = $this->userRepository->find($command->buyerId()); $book = $this->bookRepository->find($command->bookId()); $buyer->purchase($book); $this->userRepository->persist($buyer); $this->entityManager->commit(); $this->mailer->send( $buyer->getEmailAddress(), 'Your purchase is being processed', 'template_purchase.html' ); // Logs the purchase } catch (\Exception $e) { $this->entityManager->rollback(); // Logs when error is raised } } }
6.$0.."/%4¶10%&4&3"440$*"%0"6.)"/%-&3 6.)"/%-&34¶10%&4&3"440$*"%0"6.$0.."/%
6.)"/%-&3/§0%&7&3&503/"37"-03 4)06-%#&70*%
26"*4"43&"*47"/5"(&/4%&64"3&44""#03%"(&. 10%&4&3&9&$65"%0&.26"-26&31"35&%"46""1-*$"ª§0 8&#$-* /§05&3¥."*4$¶%*(03&1&5*%0 4&6$0/530--&3/§05&3¥3&(3"%&/&(¶$*0 ."*03'"$*-*%"%&1"3"5&45"3
<?php namespace Infrastructure\Command; class RegisterMemberConsoleCommand extends ConsoleCommand { public function
execute(Input $input) { $command = new RegisterMember( $input->getArgument('emailAddress'), $input->getArgument('password') ); $this->commandBus()->handle($command); } }
Http Request Controller Form INFRASTRUCTURE APPLICATION DOMAIN PurchaseCommand PurchaseHandler Entity
Repository
<?php namespace App\Http; use MyLovedFramework\Controller; use MyLovedFramework\Request; class BookController extends
Controller { // ... public function purchaseAction(Request $request) { $userId = $this->session->currentUser()->id(); $bookId = $request->get('bookId'); $command = new PurchaseBook($bookId, $userId); $this->commandBus->handle($command); // ... } }
¼/*$010/50%&&/53"%"1"3"46""1-*$"ª§0 4*/(-&10*/50''"*-63& 410'
"(03"70-5"/%01"3"0)"/%-&3 7".04"/"-*4"3$0.."*4$"65&-"
."4"/5&47".040-)"31"3"6."4*.1-&4 *.1-&.&/5"ª§0%&6.$0.."/%#64
<?php interface CommandBus { public function handle($command) : void; }
<?php class SimpleCommandBus implements CommandBus { private $handlerMap; public function
__construct($handlerMap = []) { $this->handlerMap = $handlerMap; } public function handle($command) : void { // .. $this->handlerMap(get_class($command))->handle($command); // .. } }
$handler = new PurchaseBookHandler(); $handlerMap = [ 'PurchaseCommand' => $handler
]; $command = new PurchaseCommand(); $commandBus = new SimpleCommandBus($handlerMap); $commandBus->handle($command);
<?php namespace App\Book\Application; use App\Book\Domain\PurchaseCommand; class PurchaseBookHandler { public function
__invoke(PurchaseCommand $command) { try { $this->entityManager->beginTransaction(); $buyer = $this->userRepository->find($command->buyerId()); $book = $this->bookRepository->find($command->bookId()); $buyer->purchase($book); $this->userRepository->persist($buyer); $this->entityManager->commit(); $this->mailer->send( $buyer->getEmailAddress(), 'Your purchase is being processed', 'template_purchase.html' ); $this->logger->log('success', 'Your purchase is being processed'); // Logs the purchase } catch (\Exception $e) { $this->entityManager->rollback(); $this->logger->log('error', sprintf('Error to purchase book %s.', $command->bookId())); } } }
."*4&04*/(-&3&410/4*#*-*5:13*/$*1-& 431
.JEEMFXBSF .JEEMFXBSF .JEEMFXBSF $PNNBOE)BOEMFS 3FRVFTU 3FTQPOTF
<?php class AnExampleMiddleware implements Middleware { public function execute($command, callable
$next) { // .. // .. $next($command); } }
<?php namespace League\Tactician\Doctrine\ORM; use Doctrine\ORM\EntityManagerInterface; use League\Tactician\Middleware; class TransactionMiddleware implements
Middleware { public function execute($command, callable $next) { $this->entityManager->beginTransaction(); try { $returnValue = $next($command); $this->entityManager->flush(); $this->entityManager->commit(); } catch (Exception $e) { $this->rollbackTransaction(); throw $e; } catch (Throwable $e) { $this->rollbackTransaction(); throw $e; } return $returnValue; } } $"40%&640 53"/4"ª¸&4$0. %0$53*/&03.
<?php namespace App\Book\Application; use App\Book\Domain\PurchaseCommand; class PurchaseBookHandler { public function
__invoke(PurchaseCommand $command) { try { $buyer = $this->userRepository->find($command->buyerId()); $book = $this->bookRepository->find($command->bookId()); $buyer->purchase($book); $this->userRepository->persist($buyer); $this->mailer->send( $buyer->getEmailAddress(), 'Your purchase is being processed', 'template_purchase.html' ); $this->logger->log('success', 'Your purchase is being processed’); } catch (\Exception $e) { $this->logger->log('error', sprintf('Error to purchase book %s.', $command->bookId())); } } }
<?php namespace League\Tactician\Logger; // .. class LoggerMiddleware implements Middleware {
// ... public function execute($command, callable $next) { $this->formatter->logCommandReceived($this->logger, $command); try { $returnValue = $next($command); } catch (Exception $e) { $this->formatter->logCommandFailed($this->logger, $command, $e); throw $e; } $this->formatter->logCommandSucceeded($this->logger, $command, $returnValue); return $returnValue; } } $"40%&640 -0(4
"(03"10%&.04&9&$65"3 /07"4"ª¸&4"/5&4&%&10*4 %"&9&$6ª§0%&6.$0."/%0
<?php namespace App\Book\Application; use App\Book\Domain\PurchaseCommand; class PurchaseBookHandler { public function
__invoke(PurchaseCommand $command) { try { $buyer = $this->userRepository->find($command->buyerId()); $book = $this->bookRepository->find($command->bookId()); $buyer->purchase($book); $this->userRepository->persist($buyer); $this->mailer->send( $buyer->getEmailAddress(), 'Your purchase is being processed', 'template_purchase.html' ); } catch (\Exception $e) { } } }
$0.640%&.*%%-&8"3&"41044*#*-*%"%&44§0*/¼.&3"4 -0((&3 7"-*%"503 4&$63*5: 1&3'03."/$&.&53*$4 46"/&$&44*%"%&
IUUQTHJUIVCDPN4JNQMF#VT.FTTBHF#VT
IUUQTHJUIVCDPNUIFQIQMFBHVFUBDUJDJBO
7".040-)"30"/5&4&%&10*4
<?php namespace App\Book\Application; use App\Book\Domain\PurchaseCommand; class PurchaseBookHandler { public function
__invoke(PurchaseCommand $command) : void { $buyer = $this->userRepository->find($command->buyerId()); $book = $this->bookRepository->find($command->bookId()); $buyer->purchase($book); $this->userRepository->persist($buyer); $this->mailer->send( $buyer->getEmailAddress(), 'Your purchase is being processed', 'template_purchase.html' ); } } <?php namespace App\Http; use MyLovedFramework\Controller; use MyLovedFramework\Request; class BookController extends Controller { // ... public function purchaseAction(Request $request) { $userId = $this->session->currentUser()->id(); $bookId = $request->get('bookId'); $command = new PurchaseBook($bookId, $userId); $this->commandHandler->handle($command); // ... } }
None
/04*-7&3#6--&5 IUUQXXXJUVELQFPQMFIFTK#461BSUJLMFSOPTJMWFSCVMMJUQEG
IUUQDVMUUUDPNDSFBUJOHVTJOHDPNNBOECVT IUUQTQIQBOETZNGPOZNBUUIJBTOPCBDLOMBXBWFPGDPNNBOECVTFT IUUQTQIQBOETZNGPOZNBUUIJBTOPCBDLOMSFTQPOTJCJMJUJFTPGUIFDPNNBOECVT IUUQTIBXONDDPPMDPNNBOECVT IUUQTHOVHBUHJUIVCJPUPXBSETDRSTDPNNBOECVTIUNM 3FGFSÊODJBT
0#3*("%0