Dependency injection ocaml,函子:依赖项注入

Dependency injection ocaml,函子:依赖项注入,dependency-injection,ocaml,Dependency Injection,Ocaml,其中关于函子: 依赖注入 使系统的某些组件的实现可交换。当您想要模拟零件时,这尤其有用 用于测试和模拟目的的系统 但是我没有领会这个想法。 我也看了维基百科,但实际上我没有抓住与测试和模拟目的的关系。在我看来,他们只是试图展示术语“依赖注入”如何被视为是指完整模块的参数。这就是OCaml函子的含义:带有参数的模块也是模块 这有很多用途,不仅仅是测试和模拟。但是你当然可以用它来做这些。例如,您可以使用它在测试期间提供一个“模拟”模块,以替换系统中难以在测试环境中精确复制的某些部分 一种看待这一点的

其中关于函子:

依赖注入

使系统的某些组件的实现可交换。当您想要模拟零件时,这尤其有用 用于测试和模拟目的的系统

但是我没有领会这个想法。
我也看了维基百科,但实际上我没有抓住与测试和模拟目的的关系。

在我看来,他们只是试图展示术语“依赖注入”如何被视为是指完整模块的参数。这就是OCaml函子的含义:带有参数的模块也是模块

这有很多用途,不仅仅是测试和模拟。但是你当然可以用它来做这些。例如,您可以使用它在测试期间提供一个“模拟”模块,以替换系统中难以在测试环境中精确复制的某些部分

一种看待这一点的方式是,“依赖注入”并不像它的拥护者想让你想的那样有趣或新奇。至少我个人是这么想的。使用模块作为参数并不是一个惊天动地的想法,它在ML语言中已经存在了几十年。至少在Angular中,这与一个单独的概念相混淆,即函数参数的名称在语义上是有意义的。这(IMHO)是一个错误。

是一种软件工程技术,其目的是减少程序的两个子系统之间的相互依赖性。这项技术的一个非常重要的细节是,它涉及的不是两个子系统,而是三个子系统:

  • 服务,
  • 使用
  • 注射器,其职责是为客户准备服务
后一个子系统及其职责是一个经常被忽略但至关重要的细节:这意味着客户机对服务的了解与其公共接口一样少,这意味着可以很容易地使用模拟服务来测试客户机

假设我们编写了一个通过网络与键值存储进行通信的应用程序。键值存储具有以下签名:

module type AbstractKeyValueStoreService =
sig
   exception NetworkError
   type t
   val list : t -> string
   val find : t -> string -> string option
   val set : t -> string -> string -> unit
end
如果我们通过AbstractKeyValueStoreService类型的模块将客户机代码编写为客户机参数,我们可以通过提供模拟服务来测试应用程序在使用set函数时对网络错误的恢复能力,而无需实际创建网络错误:

module KeyValueStoreServiceFailingOnSet =
struct
  exception NetworkError
  type t = unit
  let list () = [ "a"; "b"]
  let find = function
    | "a" -> Some("x")
    | "b" -> Some("y")
    | _ -> None
  let set _ _ = raise NetworkError
end
如果我们的客户机是由AbstractKeyValueStoreService类型的模块作为函子参数编写的,那么很容易为这个软件组件编写测试,其中模拟服务遵循与客户机的或多或少复杂的交互脚本

使用模块作为参数可能不是一个“惊天动地的想法”,但重要的是要知道如何使用这个想法来解决重要的软件工程问题。这就是“真实世界OCaml”的作者们所做的