使用功能方式处理日志消息的最佳实践是什么

What is the best practice for Handling Log message with using functional way

我是 Scala 编程新手。我现在对如何以异步和函数式的方式声明一个 biz 方法感到困惑,该方法的实现应该包含许多日志消息。作为一种不好的做法,我这样写代码:

// trait
trait StoreService {
    def create[Config]: Kleisli[Future, Config, Store]
}

// and the interpreter
trait StoreServiceInterpreter extends StoreService {
    def create[Config]: Kleisli[Future, Config, Store] = Kleisli {cfg => 
        // some implementation ...
        log.info("bla bla bla ...")
        // some implementation ...
        // return a store
        Store(...)
    }
}

不好,因为实施有副作用,请在此处记录一些内容。所以,我像这样更改方法声明:

// trait
trait StoreService {
    def create[Config]: Kleisli[Future, Config, Writer[Vector[String], Store]]
}

// and the interpreter
trait StoreServiceInterpreter extends StoreService {
    def create[Config]: Kleisli[Future, Config, Writer[Vector[String], Store]] = Kleisli {cfg => 
        // some implementation ...
        // log.info("bla bla bla ...")
        // some implementation ...
        // return a store
        Writer(Vector("bla bla bla...", Store(...))
    }
}

使用Writer,消除了副作用,但代码不清晰:

为方便起见,我认识的大多数 Scala 开发人员倾向于将日志记录视为 "non-side-effect"。但是,如果你真的想跟踪它们,你可能想看看 "free monad" 概念。更多的信息: general description, example with logging

我的粗略解释是"let's model our program as some AST and interpret it"。因此,在 AST 中,您定义了一个 "logging" 的概念,而不是稍后在解释中出现的实现。这种方法允许您关注日志记录并更改操作(从写入 /dev/null 到异步 post 到外部服务)而不影响代码的 "business" 部分。