Software Design/Log successful function execution inside the function itself
Logging successful function execution inside the function itself means the code like this:
fun computeFoo(): Foo {
//...function's logic
log("computeFoo() result: $resultFoo")
return resultFoo
}
Rather than like this:
fun computeFoo(): Foo {
//...function's logic
return resultFoo
}
//...client code
val foo = computeFoo()
log("computeFoo result: $foo")
Checklist questions:
- A function call is not followed by logging a successful execution?
Why
[edit | edit source]DRY: if the function is called in multiple places, logging shouldn't be repeated in all of them.
Keeping client code free of logging of successful execution of called functions makes it clearer. This could also be seen as an instance of separation of concerns between the client code and the function, although exactly the opposite view is also possible: logging inside the function makes it responsible for two things (the logic and the logging) instead of just one.
If there are also some logging statements in the beginning and in the middle of the function's body, the logging statement about successful execution should be kept congruent with the logging above if there is an objective to avoid logging duplicated information and thus reduce the noisiness of the logs, or to increase the performance, e. g. if serializing function's arguments into string form for the purposes of logging takes significant CPU resources. When all logging is confined to the function's body, keeping it deduplicated is less error-prone and requires less navigation than when the logging statements are spread between the function's body and the function's call sites.
Logging inside the function may output some private information, such as values in some private fields in the class containing the function, or some intermediate computation results which are not returned from the function.
Why not
[edit | edit source]If the function is pure, or if the class to which the function belongs isn't concerned with logging, passing a logger
object into the function or injecting logging in the class makes the code bigger and less clear.
If at different call sites different logging verbosity level is desired for the function, it needs an additional parameter to control this, which also makes the code bigger and less clear.