I’ve a a class that does some operation that could...
# coroutines
t
I’ve a a class that does some operation that could be heavy (transversing a tree) so ideally this should be running in the
Default
dispatcher. What’s the best way to force who uses this do that? Is it actually a bad thing to enforce this? Should it have a param like
val dispatcher: CoroutineDispatcher = Dispatcher.Default
? Am I looking at this problem with the wrong lens? 🤔
s
Just wrap it in
withContext(Dispatchers.Default)
t
But isn’t bad practice to not have it switchable for testing?
d
Depends on what's happening there. If there is a possibility of a
delay
call there, for example, then sure, a test dispatcher would be beneficial (does your operation run any user-supplied code?). Likewise, if your operation doesn't follow structured concurrency and runs in something like
GlobalScope
, it's certainly worth it to make the
CoroutineScope
injectable. If you don't see a reason for anyone to realistically want to launch your code in something other than
Dispatchers.Default
, then there's probably no reason to introduce a parameter.
t
At this moment I don’t see the need to ever use some
delay
and all the operations on the tree are just executed by methods inside the class, so there isn’t any user-supplied code. So I think in this case it’s indeed a good idea to go with the code wrapped in
withContext(Dispatchers.Default)
. Thanks for both inputs! 😄
k
Does the actual traversal of the tree need to use coroutines or is it just thread switching? If it's just thread switching, you might choose to write two functions. An internal synchronous function that does tree traversal which you write tests against, and then a separate suspending function which offloads onto the default dispatcher.
t
What would be the difference to write the tests directly for the one with default dispatcher?
k
There isn't a big one, but you had raised concerns about testing with the injection of dispatchers. This is an alternative way to test without having to think about that
t
Yeah, for some reason I had in my mind that Dispatchers should always be injected but I guess in this case where there’s no delay and it’s just for “performance” then maybe it’s not a big issue as I initially though it was
k
One of the reasons hard coding dispatchers is largely discouraged is because you can't control them under test, and for specific dispatchers like
Main
that causes a group of issues which are really annoying since that dispatcher isn't available for tests. Default is so it's mostly fine.
gratitude thank you 1
m
If, for example, you would hard code Dispatchers.IO, you would be surprised if you later try to run this code on the
wasmJs
target.
👍 1
t
In this case there’s 0 chance of being multiplatform, so it’s safe. But it’s good to know this for my personal multiplatform projects, I didn’t know that 🤔