My job is almost like that of an SRE ▪ e.g. web application, library, infra, CI etc ... ◦ Ansible >>>> Terraform >>> Ruby ▪ BTW. I’m an Itamae maintainer 17 What I've been doing at pixiv Inc.
architecture and best practice • Architecture and best practices in regular gem development ◦ Architecture techniques in API clients also help the other gem development 20 The Goal/Objective of this talk
• non-text-based APIs ◦ APIs of which both requests and responses aren't in text format ◦ e.g. Protocol Buffers • non web APIs 23 Topics NOT covered today
Official client ▪ Users don't have to worry which client to use ▪ Often kept secure. (since it's maintained officially) ▪ e.g. octokit(GitHub), newrelic-rpm(NewRelic), raven(Sentry.io) 26 1. Public APIs made by ourselves
◦ There aren't API clients in OSS, so we have to make it ourselves • BTW. In Japan, the most commonly used API documentation tool is Excel (xls, xlsx) ◦ Naturally there is no swagger 32 4. Private APIs made by others
◦ I have actually seen this many times • Case 2: external gem ◦ e.g. in-house gem ◦ Even if for only 1 app, we should gemify 33 Where to place API client in our app?
responsibilities should be focused on making the target API (e.g Twitter, Facebook etc.) easy to use in the target language (e.g Ruby) • If extra functions are included, it is difficult to follow API specification changes 38 Responsibilities of API clients
with `Date`, and want to handle timestamp with `Time` • However, in the HTTP world it is necessary to convert it to `String` ◦ Format depends on API ◦ e.g. YYYY-MM-DD, YYYY/MM/DD • snake_case -> camelCase 41 1. Convert param from Ruby to HTTP
a fixed time • Requires dependency and config for memcached ◦ If we support cache backend other than memcached, it requires provider-style config • Requires complicated implementation for generalization ◦ Maintenance becomes difficult • This violates the SRP 49 1. API Response caching
not • Acceptable only when validating ◦ required params (use required keyword args) ◦ non-blank params ◦ using official schema 50 2. Request params validation
can do anything ◦ https://github.com/lostisland/faraday • Suitable when supporting all CRUD requests • Faraday's request and response is pluggable: easy to handle special cases 72 2. Faraday is a silver bullet
if you use keyword args ◦ an Array of Hash is difficult to express in comment 85 5. Introduce parameter object # @param request [Array<Hash>] an Array of Hash # (key is name, message, content_type, ....) def create_content (request) # Send a request to API with XML end
# @return [String] the name of the content attr_accessor :name # and many more args def initialize(name:, message: content_type: "article", ...) end def to_param { name: name, message: message, contentType: content_type, ... } end end
about unclear things or bugs • Writing sample code in ruby is not appropriate ◦ Reason 1. API providers don't necessarily know Ruby ◦ Reason 2. This may be bugs or specification of Ruby. (instead of API) 93 7. curl is universal language
can express all contexts with oneliner 94 Why should we use curl ? $ curl -X GET “https://example.com/api/user” -H “X-ACCESS-TOKEN: $ACCESS_TOKEN” -H “X-ACCESS-SECRET: $ACCESS_SECRET”
◦ I always use this 95 Why should we use curl ? $ curl -X GET “https://example.com/api/user” -H “X-ACCESS-TOKEN: $ACCESS_TOKEN” -H “X-ACCESS-SECRET: $ACCESS_SECRET” | jq . { “name”: “sue445” }
CURL compatible commands so you can share the calls you're making with someone else or keep them for debugging purposes. 97 Auto debug logging in curl format
• Responsibilities of API clients are SRP • Tips in my API clients • API Client 7 Good Patterns • Read “Refactoring: Ruby Edition” • Happy coding 100 Conclusion