Say I have a repository function that creates a re...
# codereview
d
Say I have a repository function that creates a record in the db, and I'd like to invalidate caches that might need to know about the new record, and also update my search engine's db with the new record. What would be the best way to do SRP in this case: 1. (con: not really applying SRP; pro: really clear that these things are happening for createFoo -- conductive to not accidentally forgetting to do them where needed)
Copy code
class FooRepo(
   val db: ...,
   val cache: ...,
   val searchEngine: ...
) {
  suspend fun createFoo(...) {
     // create in db
     // call corresponding invalideXXX for cache
     // call addFoo(....) in searchEngine
  }
}
2) Use an interface for FooRepo and delegation for all the unimplemented funs in the repo and then use decorators for each operation (con: very unclear what is going on by looking at the call site, might forget to do this when needed... to know whether it was done is going to another class and making sure this class is wrapped) 3) other ideas?
c
I prefer 2) because it makes it easier to test the repository without the external things, however it's really easy to forget to decorate instances with the cache/search layer
d
Yeah, that was a bit of my dilemma, and multiply that tons of times for a big codebase doing such things very often...
I also considered using a lambda to "wrap" the function which such functionality as a sort of marker and then having a no-op for testing using 1)... but that's not so nice, and it would be a mess with dependency injection...
I really need the result of this function and then do some side-effects.
While showing clearly that they're being done from the repo code, (preferrably with easy access to the implementations of these side-effects).
In micronaut there's a similar feature using some kind of InvalidCaches() annotation as AOP.
c
Note that you can use
Copy code
cache { … }
without adding any layers: that's already a no-op!
d
In this case, I need to invalidate certain caches as a result of updating or adding entries... so cache { } isn't relevent here.
The results of the computation are needed to use that id to invalidate the all the cache entries related to that update