I've got a standalone helper method which does som...
# announcements
b
I've got a standalone helper method which does some work and I want to be able to log information within it in the context of the calling methods, but I find it a bit awkward/annoying to have to pass a logger to it, has anyone come up with a good strategy for things like that? I thought about: 1. Define a
HasLogger
interface (which defines a
logger
property) and make the helper method an extension on that, so that way it could access the logger, but that requires all classes make access to their logger instance public, which seems wrong. 2. Make the helper function an extension function on
Logger
directly. This feels like it would be awkward at the call site, as the function itself has nothing to do with logging but would look like
logger.myHelperFunction(...)
. Even wrapping the call in a
with(logger)
feels a bit weird because it feels like the fact that it logs shoudn't be so explicit. 3. Just suck it up and pass a logger instance. This works but I find it distracting. I have an auto-close-style helper
withResource
and calling
withResource(myResource) { ... }
feels a lot better than
withResource(logger, myResource) { ... }
which seems like it makes it confusing as to which resource is being managed. 4. Have the method use its own logger. This works but our logger instances are part of a hierarchy and include contextual information from the parents, which it would be nice to have when the helper is called in the scope of some class' logger. Has anyone done anything that worked well for a use case like this?
c
Not saying it's the best way, but this is a typical example given in functional programming class where they use this: make your logging functions return a pair of their output and their logs.
fun plusOne(a: Int) = a+1 to "my logs"
And then add a composition function:
Copy code
infix fun <T, R, S> (T) -> Pair<R, String>.then(other: (R) -> Pair<S, String>: (T) -> Pair<S, String> = { t ->
  val (firstResult, firstLog) = this(t)
  val (secondResult, secondLog) = other(firstResult)
  return secondResult to firstLog + "\n" + secondLog
}
And you can just use it like so:
val plusTwo = ::plusOne then ::plusOne