过程或函数的副作用是_依赖注入, Effect System 和函数式程序架构

DI, Wire, Effect System, Architecture of Functional Program

之前用 Go 体验没特别好的一点是很多函数需要传同样的参数, 例如操作数据库的函数都要带上数据库连接, 这明显是 DI 适用的场景, 之后用上了当时刚发布不久的 wire[1], 那个时候还在 go-cloud 的 repo 里主要用来适配不同的 Cloud Provider 提供的操作. 这次用上wire 相比与之前多了 cleanup 函数[2], 然后把 setup 一个 micro[3]service 的过程用 wire 包装了一遍, 中间的 handler 函数也可以变得相对容易测试.

在用 wire 的时候把一个 handler 的依赖都放进 handler 的 struct 里, handler 作为 handler struct的方法, 和 Haskell 里的 ReaderT Design Pattern[4]简直不谋而合, 单纯 ReaderT 缺少 wire 里的生命周期 cleanup 操作, 这个组合 Continuation Monad 就可以实现. 这些和 Erlang OTP 里的 Application[5], Clojure 里的 Component[6]都很类似, 都是带有副作用和生命周期的组件. (btw, 十分喜欢 wire 从 Dagger 2 学来的根据类型在编译时的 DI, 用类型来 encode 元信息比 XML 舒服多了)

ReaderT Design Pattern 的问题是副作用的"接口"都包含在一个大的 struct 里, 一旦函数获得了这个 struct 就可以操作里面所有的副作用, 例如不能操作数据库的函数就不可以获得数据库的连接. 所以需要可以控制"带上副作用的 struct" 哪些部分可以传递到下游的功能. 相对的, 下游的函数可以描述上游应该带有什么副作用, 阅读代码的人就可以很清晰地知道这个函数会 perform 什么副作用. Haskell 里类似的解决方案有很多, 2019 简直 Haskell Effect System 之年, 发布了 1.0 的 fused-effect[7], freer-simple 的后代 Polysemy[8], 正在重写的 Eff[9], 如何去架构一个 Haskell 程序的方式似乎永远不会存在一个定论, 之前就吐槽过 "Java 圈真的可以拿一车 DI 框架鄙视 Haskell 那一车 effect 解决方案", 但是至少比 "Hexagonal/Onion/Clean architecture", "Functional Core, Imperative Shell", "DDD" 之类的纲领性文字容易接受多了: "编译器: 你这样写不过 type check" v.s. "PPT 架构师: 你这么写不符合我设计的架构".

sidenote 的 sidenote

作为接口来讲 Go 的 interface (structural) 比 Haskell 的 Typeclass 确实是个更加 scale 的设计, 例如用 typeclass 做序列化 (FromJSON/ToJSON), 太容易出现 Orphan instance[10] 的情况了, interface 对于 typeclass 来说少了 coordinate 的成本.

参考

  1. ^google/wire https://github.com/google/wire
  2. ^Cleanup functions https://github.com/google/wire/blob/master/docs/guide.md#cleanup-functions
  3. ^go-micro https://github.com/micro/go-micro
  4. ^The ReaderT Design Pattern. https://www.fpcomplete.com/blog/2017/06/readert-design-pattern
  5. ^Application behaviour https://hexdocs.pm/elixir/Application.html
  6. ^stuartsierra/component https://github.com/stuartsierra/component
  7. ^fused-effects https://www.zhihu.com/question/47092173/answer/831900164
  8. ^polysemy https://github.com/polysemy-research/polysemy
  9. ^Eff https://github.com/hasura/eff
  10. ^Orphan instance https://wiki.haskell.org/Orphan_instance
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值