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

Mike Willbanks

October 22, 2015
Tweet

More Decks by Mike Willbanks

Other Decks in Technology

Transcript

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

    View full-size slide

  2. I AM MIKE WILLBANKS
    • Father, Husband, Developer
    • VP of Development at
    Packet Power
    • Twitter: @mwillbanks

    View full-size slide

  3. Applications much like onions,
    have multiple layers.

    View full-size slide

  4. ONCE UPON A TIME
    We wrote procedural code…

    View full-size slide


  5. Recent Books


    $books = $db->select('...');
    foreach ($books as $book) {
    echo '' . $book['title'] . '';
    }
    ?>



    View full-size slide

  6. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $db->insert('book', array(
    'title' => $_POST['title'],
    ));
    }
    ?>

    Add Book







    View full-size slide

  7. ALL WAS FINE
    IN THE
    WORLD
    Except for what was playing
    out before us…

    View full-size slide

  8. WE NEED
    LIBRARY
    The boss tells you it’s time for
    the library feature… and we
    need to update books.

    View full-size slide


  9. My Libraries


    $libraries = $db->select('...');
    foreach ($libraries as $library) {
    echo '' .
    $library['name'] . '';
    }
    ?>



    View full-size slide

  10. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $db->insert('library', array(
    'name' => $_POST['name'],
    ));
    }
    ?>

    Add Library







    View full-size slide

  11. $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('...');
    ?>

    Update Book


    $libraries); ?>

    View full-size slide

  12. And these things continued…

    View full-size slide

  13. EVERYTHING IS FALLING APART

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  16. REWRITE!
    Or I’m done!

    View full-size slide

  17. MVC
    Model View Controller
    Model
    Controller
    View

    View full-size slide

  18. MVC REQUEST LIFECYCLE

    View full-size slide

  19. CONTROLLERS
    • Send commands to the model and sends
    information to the view.
    • It’s where your request and response are handled.

    View full-size slide

  20. class BookController extends AbstractController {
    public function addAction() {
    $book = $this->model->insert(array(
    'title' => $this->getPost('title')
    ));
    return array(
    'book' => $book
    );
    }
    }

    View full-size slide

  21. MODELS
    • Handles the state,
    persistence, data access and
    more.
    • Might have mappers and
    entities, it might not..
    • It’s a loaded term.

    View full-size slide

  22. class BookModel extends AbstractModel {
    public function insert(array $book) {
    $book['id'] = $this->db->insert('book',
    $book);
    return $book;
    }
    }

    View full-size slide

  23. class BookModel extends AbstractModel {
    public function getId();
    public function setId($id);
    public function getTitle();
    public function setTitle($title);
    }

    View full-size slide

  24. class BookModelMapper extends AbstractMapper {
    public function save(BookModel $book);
    public function find($id);
    public function fetchAll();
    }

    View full-size slide

  25. VIEWS
    • Separating display from business logic
    • Escaping and handling what our controller is
    providing

    View full-size slide

  26. $this->layout('main');
    ?>


    escape($book->getTitle());?>
    li>


    View full-size slide

  27. THERE IS A
    BETTER WAY.

    View full-size slide

  28. SOA
    Service Oriented Architecture
    Service Layer
    Controller
    View
    Domain Models
    Data Mappers
    Data Access Objects
    Model

    View full-size slide

  29. BENEFITS OF A SERVICE LAYER
    • Better Controllers
    • Better Maintainability
    • Better Parallelism in
    Development
    • Better Testing/Fewer
    Defects
    • More Reuse

    View full-size slide

  30. LETS GET BUILDING

    View full-size slide

  31. BASIC PRINCIPLES

    View full-size slide

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

    View full-size slide

  33. 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());
    }
    }

    View full-size slide

  34. SERVICES
    • Your application logic /
    business functionality
    • The in-between layer
    • The internal API to your
    application

    View full-size slide

  35. – Wikipedia http://en.wikipedia.org/wiki/Service_(systems_architecture)
    “A set of related software functionalities that can be
    reused for different purposes.”

    View full-size slide

  36. 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;
    }
    }

    View full-size slide

  37. DOMAIN
    MODELS
    • Describe a “thing”
    • Data object
    • Domain logic
    • Generally getters, setters

    View full-size slide

  38. 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);
    }

    View full-size slide

  39. FILTERING AND VALIDATION
    • Always filter
    • User data to be validated.

    View full-size slide

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

    View full-size slide

  41. 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;
    }
    }

    View full-size slide

  42. INPUT FILTER
    PATTERN
    Merge filters and validators

    View full-size slide

  43. 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;
    }
    }

    View full-size slide

  44. 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());
    }
    }

    View full-size slide

  45. DATA
    MAPPERS
    • Separates mapping data to
    a data store as well as your
    data model.
    • Data store can be anything
    or even multiple things.

    View full-size slide

  46. class BookMapper extends AbstractMapper {
    public function addBook(BookEntity $book) {
    $this->repository->save($book);
    return $book;
    }
    }

    View full-size slide

  47. But I have multiple tables for this entity!!!

    View full-size slide

  48. 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);
    }
    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);
    }

    View full-size slide

  49. class BookMapper extends AbstractMapper {
    public function addBook(BookEntity $book) {
    $this->bookRepository->save($book);
    $this->bookDetails->save($book);
    }
    }

    View full-size slide

  50. DUPLICATION?!
    Not Exactly

    View full-size slide

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

    View full-size slide

  52. 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;
    }
    }

    View full-size slide

  53. But that seems messy.

    View full-size slide

  54. 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.

    View full-size slide

  55. 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()
    ));
    }
    }

    View full-size slide

  56. interface RepositoryInterface {
    public function save($entity);
    public function find($id);
    public function findBy($criteria);
    public function findOneBy($criteria);
    public function delete($entity);
    }

    View full-size slide

  57. interface BookRepository {
    public function findRecent();
    }

    View full-size slide

  58. DECORATOR PATTERN
    • Used to extend the
    functionality of a certain
    object.
    • Ultimately wrapping

    View full-size slide

  59. class BookDbRepository implements BookRepository {
    public function findRecent() {
    $book = $this->gateway->select(...);
    return $book;
    }
    }

    View full-size slide

  60. 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;
    }
    }

    View full-size slide

  61. WHAT ARE WE ACHIEVING
    • Discoverability
    • Maintainability
    • Readability

    View full-size slide

  62. DEPENDENCY INJECTION
    Keeping everything alive.

    View full-size slide

  63. Dependency injection is the concept of simply
    injecting anything that is necessary for that object to
    operate.

    View full-size slide

  64. new BookService(
    new BookMapper(
    new BookCacheRepository(
    new BookDbRepository(
    new TableGateway('book')
    )
    )
    )
    );

    View full-size slide

  65. DI
    CONTAINERS
    • Inject dependencies by use
    of a container.

    View full-size slide

  66. return array(
    'di' => array(
    'BookService' => array(
    'arguments' => array(
    'BookMapper',
    ),
    ),
    'BookMapper' => array(
    'arguments' => array(
    'BookCacheRepository',
    ),
    ),
    'BookCacheRepository' => array(
    'arguments' => array(
    'BookDbRepository',
    ),
    ),
    'BookDbRepository' => array(
    'arguments' => array(
    'TableGateway',
    ),

    View full-size slide

  67. 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
    $bookService =
    $container->get(
    ‘BookService’
    );

    View full-size slide

  68. CLI?
    Oh, yes. We can!

    View full-size slide

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

    View full-size slide

  70. THAT’S SEEMS A
    LITTLE SLIMY…
    BUT, there is nothing
    preventing us from using
    controllers.

    View full-size slide

  71. if (php_sapi_name() == 'cli') {
    $router = $container->get('cliRouter');
    } else {
    $router = $container->get('router');
    }
    class BookCliController extends
    AbstractCliController {
    public function addBookAction();
    }

    View full-size slide

  72. BUT WHAT
    BELONGS?
    • Orchestration
    • Security
    • Transactions

    View full-size slide

  73. DOMAIN EVENTS
    A kitchen full of examples…

    View full-size slide

  74. 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;
    }
    }

    View full-size slide

  75. $bookService->attach('book.add', function($e) use
    ($mq) {
    $params = $e->getParams();
    $book = $params['book'];
    $mq->sendMessage('book.add', array('book' =>
    $book));
    });

    View full-size slide

  76. AUTHENTICATION
    Where does it belong?

    View full-size slide

  77. STACKING
    • Routing / Dispatch
    • Controllers
    • Services
    • Data Access Layer

    View full-size slide

  78. WEB SERVICES
    In general, practically free in most libraries, frameworks
    and languages.

    View full-size slide

  79. 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!

    View full-size slide

  80. REST
    • HTTP with HTTP verbs
    • Involves collections of
    resources.

    View full-size slide

  81. $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(...);
    }
    }

    View full-size slide

  82. SOAP
    • XML Information Set
    • Operation under any
    transport protocol.

    View full-size slide

  83. $server = new Zend\Soap\Server(null, array(...));
    $server->setClass('BookService');
    $server->setObject(new BookService());
    $server->handle();

    View full-size slide

  84. RPC
    • Request / Response like
    protocol.
    • XML / JSON

    View full-size slide

  85. $server = new Zend\Json\Server\Server();
    $server->setClass('BookService');
    $server->handle();
    $server = new Zend\XmlRpc\Server();
    $server->setClass('BookService');
    echo $server->handle();

    View full-size slide

  86. DISCOVERY
    Strategies for discoverability

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  89. • 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

    View full-size slide