Context
Let's say I have a navigation service that allows me to navigate to a page.
The Navigate
method is async
because an animation (about 250ms) is involved.
public interface INavigator
{
Task<IViewModel> Navigate(Type viewModelType);
}
Problematic use-case: Concurrent calls
Now imagine that have a bottom navigation bar with multiple buttons, each allowing navigation to a specific page. It's very easy tap 2 or more buttons quickly enough to trigger multiple calls to the Navigate
method.
I would like my service to discard concurrent calls, allowing only the first one to execute.
Current solution
My current solution is implemented by tracking the state of the navigator. (i.e. Is it already processing a navigation?) When a concurrent call is detected, the method simply logs a warning and returns null
. This works fine.
Let's call that Solution 1 for future discussions.
Question
In the context of a class not supporting concurrent calls, what's the best error design?
- Return a default value? (current implementation, where I also log a warning)
- Throw an exception? (similarly to what database could do)
- Have the method return a boolean using a try-out pattern?
- Have the method return a boolean using a wrapper object?
My thoughts so far
- All solutions involve some handling from the calling code (catch an exception, null check, or bool check).
- Solution 1 can hide failures when the return value isn't used. You don't see that anything went wrong unless you look at logs.
- Solution 2 can seem loud as exceptions involve stopping the execution and capturing the stack trace. Can this cause performance issues? Should I even bother about that?
- Solutions 3 and 4 make the method signature heavier.
- It seems that part of the problem is figuring out whether this use-case is an edge-case.
- I'm asking the question because solution 2 might seem like a better approach because it would be clearer (more explicit).
Navigate
method but you don't actually navigate, you might wonder why. Having explicit feedback that"the navigation request was discarded because another one is processing"
seems like a reasonable behavior. Perhaps the log level should be lower than warning though because, like you said, there isn't much to do about it.