Open arinal opened 7 years ago
That's definitely an option - no design is ever complete and there are always alternatives. In fact instead of committing to Future
in the repository you can make it return a Monad
(in the style of tagless final), which can be specialized to Future
for your implementation. The advantage is that testing becomes easier - you can test your repository using the Identity
monad, while continue to use Future
in production implementation.
At one perspective people would say returning generic Monad
will blur the original intention of the function definition, another perspective would say repository doesn't have to return Future
as InMemoryRepository
usually do. Apart from it, I can see elegance in this and want to using it in my projects, do you ever use it in production?
Somehow I still prefer using Future
as it will be more understandable for beginner readers, and using Future.successfull
with fake ExecutionContext
as a replacement for returning Identity
monad. Remember, your reader haven't yet introduced to Identity
monad :)
NB: Those beginner readers remind me of myself several months ago. Thanks to your book!
Using Future
is ok functionally and may suit the beginner as well. I am a huge fan of parametricity and generally prefer to use concrete types at the boundary. Hence the suggestion for Monad
. The problem with concretizing with Future
is that in unit tests u still need all the machinery of Future
that u also have mentioned even to use a Map
as the repository. Anyway, it's better to start simple :-)
The root cause why the operation need to return
Future
is because repository. Rather than eagerly callingFuture.apply
in service level, why can't we introduceFuture
as the return type from repository, and compose it accordingly in service level?Let's say our repository is non-blocking, we will call this already well-shaped repository in another thread, which is unnecessary.