功能规格:-spec.有效使用

ego*_*or7 11 erlang

我怎么能-spec在erlang中使用word?请给我一个有效使用这个词的想法.这仅代表文档目的吗?

我试图通过函数类型规范使用约束来在模块中运行-spec,但是我失败了 - 没有应用任何限制.

aro*_*tav 22

-spec属性确实被编译器和运行时系统视为文档.您无法使用它们向代码中添加任何"可执行功能",这同样适用于-type-opaque属性.

但它们有用:

  • 文档:EDoc使用它们为您的代码生成所有不同形式的文档.-spec属性是函数签名,根据您投入的精力,可以使您的代码更易于理解和维护.假设这个月你最喜欢的数据结构是dict().请考虑以下代码:

    my_function(SomeArg, SomeOtherArg, Dict) ->
      ...
      dict:find(SomeKey, Dict)
      ...
    
    Run Code Online (Sandbox Code Playgroud)

    用作dict的变量已被命名为.但是,假设您有以下代码段:

    my_other_function(NamesDict, PlacesDict) ->
      ...
      R1 = my_function(A, B, NamesDict),
      ...
      R2 = my_function(C, D, PlacesDict),
    ...
    
    Run Code Online (Sandbox Code Playgroud)

    试图跟上这一点可能很快会导致代码重复此Dict后缀.更重要的是,你可能甚至不想记住my_other_function这两个论点的背景dict().所以你可能想要这样做:

    -spec my_other_function(dict(), dict()) -> atom().
    
    my_other_function(Names, Places) ->
      ...
      R1 = my_function(A, B, Names),
      ...
      R2 = my_function(C, D, Places),
      ...
    
    Run Code Online (Sandbox Code Playgroud)

    现在很明显,这些参数应该是dict()以使函数工作,并希望每个人都能够在不深入代码的情况下解决这个问题.但是假设您Name dict()在其他地方使用它,并且它存储了一些使用不同API公开的特定信息.然后它是-type宣言的完美候选人:

    -type names() :: dict().
    
    -spec my_other_function(names(), places()) -> atom().
    
    my_other_function(Names, Places) ->
      ...
      R1 = my_function(A, B, Names),
      ...
      R2 = my_function(C, D, Places),
      ...
    
    Run Code Online (Sandbox Code Playgroud)

    如果其他人频繁使用此特定数据结构,您可能也想要导出它:

    -module(my_module).
    
    -export_type([names/0]).
    
    -type names() :: dict().
    
    Run Code Online (Sandbox Code Playgroud)

    其他模块现在可以引用此特定数据结构:

    -module(my_other_module).
    
    -record(my_state, {names :: my_module:names(),
                       ...}).
    
    Run Code Online (Sandbox Code Playgroud)

    最后,如果您希望其他开发人员不在其模块中以任何方式检查此数据结构,则可以将其声明为-opaque.同样,这是一个"友好的建议",就像到目前为止所有其他的东西一样.还是......?

  • 差异检测:如果您需要时间使用-specs,-types您非常希望这些保持最新.众所周知,如果没有观看,没有人保持文档最新!幸运的是,Dialyzer正在观看.Dialyzer 可以 检查所有my_function()对参数的调用dict()(即使没有你的-spec注释它也能做到这一点,但如果有这些也会更容易)并且如果你用其他东西调用它就会尖叫血腥谋杀.此外,它还可以跟踪这些导出的类型,甚至可以报告不透明度违规.所以它不仅仅是"文档".

  • 测试用例生成:PropEr可以使用-spec-type定义自动检查您的函数与随机测试用例.即使从这样的声明,它也能够制作随机测试用例:

    -type int_tree() :: {node, integer(), tree(), tree()} | nil.
    
    Run Code Online (Sandbox Code Playgroud)
  • 为行为指定一组回调的全新方式是使用熟悉的-spec语法.编译器,Dialyzer和其他可能的工具可以使用此信息来检查行为实现.请参阅OTP行为代码此处的更多信息

在这里阅读更多.


I G*_*ERS 9

-spec功能的规格有几个地方可以帮助:

  • 它们充当函数的文档.生成EDoc将提取规范并在文档中提供它们.
  • 它们是透析器的规格.当透析器运行时,它将使用规范以任何方式确定代码是否错误.也就是说,如果您的规范是错误的 - 在某些情况下,它将帮助系统准确理解代码错误的原因.
  • 它们是行为规范中的宝贵工具.有一个新-callback关键字可用于为行为API执行此操作.
  • 它们对于构建程序如何组合以及数据来自何处的类型框架非常有价值.
  • 加上表兄弟-type-opaque可以强制某些类型来是不透明的代码段.这意味着您不能在静态验证级别上查看内部表示.这可以反过来帮助驱动模块化代码,因为您不允许紧密耦合代码片段.