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
68
Background Jobs - Ao infinito e além
hugohenrique
1
200
Other Decks in Programming
See All in Programming
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
2
400
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.6k
AWS CDKのカスタムリソースでContinuum(旧Security Agent)を実装した話 | Implementing Continuum (formerly Security Agent) via AWS CDK Custom Resource
akihisaikeda
2
150
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
790
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
380
Apple Intelligence を用いた個人情報誤送信防止、及びユーザーリクエスト体験の改善について
yukiny
0
350
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
160
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
260
APNsからLive Activityを開始する話
yumnumm
0
170
Railsバージョンを4倍にした話
optim
0
440
Featured
See All Featured
How to Ace a Technical Interview
jacobian
280
24k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
560
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
780
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
930
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
730
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
330
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
310
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
My Coaching Mixtape
mlcsv
0
360
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