使用功能方式处理日志消息的最佳实践是什么
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,消除了副作用,但代码不清晰:
- 作家为何归来?
Writer[Vector[String], Store]
比 Store
有更多噪音,有什么办法可以避免样板代码并保持无副作用?
- 写
log
不是临时的!我应该构建一个字符串向量来保存消息,使用 :+
或 ++
操作来添加日志。我认为这不是临时日志记录,就像在任何地方写 log.info(...)
一样。
为方便起见,我认识的大多数 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" 部分。
我是 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
不是临时的!我应该构建一个字符串向量来保存消息,使用:+
或++
操作来添加日志。我认为这不是临时日志记录,就像在任何地方写log.info(...)
一样。
为方便起见,我认识的大多数 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" 部分。