Group Group Group Group Group Group Group Group Group

REDUX - API requests that require a RemoteSession

What is the best way to have access to the users RemoteSession when making an API request in the Redux architecture example? In the example, the UserSession lives on the store, and most of the API requests are triggered from a UserInteraction class. Would you DI an observable of the RemoteSession into the UserInteraction class at time of creation, and then DI that into the remoteAPI when you make the request?

I saw a post where you mentioned RemoteAPI could hold onto a reference of the RemoteUserSession. What happens if some requests require authentication, but some don’t? How does that RemoteUserSession get updated?

Hi @kaptain_k1rk, a great way is to inject the RemoteSession into the RemoteAPI object directly via initializer injection. For example in the Redux example codebase, KooberCloudNewRideRemoteAPI takes a RemoteUserSession in the initializer and holds on to a reference with the userSession property.

Once the RemoteAPI initializer accepts a RemoteSession, you can inject the session in a factory method within the signed-in user’s dependency container. For instance, this would happen in KooberSignedInDependencyContainer on line 49. Instead of initializing a fake RemoteAPI you could initialize a real one with the RemoteSession. This way, the Repository classes would not need to know about RemoteSession, just that they need something that conforms to one of the RemoteAPI protocols. Same with the UserInteraction classes, they wouldn’t need to know about RemoteSession, just something that conforms to the specific Repository protocol needed. This keeps everything nicely decoupled so that when you need to refactor the RemoteAPI it doesn’t affect all the upstream classes.

If some requests require authentication and others do not, I would separate these requests into separate RemoteAPI protocols. Then I’d create an AnonymousUser dependency container and have the non-authenticated RemoteAPIs created and stored in the AnonymousUser dependency container. The RemoteAPIs that require authentication would be created and stored in the SignedIn dependency container, which contains the user’s session.

One of the goals with dependency containers and dependency container scopes is to avoid mutable objects. Using different containers for different scopes allows you to avoid needing to store a mutable user session that you would change depending on the request being made. This approach allows you to write more deterministic code that is easier to reason about.

Hope this helps. Please let me know if I can expand or explain anything else. Cheers.

That does thank you! Injecting the factory allows me to determine how the remote session is created, and it doesn’t have to be strictly tied to a reference.

I do have a question about having separate dependency containers with regards to anonymous user / signed in user.

What if the user can access the same parts of the app whether they are signed in or not? Would it make sense to still have two separate dependency containers? The containers would share the same functions to create the view controllers needed. How would you model your app state at that point?

For example, in my app I have two states for my Running state: onboarding, and completedOnboarding(in Koober I think its onboarding, and signedIn). The completedOnboarding state has an optional UserSession associated value, along with a CompletedOnboardingState which is the rest of the app state for that scope (very similar to Koober’s SignedInViewControllerState).
Would it make sense to change my Running state to something like this:

enum RunningState {
  case onboarding(OnboardingState)
  case anonymous(CompletedOnboardingState)
  case signedIn(UserSession, CompletedOnboardingState)
}

This would allow me to remove the optionality around a UserSession, but I wasn’t sure if it made sense to model it this way.

hi @kaptain_k1rk, apologies for the delay in response. Yes! Making UserSession non-optional and inside the signedIn case looks great. Removing optionality is one of the goals for the architectures we share in the book.

Usually anonymous state is the same as onboarding so you might want to remove the anonymous case. These state enum’s are meant to represent what single state the user is in. So if the user can be in both anonymous and signedIn state at the same time, I’d remove the anonymous case.

When modeling your dependency containers, it’s a matter of what instances of objects you have and where they should be stored so you could go about it two ways… It comes down to where the anonymous remoteAPI instances should be stored. You could store them in the onboarding dependency container and pass them into the signedIn dependency container when creating the signedIn container. You could also just re-create the remoteAPI instances within the signedIn container. Anonymous RemoteAPIs should in theory be stateless so there shouldn’t be problems with having more than one copy around. Hope this helps! Please feel free to reach out if there’s anything I can expand on.

Cheers!
Rene