API Engineering
Principles
- APIs should be easy to understand that there shouldn’t be a need for UI onboarding
- To follow a specific process/format to make the API understanding easier
- To set a standard for everyone to be in sync in API understanding
- Letting know the whole front-end team to be aware of new APIs or API changes without having to draft these (slack) messages and tumble on the message format every time
- Avoid follow-ups in knowing if an API or API change is upon staging/prod
- Keeping the frontend and backend together to lessen the chances of such miscommunications, facilitating smooth application development
- Achieve complete coherence of the teams working on the project
Have a Changelog project
Goal: Letting know developers of any new features, improvements, and changes that have been made to an API
What is Changelog?
- Managing public APIs where front-end developers or third party developers who need to be kept in the loop of new features or changes on the platform
- Store a list of updates to platforms for power users who are interested in feature updates
Steps on how to use Changelog:
- Create a project aligning it to a company
- Navigate to the projects section
- Create a log on entering 🎯 Regarding an API, API developers need to give (UI devs) full context in the description, on what to do with the API. This includes providing screenshots pointing to each field and describing what it needs to be used for (if not clear from the documentation). Below are two reference logs as such:
Title
- Title of the logCategory
- Category could be a New feature, Improvement, Bug, Breaking change, FixDescription
- Description of the log- Log 1
- Log 2
- Subscribe to a project you would wish to receive updates in Below is an image of a log with log title, type of update (category), and description of the log
Documentation
Documentation is a first‐class feature of GraphQL type systems. To ensure the documentation of a GraphQL service remains consistent with its capabilities, descriptions of GraphQL definitions are provided alongside their definitions and made available via introspection.
Description for field
Descriptions can be added with the field(...)
method as a positional argument, a keyword argument, or inside the block.
- 3rd positional argument
description:
keyword- Inside the block
field :name, String, "name of this thing", null: false
field :name, String, null: false, description: "name of this thing"
field :name, String, null: false do description "name of this thing"end
Description for argument
- Write description for argument
- Define arguments that are required vs optional
argument :first_name, String, "Description goes here - First name of the user", required: true
Required arguments
argument :category, String, required:true
Optional arguments
argument :category, String, required:false
Note: If all arguments are optional it leads to ArgumentError, to prevent this, you must either specify default_value for all keyword arguments or use the **args double splat operator argument in the method definition
- In your application, enums extend GraphQL::Schema::Enum and define values with the
value(...)
Method:
# app/graphql/types/base_enum
class Types::BaseEnum < GraphQL::Schema::Enum
end
# app/graphql/types/media_category.rb
class Types::MediaCategory < Types::BaseEnum
value “AUDIO”, “An audio file, such as music or spoken word”
value “IMAGE”, “A still image, such as a photo or graphic”
value “TEXT”, “Written words” value “VIDEO”, “Motion picture, may have audio”
end
Each value may have:
- A description (as the second argument or
description:
keyword) - A deprecation reason (as
deprecation_reason:
), marking this value as deprecated - A corresponding Ruby value (as
value:
), see below: - Defining GraphQL enums dynamically from Rails enums
By default, Ruby strings correspond to GraphQL enum values. But, you can provide value:
options to specify a different mapping. For example, if you use symbols instead of strings, you can say:
value "AUDIO", value: :audio
Then, GraphQL inputs of AUDIO
will be converted to :audio
and Ruby values of :audio
will be converted to "AUDIO"
in GraphQL responses.
module Types
class IssuableSeverityEnum < BaseEnum
graphql_name 'IssuableSeverity'
description 'Incident severity'
::IssuableSeverity.severities.keys.each do |severity|
value severity.upcase, value: severity, description: "#{severity.titleize} severity."
end
end
end
Description for Type
Write descriptions for Types
class ExampleType < Types::BaseObject
description "description goes here"
end
Description for Query
Write description for Query
class ExampleQuery < Queries::BaseQuery
description "description goes here"
end
Descriptions for Mutations
Write descriptions for Mutations
class ExampleMutation < Mutations::BaseMutation
description "description goes here"
end
Handle deprecation
Fields deprecation
- Deprecated fields can be marked by adding a
deprecation_reason:
keyword argument - Have the deprecated field logged on Changelog
field :name, String, null: true,
deprecation_reason: "We split up the name into two; firstname and lastname"
Include the applicable Deprecated field, Reason, Date of deprecation, and Date of removal in the description of the log.
Arguments deprecation
- Deprecated arguments can be marked by adding a
deprecation_reason:
keyword argument: - Use
as: :alternate_name
to use a different key from within your resolvers while exposing another key to clients. - Have the deprecated argument logged on Changelog
argument :name, String, required: false, deprecation_reason: "Use `first_name` instead."
argument :first_name, String, required: false
⚠️ Note: argument deprecation is a stage 2 GraphQL proposal so not all clients will leverage this information.
field :post, PostType, null: false do
argument :post_id, ID, required: true, as: :id
end
def post(id:)
Post.find(id)
end