SlideShare a Scribd company logo
Taming
Command Bus
Krzysztof Menżyk
 @kmenzyk
About me
Technical Leader at
Test infected
Believes that software is a craft
Loves domain modelling
Homebrewer & squash player
This talk is not
This talk is not
DDD*
This talk is not
CQRS*
Back to the
PAST
BEGAN
It all
with ...
class ProductController extends Controller
{
//...
public function updateAction($id)
{
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AcmeDemoBundle:Product')->find($id);
if (!$product) {
throw $this->createNotFoundException('Unable to find Product entity.');
}
$request = $this->getRequest();
$editForm = $this->createForm(new ProductType(), $product);
$editForm->bind($request);
if ($editForm->isValid()) {
$product->setLastUpdated(new DateTime);
$em->flush();
$message = Swift_Message::newInstance()
->setSubject('Product updated')
->setFrom($this->container->getParameter('acme.product_email.from'))
->setTo($this->container->getParameter('acme.product_email.to'))
->setBody($this->renderView(
'AcmeDemoBundle:Product:email.txt.twig',
array('product' => $product))
)
;
$this->get('mailer')->send($message);
return $this->redirect(
$this->generateUrl('product', array('id' => $id))
);
}
return new Response(
$this->renderView(
'AcmeDemoBundle:Product:edit.html.twig',
array(
'product' => $product,
'edit_form' => $editForm->createView(),
)
)
);
}
}
Controller
Driven Design
„approach”
class ProductController extends Controller
{
//...
public function updateAction($id)
{
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AcmeDemoBundle:Product')->find($id);
if (!$product) {
throw $this->createNotFoundException('Unable to find Product entity.');
}
$request = $this->getRequest();
$editForm = $this->createForm(new ProductType(), $product);
$editForm->bind($request);
if ($editForm->isValid()) {
$product->setLastUpdated(new DateTime);
$em->flush();
$message = Swift_Message::newInstance()
->setSubject('Product updated')
->setFrom($this->container->getParameter('acme.product_email.from'))
->setTo($this->container->getParameter('acme.product_email.to'))
->setBody($this->renderView(
'AcmeDemoBundle:Product:email.txt.twig',
array('product' => $product))
)
;
$this->get('mailer')->send($message);
return $this->redirect(
$this->generateUrl('product', array('id' => $id))
);
}
return new Response(
$this->renderView(
'AcmeDemoBundle:Product:edit.html.twig',
array(
'product' => $product,
'edit_form' => $editForm->createView(),
)
)
);
}
}
class ProductController extends Controller
{
//...
public function updateAction($id)
{
if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
$em = $this->getDoctrine()->getManager();
$product = $em->getRepository('AcmeDemoBundle:Product')->find($id);
if (!$product) {
throw $this->createNotFoundException('Unable to find Product entity.');
}
$request = $this->getRequest();
$editForm = $this->createForm(new ProductType(), $product);
$editForm->bind($request);
if ($editForm->isValid()) {
$product->setLastUpdated(new DateTime);
$em->flush();
$message = Swift_Message::newInstance()
->setSubject('Product updated')
->setFrom($this->container->getParameter('acme.product_email.from'))
->setTo($this->container->getParameter('acme.product_email.to'))
->setBody($this->renderView(
'AcmeDemoBundle:Product:email.txt.twig',
array('product' => $product))
)
;
$this->get('mailer')->send($message);
return $this->redirect(
$this->generateUrl('product', array('id' => $id))
);
}
return new Response(
$this->renderView(
'AcmeDemoBundle:Product:edit.html.twig',
array(
'product' => $product,
'edit_form' => $editForm->createView(),
)
)
);
}
}

LAYERS
Presentation
Presentation
Domain
Presentation
Service
Domain
Presentation
Service
Domain
Infrastructure
Presentation
Service
Domain
Infrastructure
Defines an application's
boundary with a layer
of services.
Service Layer
Establishes set
of available operations.
Service Layer
Coordinates
the application's
response in each
operation.
Service Layer
USE Cases
USER STORIES
Application Layer
class Library
{
public function borrowBook($bookId, $readerId)
{
// ...
}
}
class LibraryController
{
public function borrowAction(ServerRequestInterface $request)
{
// Forms, etc.
$this->library->borrowBook($bookId, $readerId);
// Response
}
}
class Library
{
public function borrowBook($bookId, $readerId)
{
if (null === $bookId || null === $readerId) {
throw new InvalidArgumentException();
}
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($bookId);
$book->borrowBy($readerId);
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
class Library
{
public function borrowBook($bookId, $readerId)
{
if (null === $bookId || null === $readerId) {
throw new InvalidArgumentException();
}
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($bookId);
$book->borrowBy($readerId);
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
class Library
{
public function borrowBook($bookId, $readerId)
{
if (null === $bookId || null === $readerId) {
throw new InvalidArgumentException();
}
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($bookId);
$book->borrowBy($readerId);
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
class Library
{
public function borrowBook($bookId, $readerId)
{
if (null === $bookId || null === $readerId) {
throw new InvalidArgumentException();
}
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($bookId);
$book->borrowBy($readerId);
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
class Library
{
public function borrowBook($bookId, $readerId)
{
if (null === $bookId || null === $readerId) {
throw new InvalidArgumentException();
}
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($bookId);
$book->borrowBy($readerId);
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
borrowBook($bookId, $readerId)
new BorrowBook($bookId, $readerId)
COMMAND
not a class/object
MESSAGE
Messaging Flavors
by @mathiasverraes
Messaging Flavors
by @mathiasverraes
Imperative
Messaging Flavors
by @mathiasverraes
Imperative
Command
Messaging Flavors
by @mathiasverraes
Imperative Interrogatory
Command
Messaging Flavors
by @mathiasverraes
Imperative Interrogatory
Command QUERY
Messaging Flavors
by @mathiasverraes
Imperative Interrogatory Informational
Command QUERY
Messaging Flavors
by @mathiasverraes
Imperative Interrogatory Informational
Command QUERY EVENT
Messaging Flavors
by @mathiasverraes
Imperative Interrogatory Informational
Command QUERY EVENT
Captures
THE INTENT
of the user
Supports
Ubiquitous
LANGUAGE
Borrow Book
Give Book Back
Register User
Start Subscription
Hire Employee
Contains
THE INPUT
to carry out the task
final class BorrowBook
{
public $bookId;
public $readerId;
public function __construct($bookId, $readerId)
{
$this->bookId = $bookId;
$this->readerId = $readerId;
}
}
Should be
IMMUTABLE
final class BorrowBook
{
private $bookId;
private $readerId;
public function __construct($bookId, $readerId)
{
$this->bookId = $bookId;
$this->readerId = $readerId;
}
public function getBookId()
{
return $this->bookId;
}
public function getReaderId()
{
return $this->readerId;
}
}
Must be
VALID
final class BorrowBook
{
private $bookId;
private $readerId;
public function __construct($bookId, $readerId)
{
Assertion::notNull($bookId);
Assertion::notNull($readerId);
$this->bookId = $bookId;
$this->readerId = $readerId;
}
public function getBookId()
{
return $this->bookId;
}
public function getReaderId()
{
return $this->readerId;
}
}
INTERPRET
How to
a command?
COMMAND
Handler
per command
ONE HANDLER
Returns
NO VALUE
final class BorrowBookHandler
{
public function handle(BorrowBook $command)
{
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($command->getBookId());
$book->borrowBy($command->getReaderId());
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
final class BorrowBookHandler
{
public function handle(BorrowBook $command)
{
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($command->getBookId());
$book->borrowBy($command->getReaderId());
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
One more thing ...
The BUS
COMMAND
BUS
Hands over
THE COMMAND
to
THE HANDLEr
Handler C
Command
Bus
Handler BHandler A
Handler C
Command C
Command
Bus
Handler BHandler A
Handler C
Command
Bus
Handler BHandler A
Command C
Handler C
Command
Bus
Handler BHandler A Command C
Handler C
Command
Bus
Handler BHandler A
Single
ENTRY POINT
to the application
interface CommandBus
{
public function handle($command);
}
class LibraryController
{
public function borrowAction(ServerRequestInterface $request)
{
// Forms, etc.
$this->commandBus->handle(new BorrowBook($bookId, $readerId));
// Response
}
}
class SomeOtherController
{
public function someOtherAction(ServerRequestInterface $request)
{
// Forms, etc.
$command = $form->getData();
$this->commandBus->handle($command);
// Response
}
}
class SomeOtherController
{
public function someOtherAction(ServerRequestInterface $request)
{
// Forms, etc.
$command = $form->getData();
$this->commandBus->handle($command);
// Response
}
}
class BorrowBookCli
{
protected function execute(InputInterface $input, OutputInterface $output)
{
// get $command from the input somehow
$this->commandBus->handle($command);
// ...
}
}
IMPLEMENT
Let's
the stupid thing
class SimpleCommandBus implements CommandBus
{
private $handlers;
public function __construct(array $handlers)
{
$this->handlers = $handlers;
}
public function handle($command)
{
$commandName = get_class($command);
if (!isset($this->handlers[$commandName])) {
throw new InvalidArgumentException('No handler');
}
$this->handlers[$commandName]->handle($command);
}
}
new SimpleCommandBus([
BorrowBook::class => $borrowBookHandler,
GiveBookBack::class => $giveBookBackHandler,
]);
That's it?
Do not
TRY IT
at home
class SimpleCommandBus implements CommandBus
{
private $handlers;
public function __construct(array $handlers)
{
$this->handlers = $handlers;
}
public function handle($command)
{
$commandName = get_class($command);
if (!isset($this->handlers[$commandName])) {
throw new InvalidArgumentException('No handler');
}
$this->handlers[$commandName]->handle($command);
}
}
Cross cutting
concerns
interface CommandBus
{
public function handle($command);
}
DECORATOR
class CommandBusWithAddedBehavior implements CommandBus
{
public function __construct(CommandBus $originalCommandBus)
{
$this->originalCommandBus = $originalCommandBus;
}
public function handle($command)
{
// do anything you want
$this->originalCommandBus->handle($command);
// do even more
}
}
new CommandBusWithAddedBehavior(
new SimpleCommandBus([
BorrowBook::class => $borrowBookHandler,
GiveBookBack::class => $giveBookBackHandler,
])
);
Command Bus
Decorator
Decorator
Command
final class BorrowBookHandler
{
public function handle(BorrowBook $command)
{
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($command->getBookId());
$book->borrowBy($command->getReaderId());
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
class TransactionalCommandBus implements CommandBus
{
public function __construct($innerCommandBus, $connection)
{
$this->innerCommandBus = $innerCommandBus;
$this->connection = $connection;
}
public function handle($command)
{
$this->connection->beginTransaction();
try {
$this->innerCommandBus->handle($command);
$this->connection->commit();
} catch (Exception $exception) {
$this->connection->rollBack();
throw $e;
}
}
}
final class BorrowBookHandler
{
public function handle(BorrowBook $command)
{
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($command->getBookId());
$book->borrowBy($command->getReaderId());
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
class LoggingCommandBus implements CommandBus
{
public function __construct($innerCommandBus, $logger)
{
$this->innerCommandBus = $innerCommandBus;
$this->logger = $logger;
}
public function handle($command)
{
$commandClass = get_class($command);
$this->logger->debug('Started handling ' . $commandClass);
try {
$this->innerCommandBus->handle($command);
} catch (Exception $exception) {
$this->logger->debug('Error while handling ' . $commandClass);
throw $e;
}
$this->logger->debug('Finished handling ' . $commandClass);
}
}
final class BorrowBookHandler
{
public function handle(BorrowBook $command)
{
$this->logging->debug('A reader is borrowing a book');
$this->connection->beginTransaction();
try {
$book = $this->books->get($command->getBookId());
$book->borrowBy($command->getReaderId());
$this->books->add($book);
$this->connection->commit();
} catch (Exception $e) {
$this->connection->rollBack();
$this->logging->debug('Ooops! Bad luck.');
throw $e;
}
$this->logging->debug('Success!');
}
}
final class BorrowBookHandler
{
public function handle(BorrowBook $command)
{
$book = $this->books->get($command->getBookId());
$book->borrowBy($command->getReaderId());
$this->books->add($book);'Success!');
}
}
Easy to
TEST
But...
new LoggingCommandBus(
new TransactionalCommandBus(
new SimpleCommandBus([
BorrowBook::class => $borrowBookHandler,
GiveBookBack::class => $giveBookBackHandler,
]),
$connection
),
$logger
);
Can we do better?
Yes
We can!
CHAIN OF
RESPONSIBILITY
interface CommandBusMiddleware
{
public function handle($command, callable $next);
}
Command
Handler
Middleware
Command
Middleware
Middleware
class AddedBehaviorMiddleware implements CommandBusMiddleware
{
public function handle($command, callable $next)
{
// do anything you want
$next($command);
// do even more
}
}
new CommandBusSupportingMiddleware([
new AddedBehaviorMiddleware(),
new CommandHandlerMiddleware([
BorrowBook::class => $borrowBookHandler,
GiveBookBack::class => $giveBookBackHandler,
])
]);
new CommandBusSupportingMiddleware([
new LoggingMiddleware($logger),
new TransactionalMiddleware($connection),
new CommandHandlerMiddleware([
BorrowBook::class => $borrowBookHandler,
GiveBookBack::class => $giveBookBackHandler,
])
]);
Transactions
Logging
Security
Performance Metrics
Audit log
You name it
Command Bus libraries
by @matthiasnoback
Simple Bus
by @rosstuck
TACTICIAN
by @qandidate-labs
BROADWAY
Use them and contribute
Like we
DID
Krzysztof Menżyk
 @kmenzyk
Thanks!
Taming Command Bus
PHOTO CREDITS
https://flic.kr/p/F2qhc7
https://flic.kr/p/zMzVzW
https://flic.kr/p/F4j2fH
https://flic.kr/p/5a5d3b
https://flic.kr/p/vXAK3D

More Related Content

PDF
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
PDF
Be pragmatic, be SOLID
PDF
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
PDF
Design Patterns in PHP5
PDF
Min-Maxing Software Costs - Laracon EU 2015
PDF
Decoupling with Design Patterns and Symfony2 DIC
PDF
Min-Maxing Software Costs
PDF
Design how your objects talk through mocking
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
Design Patterns in PHP5
Min-Maxing Software Costs - Laracon EU 2015
Decoupling with Design Patterns and Symfony2 DIC
Min-Maxing Software Costs
Design how your objects talk through mocking

What's hot (20)

PDF
購物車程式架構簡介
PPTX
Adding Dependency Injection to Legacy Applications
PPTX
Crafting beautiful software
PDF
Virtual Madness @ Etsy
PPTX
Hacking Your Way To Better Security - Dutch PHP Conference 2016
PPTX
Presentation1
ODP
Rich domain model with symfony 2.5 and doctrine 2.5
KEY
Symfony2 Building on Alpha / Beta technology
PDF
Php unit the-mostunknownparts
ODP
Symfony2, creare bundle e valore per il cliente
PDF
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
PDF
Your code sucks, let's fix it - DPC UnCon
PDF
Mocking Demystified
PDF
Unittests für Dummies
KEY
Unit testing with zend framework PHPBenelux
PDF
Unit testing with zend framework tek11
PDF
international PHP2011_Bastian Feder_jQuery's Secrets
PDF
PHPUnit でよりよくテストを書くために
PDF
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
KEY
Solid principles
購物車程式架構簡介
Adding Dependency Injection to Legacy Applications
Crafting beautiful software
Virtual Madness @ Etsy
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Presentation1
Rich domain model with symfony 2.5 and doctrine 2.5
Symfony2 Building on Alpha / Beta technology
Php unit the-mostunknownparts
Symfony2, creare bundle e valore per il cliente
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
Your code sucks, let's fix it - DPC UnCon
Mocking Demystified
Unittests für Dummies
Unit testing with zend framework PHPBenelux
Unit testing with zend framework tek11
international PHP2011_Bastian Feder_jQuery's Secrets
PHPUnit でよりよくテストを書くために
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
Solid principles
Ad

Viewers also liked (7)

PDF
Troubleshooting RabbitMQ and Microservices That Use It
PDF
Queues queues queues — How RabbitMQ enables reactive architectures
PDF
Reactive streams
PPTX
Reactive Streams and RabbitMQ
PDF
RabbitMQ Operations
PDF
Resilient Applications with Akka Persistence - Scaladays 2014
PDF
Akka in Practice: Designing Actor-based Applications
Troubleshooting RabbitMQ and Microservices That Use It
Queues queues queues — How RabbitMQ enables reactive architectures
Reactive streams
Reactive Streams and RabbitMQ
RabbitMQ Operations
Resilient Applications with Akka Persistence - Scaladays 2014
Akka in Practice: Designing Actor-based Applications
Ad

Similar to Taming Command Bus (20)

PPTX
PDF
Command Bus To Awesome Town
PDF
Things I Believe Now That I'm Old
PDF
How Kris Writes Symfony Apps
PDF
Database Design Patterns
PPTX
Basics of Working with PHP and MySQL.pptx
PDF
Models and Service Layers, Hemoglobin and Hobgoblins
PDF
The History of PHPersistence
PPTX
Tidy Up Your Code
PDF
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PDF
jQuery: out with the old, in with the new
PDF
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
PDF
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
PDF
50 Laravel Tricks in 50 Minutes
PDF
laravel tricks in 50minutes
PDF
You code sucks, let's fix it
PDF
Refactoring using Codeception
PDF
Design Patterns avec PHP 5.3, Symfony et Pimple
PDF
Dependency Injection
TXT
Daily notes
Command Bus To Awesome Town
Things I Believe Now That I'm Old
How Kris Writes Symfony Apps
Database Design Patterns
Basics of Working with PHP and MySQL.pptx
Models and Service Layers, Hemoglobin and Hobgoblins
The History of PHPersistence
Tidy Up Your Code
PHPCon 2016: PHP7 by Witek Adamus / XSolve
jQuery: out with the old, in with the new
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
50 Laravel Tricks in 50 Minutes
laravel tricks in 50minutes
You code sucks, let's fix it
Refactoring using Codeception
Design Patterns avec PHP 5.3, Symfony et Pimple
Dependency Injection
Daily notes

Recently uploaded (20)

PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPT
Teaching material agriculture food technology
PDF
Spectral efficient network and resource selection model in 5G networks
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Electronic commerce courselecture one. Pdf
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Spectroscopy.pptx food analysis technology
MIND Revenue Release Quarter 2 2025 Press Release
Network Security Unit 5.pdf for BCA BBA.
Building Integrated photovoltaic BIPV_UPV.pdf
Teaching material agriculture food technology
Spectral efficient network and resource selection model in 5G networks
The AUB Centre for AI in Media Proposal.docx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Encapsulation_ Review paper, used for researhc scholars
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Empathic Computing: Creating Shared Understanding
Dropbox Q2 2025 Financial Results & Investor Presentation
Chapter 3 Spatial Domain Image Processing.pdf
Diabetes mellitus diagnosis method based random forest with bat algorithm
“AI and Expert System Decision Support & Business Intelligence Systems”
Electronic commerce courselecture one. Pdf
Understanding_Digital_Forensics_Presentation.pptx
Approach and Philosophy of On baking technology
Mobile App Security Testing_ A Comprehensive Guide.pdf
Spectroscopy.pptx food analysis technology

Taming Command Bus