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 Slide

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

    View Slide

  3. Applications much like onions,
    have multiple layers.

    View Slide

  4. A STORY

    View Slide

  5. ONCE UPON A TIME
    We wrote procedural code…

    View Slide


  6. Recent Books


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



    View Slide

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

    Add Book







    View Slide

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

    View Slide

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

    View Slide


  10. My Libraries


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



    View Slide

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

    Add Library







    View Slide

  12. $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 Slide

  13. And these things continued…

    View Slide

  14. EVERYTHING IS FALLING APART

    View Slide

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

    View Slide

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

    View Slide

  17. REWRITE!
    Or I’m done!

    View Slide

  18. MVC
    Model View Controller
    Model
    Controller
    View

    View Slide

  19. MVC REQUEST LIFECYCLE

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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


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


    View Slide

  28. THERE IS A
    BETTER WAY.

    View Slide

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

    View Slide

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

    View Slide

  31. LETS GET BUILDING

    View Slide

  32. BASIC PRINCIPLES

    View Slide

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

    View Slide

  34. 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 Slide

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

    View Slide

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

    View Slide

  37. 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 Slide

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

    View Slide

  39. 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 Slide

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

    View Slide

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

    View Slide

  42. 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 Slide

  43. INPUT FILTER
    PATTERN
    Merge filters and validators

    View Slide

  44. 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 Slide

  45. 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 Slide

  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.

    View Slide

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

    View Slide

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

    View Slide

  49. 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 Slide

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

    View Slide

  51. DUPLICATION?!
    Not Exactly

    View Slide

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

    View Slide

  53. 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 Slide

  54. But that seems messy.

    View Slide

  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.

    View Slide

  56. 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 Slide

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

    View Slide

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

    View Slide

  59. DECORATION

    View Slide

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

    View Slide

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

    View Slide

  62. 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 Slide

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

    View Slide

  64. DEPENDENCY INJECTION
    Keeping everything alive.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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',
    ),

    View Slide

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

    View Slide

  70. CLI?
    Oh, yes. We can!

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  75. DOMAIN EVENTS
    A kitchen full of examples…

    View Slide

  76. 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 Slide

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

    View Slide

  78. AUTHENTICATION
    Where does it belong?

    View Slide

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

    View Slide

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

    View Slide

  81. View Slide

  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!

    View Slide

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

    View Slide

  84. $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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  89. DISCOVERY
    Strategies for discoverability

    View Slide

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

    View Slide

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

    View Slide

  92. RECAP

    View Slide

  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

    View Slide