Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2015 ZendCon - Service Oriented Architecture as a Pattern of Development

2015 ZendCon - Service Oriented Architecture as a Pattern of Development

753abf3aed0f744b24efda893b67ff43?s=128

Mike Willbanks

October 22, 2015
Tweet

Transcript

  1. SERVICE ORIENTED ARCHITECTURE AS A PATTERN OF DEVELOPMENT ZendCon 2015

  2. I AM MIKE WILLBANKS • Father, Husband, Developer • VP

    of Development at Packet Power • Twitter: @mwillbanks
  3. Applications much like onions, have multiple layers.

  4. A STORY

  5. ONCE UPON A TIME We wrote procedural code…

  6. <html> <head><title>Recent Books</title></head> <body> <ul class="books"> <?php $books = $db->select('...');

    foreach ($books as $book) { echo '<li>' . $book['title'] . '</li>'; } ?> </ul> </body> </html>
  7. <?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { $db->insert('book', array( 'title' =>

    $_POST['title'], )); } ?> <html> <head><title>Add Book</title></head> <body> <form method="post"> <input type="text" name="title"> <!-- .... --> </form> </body> </html>
  8. ALL WAS FINE IN THE WORLD Except for what was

    playing out before us…
  9. WE NEED LIBRARY The boss tells you it’s time for

    the library feature… and we need to update books.
  10. <html> <head><title>My Libraries</title></head> <body> <ul class="libraries"> <?php $libraries = $db->select('...');

    foreach ($libraries as $library) { echo '<li><a href="/library/' . $library['id'] . '">' . $library['name'] . '</a></li>'; } ?> </ul> </body> </html>
  11. <?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { $db->insert('library', array( 'name' =>

    $_POST['name'], )); } ?> <html> <head><title>Add Library</title></head> <body> <form method="post"> <input type="text" name="name"> <!-- .... --> </form> </body> </html>
  12. <?php $rs = $db->select('...'); $book = $rs[0]; if ($book &&

    $_SERVER['REQUEST_METHOD'] == 'POST') { $db->update('book', array( 'library_id' => $_POST['library_id'], 'title' => $_POST['title'], ), array( 'book_id' => $book['id'], )); } $libraries = $db->select('...'); ?> <html> <head><title>Update Book</title></head> <body> <form method="post"> <?php displaySelectFromDbResult('library_id', $libraries); ?>
  13. And these things continued…

  14. EVERYTHING IS FALLING APART

  15. BUGS All these little demons came out of the groundwork.

  16. #!/bin/bash grep -lri bookId * | wc -l $ 271

  17. REWRITE! Or I’m done!

  18. MVC Model View Controller Model Controller View

  19. MVC REQUEST LIFECYCLE

  20. CONTROLLERS • Send commands to the model and sends information

    to the view. • It’s where your request and response are handled.
  21. <?php class BookController extends AbstractController { public function addAction() {

    $book = $this->model->insert(array( 'title' => $this->getPost('title') )); return array( 'book' => $book ); } }
  22. MODELS • Handles the state, persistence, data access and more.

    • Might have mappers and entities, it might not.. • It’s a loaded term.
  23. <?php class BookModel extends AbstractModel { public function insert(array $book)

    { $book['id'] = $this->db->insert('book', $book); return $book; } }
  24. <?php class BookModel extends AbstractModel { public function getId(); public

    function setId($id); public function getTitle(); public function setTitle($title); }
  25. <?php class BookModelMapper extends AbstractMapper { public function save(BookModel $book);

    public function find($id); public function fetchAll(); }
  26. VIEWS • Separating display from business logic • Escaping and

    handling what our controller is providing
  27. <?php $this->layout('main'); ?> <ul> <?php foreach ($books as $book): ?>

    <li><?php $this->escape($book->getTitle());?></ li> <?php endforeach; ?> </ul>
  28. THERE IS A BETTER WAY.

  29. SOA Service Oriented Architecture Service Layer Controller View Domain Models

    Data Mappers Data Access Objects Model
  30. BENEFITS OF A SERVICE LAYER • Better Controllers • Better

    Maintainability • Better Parallelism in Development • Better Testing/Fewer Defects • More Reuse
  31. LETS GET BUILDING

  32. BASIC PRINCIPLES

  33. CONTROLLERS Exactly like MVC, but injecting a service layer.

  34. <?php class BookController extends AbstractController { public function addBookAction() {

    $book = $this->bookService->addBook( $this->getPost('isbn'), $this->getPost('title'), $this->getPost('description') ); return $this->redirect('/book/' . $book- >getId()); } }
  35. SERVICES • Your application logic / business functionality • The

    in-between layer • The internal API to your application
  36. – Wikipedia http://en.wikipedia.org/wiki/Service_(systems_architecture) “A set of related software functionalities that

    can be reused for different purposes.”
  37. <?php class BookService extends AbstractService { public function addBook($isbn, $title,

    $description) { $book = new BookEntity(); $book->setIsbn($isbn); $book->setTitle($title); $book->setDescription($description); $this->mapper->addBook($book); return $book; } }
  38. DOMAIN MODELS • Describe a “thing” • Data object •

    Domain logic • Generally getters, setters
  39. <?php class Book extends AbstractEntity { public function getId(); public

    function setId($id); public function getIsbn(); public function setIsbn($isbn); public function getTitle(); public function setTitle($title); public function getDescription(); public function setDescription($description); }
  40. FILTERING AND VALIDATION • Always filter • User data to

    be validated.
  41. <?php class Book extends AbstractEntity { public function getTitle(); public

    function setTitle($title) { $trim = new TrimFilter(); $title = $trim->filter($title); $this->title = title; return $this; } }
  42. <?php class Book extends AbstractEntity { pubic function getTitle(); public

    function setTitle($title) { $trim = new TrimFilter(); $title = $trim->filter($title); $validate = new AlnumValidator(); if (!$validate->isValid($title)) { throw new InvalidArgumentException($validate->getMessage()); } $this->title = title; return $this; } }
  43. INPUT FILTER PATTERN Merge filters and validators

  44. <?php class Book extends AbstractEntity { public function getInputFilter() {

    $input = new Input('title'); $input->getFilterChain() ->attachByName('stringtrim') ->attachByName('alphanumeric'); $input->getValidatorChain() ->attachByName('not_empty') ->attachByName('string_length', array('min' => 1, 'max' => 45)); $this->inputFilter->addInput($input); return $this->inputFilter; } }
  45. <?php class Book extends AbstractEntity { public function getTitle(); public

    function setTitle($title) { $inputFilter = $this->getInputFilter()- >getInput('title'); $inputFilter->setValue($title); if ($inputFilter->isValid()) { $this->title = $title; } throw new InvalidArgumentException($inputFilter- >getMessages()); } }
  46. DATA MAPPERS • Separates mapping data to a data store

    as well as your data model. • Data store can be anything or even multiple things.
  47. <?php class BookMapper extends AbstractMapper { public function addBook(BookEntity $book)

    { $this->repository->save($book); return $book; } }
  48. But I have multiple tables for this entity!!!

  49. <?php class Book extends AbstractEntity { public function getId(); public

    function setId($id); public function getIsbn(); public function setIsbn($isbn); public function getTitle(); public function setTitle($title); public function getDescription(); public function setDescription($description); } <?php class Book extends AbstractEntity { public function getId(); public function setId($id); public function getIsbn(); public function setIsbn($isbn); public function getTitle(); public function setTitle($title); public function getDescription(); public function setDescription($description); }
  50. <?php class BookMapper extends AbstractMapper { public function addBook(BookEntity $book)

    { $this->bookRepository->save($book); $this->bookDetails->save($book); } }
  51. DUPLICATION?! Not Exactly

  52. We need to lower our database load, let’s cache.

  53. <?php class BookService extends AbstractService { public function findRecent() {

    if ($this->cache->has('book.recent')) { return $this->cache->get('book.recent'); } $results = $this->repository->findRecent(); $this->cache->set('book.recent', $results); return $results; } }
  54. But that seems messy.

  55. DATA ACCESS OBJECTS • Or repositories in this case. •

    Allow us to target other areas to store data. • Allow for far better decoration • Things are looking up.
  56. <?php class BookRepository extends AbstractRepository { public function save($book) {

    if (!$book->getId()) { return $this->insert('book', $book); } return $this->update('book', $book, array( 'id' => $book->getId() )); } }
  57. <?php interface RepositoryInterface { public function save($entity); public function find($id);

    public function findBy($criteria); public function findOneBy($criteria); public function delete($entity); }
  58. <?php interface BookRepository { public function findRecent(); }

  59. DECORATION

  60. DECORATOR PATTERN • Used to extend the functionality of a

    certain object. • Ultimately wrapping
  61. <?php class BookDbRepository implements BookRepository { public function findRecent() {

    $book = $this->gateway->select(...); return $book; } }
  62. <?php class BookCacheRepository implements BookRepository { public function findRecent() {

    if ($this->cache->has('book.recent')) { return $this->cache->get('book.recent'); } $results = $this->delegateRepository- >findRecent(); $this->cache->set('book.recent', $results); return $results; } }
  63. WHAT ARE WE ACHIEVING • Discoverability • Maintainability • Readability

  64. DEPENDENCY INJECTION Keeping everything alive.

  65. Dependency injection is the concept of simply injecting anything that

    is necessary for that object to operate.
  66. <?php new BookService( new BookMapper( new BookCacheRepository( new BookDbRepository( new

    TableGateway('book') ) ) ) );
  67. DI CONTAINERS • Inject dependencies by use of a container.

  68. return array( 'di' => array( 'BookService' => array( 'arguments' =>

    array( 'BookMapper', ), ), 'BookMapper' => array( 'arguments' => array( 'BookCacheRepository', ), ), 'BookCacheRepository' => array( 'arguments' => array( 'BookDbRepository', ), ), 'BookDbRepository' => array( 'arguments' => array( 'TableGateway', ),
  69. SO WHAT DOES THAT DO? • Creates an instance of

    TableGateway • Creates an instance of BookDbRepository • Then an instance of BookCacheRepository • Then an instance of BookMapper • Finally, an instance of BookService <?php $bookService = $container->get( ‘BookService’ );
  70. CLI? Oh, yes. We can!

  71. <?php require 'bootstrap.php'; $bookService = $container->get('book.service'); $bookService->addBook($argv[0], $argv[1], $argv[2]);

  72. THAT’S SEEMS A LITTLE SLIMY… BUT, there is nothing preventing

    us from using controllers.
  73. <?php if (php_sapi_name() == 'cli') { $router = $container->get('cliRouter'); }

    else { $router = $container->get('router'); } class BookCliController extends AbstractCliController { public function addBookAction(); }
  74. BUT WHAT BELONGS? • Orchestration • Security • Transactions

  75. DOMAIN EVENTS A kitchen full of examples…

  76. <?php class BookService extends AbstractService { public function addBook($isbn, $title,

    $description) { $book = new BookEntity(); $book->setIsbn($isbn); $book->setTitle($title); $book->setDescription($description); $this->mapper->addBook($book); $this->trigger('book.add', array('book' => $book)); return $book; } }
  77. <?php $bookService->attach('book.add', function($e) use ($mq) { $params = $e->getParams(); $book

    = $params['book']; $mq->sendMessage('book.add', array('book' => $book)); });
  78. AUTHENTICATION Where does it belong?

  79. STACKING • Routing / Dispatch • Controllers • Services •

    Data Access Layer
  80. WEB SERVICES In general, practically free in most libraries, frameworks

    and languages.
  81. None
  82. JEFF BEZOS MANDATE • All teams will henceforth expose their

    data and functionality through service interfaces. • Teams must communicate with each other through these interfaces. • There will be no other form of interprocess communication allowed: no direct linking, no direct reads of another team’s data store, no shared-memory model, no back-doors whatsoever. The only communication allowed is via service interface calls over the network. • It doesn’t matter what technology they use. HTTP, Corba, Pubsub, custom protocols — doesn’t matter. • All service interfaces, without exception, must be designed from the ground up to be externalizable. That is to say, the team must plan and design to be able to expose the interface to developers in the outside world. No exceptions. • Anyone who doesn’t do this will be fired. • Thank you; have a nice day!
  83. REST • HTTP with HTTP verbs • Involves collections of

    resources.
  84. <?php $app->get('/api/book', 'ApiBookController.recentAction'); $app->put('/api/book', 'ApiBookController.addAction'); class ApiBookController extends RestfulController {

    public function recentAction() { return $this->bookService->findRecent(); } public function addAction() { return $this->bookService->addBook(...); } }
  85. SOAP • XML Information Set • Operation under any transport

    protocol.
  86. <?php $server = new Zend\Soap\Server(null, array(...)); $server->setClass('BookService'); $server->setObject(new BookService()); $server->handle();

  87. RPC • Request / Response like protocol. • XML /

    JSON
  88. <?php $server = new Zend\Json\Server\Server(); $server->setClass('BookService'); $server->handle(); <?php $server =

    new Zend\XmlRpc\Server(); $server->setClass('BookService'); echo $server->handle();
  89. DISCOVERY Strategies for discoverability

  90. BLUEPRINTS • API Blueprint • Apiary • ioDocs • Swagger

  91. HYPERMEDIA • HAL • JSON-LD • JSON Hyper Schema

  92. RECAP

  93. • http://pixabay.com/en/architecture-iron-steel-building-414035/ • http://pixabay.com/en/home-demolition-destroyed-broken-557297/ • http://pixabay.com/en/disassembly-component-parts-336507/ • http://pixabay.com/en/taps-thread-drill-milling-444473/ • http://pixabay.com/en/light-bulb-transparent-light-body-629661/

    • http://pixabay.com/en/church-trappist-georgia-monastery-233564/ • http://pixabay.com/en/lego-site-build-replica-516557/ • http://pixabay.com/en/water-tap-wall-outside-exterior-243046/ • http://pixabay.com/en/question-mark-note-duplicate-457453/ • http://pixabay.com/en/door-entry-stone-opening-grid-208081/ • http://pixabay.com/en/onion-cut-fresh-tears-vegetable-161611/ • http://pixabay.com/en/petronas-towers-skyscraper-433081/ • http://pixabay.com/en/carbine-rope-hook-backup-climbing-7104/ • http://pixabay.com/en/code-program-source-computer-pc-113611/ • http://pixabay.com/en/kitchen-cabinets-countertop-granite-670247/ • http://pixabay.com/en/injecting-medical-shot-veins-519389/ • http://pixabay.com/en/books-shelf-retro-black-and-white-635341/ • http://pixabay.com/en/crayons-pencils-blurred-circle-311062/ • http://pixabay.com/en/soap-curd-soap-bathing-cleaning-390300/ • http://pixabay.com/en/helicopter-model-model-helicopter-195660/ • http://pixabay.com/en/bricks-roofing-house-building-420725/ • http://pixabay.com/en/parrot-ara-zoo-bird-beautiful-bill-655777/ • http://pixabay.com/en/gorilla-silverback-animal-448731/ • http://pixabay.com/en/crash-demolition-site-home-floors-214744/ • http://pixabay.com/en/beetle-beasts-field-insect-431125/ • http://en.wikipedia.org/wiki/File:MVC-Process.svg • http://pixabay.com/en/prairie-dog-small-cute-rodent-keep-320836/ • http://pixabay.com/en/key-lock-door-security-home-565607/ • http://pixabay.com/en/library-inside-wood-book-books-428034/ • http://pixabay.com/en/book-old-antique-pages-empty-pages-657637/ • http://pixabay.com/en/dirt-mess-messy-grungy-face-576491/ • http://pixabay.com/en/antique-box-collectible-electronic-21935/ • http://pixabay.com/en/processor-cpu-board-circuits-540254/ • http://pixabay.com/en/slug-shell-animals-wildlife-87037/ • http://pixabay.com/en/colour-pencils-color-paint-draw-450623/ • http://pixabay.com/en/mount-st-helens-volcanic-eruption-164848/ • http://pixabay.com/en/baby-tears-small-child-sad-cry-443393/ • http://pixabay.com/en/children-win-success-video-game-593313/ • http://pixabay.com/en/peas-pod-pea-pod-green-fresh-580333/ • http://pixabay.com/en/site-construction-work-support-592458/ • http://pixabay.com/en/chimney-sweeper-chimney-sweep-14035/ • https://pixabay.com/en/frog-relaxed-fig-funny-rest-914523/ Image Credits THANK YOU! http://joind.in/talk/view/15635