Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rethinking the API development

26 views

Published on

Rethinking the API development zgphp talk

Published in: Software
  • Be the first to comment

  • Be the first to like this

Rethinking the API development

  1. 1. Rethinking the API development Zoran Antolović @ ZgPHP #102
  2. 2. API ● a set of functions and procedures allowing the creation of applications that access the features or data of an operating system, application, or other service.
  3. 3. API ● In this talk, when I say API, I mean server-side application ○ Backend, web service, ...
  4. 4. System architecture
  5. 5. System architecture ● Fat server / Thin client ● Full blown server application with exposed integration points ● Simple, data presentation client app Server appClient DB
  6. 6. System architecture ● Fat client / Thin server ● Simple server application operating as a middleware in front of the DB ● Rich & complex client application Client DB Server app
  7. 7. System architecture ● Fat client / Fat server ● Complex client and complex server apps Client DB Server app
  8. 8. Challenge: Do you even need custom API? ● Apart from job security, what’s the actual purpose of your server app? ● Access control? ● CRUD REST API? ● Authentication & Authorization? Server app Client DB
  9. 9. Challenge: Identity crisis :( ● Access control? ● CRUD REST API? ● Authentication & Authorization?
  10. 10. Challenge: Do you even need custom API? ● Why would you want to write and maintain the code that only translates HTTP queries to SQL queries, and encodes SQL entities to XML/JSON? ● The fact that we need to write pointless boring CRUD code most of the time is main motivation for ○ Low-code development platforms ○ RAD frameworks and libraries (e.g. Sonata, API platform) ○ Desperate attempts to customize Wordpress ○ Maker bundle ○ Magic behind annotations and conventions
  11. 11. Challenge: Do you even need custom API? ● Why would you want to write and maintain the code that only translates client queries and commands, packed in HTTP requests, to SQL queries, and encodes SQL entities to XML/JSON?
  12. 12. Challenge: Do you even need custom API?
  13. 13. ● Lot of integrations ● Background processing ● Complex operations ● Process or workflow based ● Not a data access proxy ● Work with models (i.e. entities) Custom server-side application - When?
  14. 14. REST API ● RESTful Web services allow the requesting systems to access and manipulate textual representations of Web resources by using a uniform and predefined set of stateless operations.
  15. 15. GraphQL ● Query language for APIs and a runtime for fulfilling those queries with your existing data. ● GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
  16. 16. Practical tips
  17. 17. Avoid “magic”. Own the API. aka it never works out-of-the-box
  18. 18. Decouple your mindset from the UI aka think in objects and interactions
  19. 19. Decouple your mindset from the UI ● Paper vs online surveys ● Don’t discuss presentation details while designing the API ○ “I need this because I need to present the date like this” ● Don’t build string values for presentation on the API ○ e.g. prices, dates, distances, … ● Use standards ○ ISO 8601 for date and time - be aware of PHP issues!
  20. 20. Clean up your architecture aka MVC is not pattern for stateless web apps.
  21. 21. Clean up your directory structure aka framework is just a tool.
  22. 22. Directory structure ● src/ ○ Entity ○ Controller ○ Service ○ ...
  23. 23. Directory structure ● Domain ● Application ● Infrastructure https://www.thinktocode.com/2018/08/16/onion-architecture/
  24. 24. Directory structure: Domain ● Entities ● Exceptions ● Value objects ● Domain repositories (interfaces) ● Domain services (interfaces or implementations) ● ...
  25. 25. Directory structure: Application ● UseCase services / Command Handlers ● Commands ● Queries / Application repositories (interfaces)
  26. 26. Infrastructure ● Integration (Adapters?) ○ Persistence ○ Bss ○ … ● UI (Ports?)
  27. 27. Infrastructure/UI ● HTTP ○ Web ■ Views / Resources ■ Controller ○ API ■ v1 ■ v2 ● Model ● Action / Controller / Endpoint ● CLI ○ Console commands
  28. 28. Infrastructure/UI/HTTP/API ● HTTP-specific integration or interaction point for your server-side application ● Everything related to ○ REST ○ JSON / XML (encoders, serializers, …) ○ HTTP specifics
  29. 29. Simplify the flow aka one happy path, many exceptions
  30. 30. Simplify the flow ● Start throwing exceptions like you’re Java ● Always keep only one happy path and treat everything else as an exception ● Design and use custom, semantically named exceptions Happy path Exceptions
  31. 31. Simplify the flow ● Don’t allow your objects to be instantiated in an invalid state ● Avoid setters ● Tell, don’t ask principle ● Slim classes & methods ( < 100 LOC) ● Command vs Queries Happy path Exceptions
  32. 32. Use data transfer objects (DTO) aka if you use associative arrays, you’re not my friend.
  33. 33. Use data transfer objects (DTO) ● Data structures ● Simple, “immutable” classes and objects ● https://gist.github.com/zoka123/67d57de528899e7c0169df96226b9e5b
  34. 34. Use API models aka don’t serialize domain entities to JSON
  35. 35. Use API models ● Your REST API returns resources, not JSON ● API model is an object representing the resource ● API model can be encoded to JSON ● API model can be instantiated from valid JSON
  36. 36. Use API models ● API model is not array ● API model is not annotated entity encoded to JSON on the fly
  37. 37. Use API models ● How do you create your API responses? ○ XYZ Bundle? ○ Serializer? ○ return new JsonResponse(...)?
  38. 38. Use API models https://symfony.com/doc/current/components/serializer.html
  39. 39. Use API models ● Don’t use serialization groups on your entities ● Design API model objects (these are DTOs too!) ● Apply all DTO rules from slides before ● https://gist.github.com/zoka123/27e27cb2762ccddb8786f8c4a52ac076
  40. 40. Use API models https://symfony.com/doc/current/components/serializer.html API model, not Entity.
  41. 41. Use API models ● Use constructor-based denormalization ○ https://symfony.com/doc/current/components/serializer.html
  42. 42. Use static analyzers aka how to make PHP suck less
  43. 43. Use static analyzers ● Phpstan ● Phpstan extensions ● Phpstan baseline ● Psalm ● PHP CS fixer
  44. 44. Some useful libraries aka how to make PHP suck less less
  45. 45. Some useful libraries ● https://github.com/beberlei/assert ○ Phpstan extension is available!
  46. 46. Some useful libraries ● https://github.com/CaptainHookPhp/captainhook ● PHP CS fixer
  47. 47. Some useful libraries ● https://github.com/sensiolabs-de/deptrac ● Enforce the architecture rules ● Separate API branches
  48. 48. Version the API from the beginning aka predict the unpredictable
  49. 49. Version the API from the beginning ● Also, think about adding the “force update” flag for mobile apps
  50. 50. Split the APIs aka don’t let strangers play with your private parts
  51. 51. Split the APIs ● Use case: Custom CMS ○ There should be one private API for CMS client app ○ There should be separate public API for the website client ● Resources may have the same name, but they are not the same! ● /posts ○ Private API returns all posts in the system ○ Public API returns only published posts
  52. 52. Functional tests aka requests have to go over the wire
  53. 53. Integrate early aka integration in last seconds before the deadline is painful
  54. 54. Integrate early ● Start using Docker ● Fake it until you make it ○ Build Docker image with mocked API ● Add unit and integration tests to your build stage ○ So you can’t build an app with failing tests ● Run functional tests against the running app, not the code or simulated requests
  55. 55. Integrate early ● The old way: ○ Design the API on your own, in your head ○ Briefly discuss resources ○ Document the API... on Slack ○ Work separately from the client-side developers ○ Be late with the API ○ Deliver the API ○ Fight with client-side devs because you’re not on the same page ○ Fix the mismatches ○ … ○ Profit?
  56. 56. Integrate early ● The OK way: ○ Design the API with all involved parties ○ Specify the API, e.g. with OpenAPI - the contract ○ Run some mock server on top of the specification ○ Work separately from the client-side developers and satisfy the contract ○ Be late with the API ○ Replace the mock API with your implementation ○ Fight with client-side devs because you’re not on the same page ○ Figure out who’s wrong (compare with contract) ○ Fix the mismatches / celebrate while client-side devs are fixing the mismatches ○ … ○ Profit?
  57. 57. Integrate early ● The it-should-be-the-best way ○ Design the API with all involved parties ○ Specify the API, e.g. with OpenAPI - the contract ○ Build the mock server - return mock responses from the controller ○ Work separately from the client-side developers and satisfy the contract ○ Continuously replace mock endpoints with implemented ones (strangler?) ○ Be late with the product delivery ○ … ○ Profit?
  58. 58. Re-think your CI pipeline aka ship executables, not code
  59. 59. Re-think your CI pipeline https://hackernoon.com/understanding-the-basic-concepts-of-cicd-73t3zec
  60. 60. Re-think your CI pipeline ● Start using Docker ● Start using Multi-stage builds ● Add unit and integration tests to your build stage ○ So you can’t build an app with failing tests ● Run functional tests against the running app as part of the CI ● Don’t rely on just code tests or simulated requests
  61. 61. Re-think your logging system aka help your future self
  62. 62. Re-think your logging system ● Fingers crossed log handler ○ How does it work with Sentry? ● Centralize logs ○ Logstash + ElasticSearch + Kibana is OK ○ Ditch the prod.log file
  63. 63. Re-think your logging system ● Start using unique request IDs ○ And attach it to the context of every log ○ https://symfony.com/doc/current/logging.html#adding-extra-data-to-each-log-e-g-a-unique-req uest-token
  64. 64. Re-think your logging system
  65. 65. Get familiar with cURL aka curling is my favorite sport
  66. 66. Get familiar with cURL ● Use cURL examples in your everyday communication with fellow developers ● UI REST API clients are also nice, but executable commands are better ● jq works well with cURL ○ https://stedolan.github.io/jq/tutorial/ ○ https://jqplay.org/
  67. 67. Measure everything! aka numbers are your friends
  68. 68. Measure everything! ● Saas solutions are a good start ○ NewRelic, DataDog ● Custom metrics and dashboards are better ○ Time series databases + Grafana ○ Prometheus ecosystem ○ ElasticSearch and Kibana ● Set up alerts
  69. 69. Follow the standard aka avoid bikeshedding
  70. 70. Bikeshedding ● https://en.wiktionary.org/wiki/bikeshedding ● The term was coined as a metaphor to illuminate Parkinson’s Law of Triviality. ● Parkinson observed that a committee whose job is to approve plans for a nuclear power plant may spend the majority of its time on relatively unimportant but easy-to-grasp issues, such as what materials to use for the staff bikeshed, while neglecting the design of the power plant itself, which is far more important but also far more difficult to criticize constructively. ● It was popularized in the Berkeley Software Distribution community by Poul-Henning Kamp and has spread from there to the software industry at large.
  71. 71. Standardization ● If you’ve ever argued with your team about the way your JSON responses should be formatted, JSON:API can be your anti-bikeshedding tool. ● pagination, filters, response structure, HTTP status code semantics, and much more
  72. 72. Standardization ● But, but, but, …. GRAPH QLLLLL ○ JSON:API and GraphQL are compatible
  73. 73. ● GraPhQL hAs TyPes ○ AKA I don’t know anything about design-first approach ○ AKA what is API documentation, is that a boy band? ○ AKA jSoNs aRe So FleXible ○ AKA I use arrays for everything and my friends don’t like me Mandatory GraphQL rant
  74. 74. ● Single request to fetch everything!!1 ○ AKA I don’t know what I’m building so I’m going to start coding the client without even designing the system yay!!! Mandatory GraphQL rant
  75. 75. https://apisyouwonthate.com/blog/lets-stop-building-apis-around-a-network-hack
  76. 76. JSON:API is completely fine! ● Avoid too-many possible inclusions when you don’t need them ● HTTP requests are cheap ● Switch to HTTP2
  77. 77. Thanks
  78. 78. Questions?

×