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

时间:2017-06-12 07:32:23

标签: scala functional-programming pure-function

我是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,副作用被消除,但代码不清楚:

  • 作家为何回归? Writer[Vector[String], Store]的噪音比Store更多,有没有办法避免样板代码并保持无副作用?
  • log不是临时的!我应该构建一个String向量来保存消息,使用:+++操作来添加日志。我认为它不是临时日志记录,就像在任何地方写log.info(...)一样。

1 个答案:

答案 0 :(得分:1)

为方便起见,我认识的大多数Scala开发人员都倾向于将日志记录视为“非副作用”。但是,如果你真的想跟踪它们,你可能想看看“免费monad”概念。更多的信息: general descriptionexample with logging

我的粗略解释是“让我们将我们的程序建模为一些AST并解释它”。因此,在AST中,您定义了“日志记录”的概念,而不是实现,后来在解释中。这种方法允许您密切关注日志记录并更改操作(从写入/ dev / null到异步发布到外部服务),而不会影响代码的“业务”部分。