A New Naming Scheme for Retrofit Requests

Posted: 16 Apr 2024. Last modified on 27-May-24.

This article will take about 2 minutes to read.


The System

We should divide network requests into a series of different classes/interfaces

Why?

The Service only exists for us to scope network requests correctly for our features

By cleanly separtating network modesl from domain models, we are partitioning the code into a section that we own, and a section that the server owns. Explicitly including a translation between the two solidifies and clarifies the contract that the two are agreeing to share. This also helps to mitigate the issues associated with sharing models across features.

Example of a Service

interface ServiceAuthentication :
  EndpointAuthSignIn
  EndpointAuthRegister
  EndpointAuthRefresh

Notice that a service is comprised of several endpoints. An endpoint can belong to multiple services.

Example of an Endpoint

interface EndpointAuthSignIn {
    @POST("/auth/signin")
    suspend fun signIn(@Body request: Request): retrofit2.Response<Response>

    data class Request(
        @SerializedName("username") val username: String,
        @SerializedName("password") val password: String,
    )

    data Response(
        @SerializedName("token") val token: String,
        @SerializedName("user") val user: User,
    ) {
        data class User(
            @SerializedName("firstName") val name: String,
            @SerializedName("lastName") val name: String,
        )
    }
}

Glossary

Service

A Service is a collection of endpoints. It DOES NOT correlate directly with the microservice implementation on the server.

Endpoint

Each Endpoint defines its own Request and Response

Requests and Responses

Requests and Responses should be automatically generated from actual server responses.

Respository

It’s the responsibility of the Respository class (or repository UseCase) to convert Request and Response types to domain types.