Skip to content

Introduce ApiResult function factory#103

Draft
StefMa wants to merge 1 commit into
mainfrom
api-result-ff
Draft

Introduce ApiResult function factory#103
StefMa wants to merge 1 commit into
mainfrom
api-result-ff

Conversation

@StefMa

@StefMa StefMa commented Feb 21, 2025

Copy link
Copy Markdown
Collaborator

Description

We are using the com.ioki.result.Result type in our code.
For convinience reasons, we wrapped it behind our own ApiResult typealias.
This works great so far.
However, especially in tests, it might get consued if a user has to fake a ApiResult.
Instead of constructing a ApiResult like he woudl expect ApiResult(data), he has to know about the Result type.
Further, it needs to know about the SuccessData class we have in place.

// Works, but expose logic of `Result` and `SuccessData`
val a: ApiResult<ApiRideResponse> = Result.Success(SuccessData(createApiRideResponse()))
// Does not compile, because `SuccessData` is abstracted away. But this might be a common error
val b: ApiResult<ApiRideResponse> = Result.Success(createApiRideResponse())

With this, I introduce a factory function that is doing exactly the a case.
But hidden behind a fake constructor:

// Both are the same and work perfectly fine
val a: ApiResult<ApiRideResponse> = Result.Success(SuccessData(createApiRideResponse()))
val b: ApiResult<ApiRideResponse> = ApiResult(createApiRideResponse())

The "problem", however, is that we don't distinct between Success and Failure here.
So a Failure case, still have to be constructed like this:

val c: ApiResult<ApiRideResponse> = Result.Failure(com.ioki.passenger.api.result.Error.Connectivity(Throwable()))

I haven't found a good solution to solve this yet.
One approach could be like this:

private fun <T : Any> ApiResult(value: Any): ApiResult<T> {
    return if (value is com.ioki.passenger.api.result.Error) {
        return Result.Failure(value)
    } else {
        Result.Success(SuccessData(value as T))
    }
}

But this only works if we define the type:

// Works
val a: ApiResult<ApiRideResponse> = ApiResult(createApiRideResponse())
val c: ApiResult<ApiRideResponse> = ApiResult(com.ioki.passenger.api.result.Error.Connectivity(Throwable()))

// Doesn't work // Not enough information to infer <T>
val x = ApiResult(com.ioki.passenger.api.result.Error.Connectivity(Throwable()))
val y = ApiResult(createApiRideResponse())

Maybe someone have an idea to make that work?! 🤔 🤷

Test artifact

Test models updated?

In case you created a new APIObject or extracted one,
make sure to update the test fakes in test/src/commonMain/models as well.

Changes to existing models will probably fail on testing and are noticed by the CI.

Test services updated?

In case you created a new service or extracted one,
make sure to update the test fakes in test/src/commonMain/services as well.

Changes to existing services will probably fail on testing and are noticed by the CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant