【问题标题】:Data format safety in clojureclojure 中的数据格式安全性
【发布时间】:2012-02-11 17:06:59
【问题描述】:

来自 Java 背景,我非常喜欢静态类型安全,并且想知道 clojure 程序员如何处理数据格式定义的问题(也许不仅仅是类型,而是一般不变量,因为类型只是其中的一个特例。 )

这类似于现有的问题“Clojure 中的类型安全”,但该问题更关注如何在编译时检查类型,而我更感兴趣的是如何务实地解决问题。

作为一个实际示例,我正在考虑一个处理特定文档格式的编辑器应用程序。每个文档都包含有几种不同类型的元素(图形元素、字体元素等)。会有针对不同元素类型的编辑器,当然还有将文档从/转换为原生字节流的功能-磁盘格式。

我感兴趣的基本问题是编辑器和读/写函数必须就通用数据格式达成一致。在 Java 中,我会将文档的数据建模为对象图,例如一个类代表一个文档,一个类代表每个元素种类。这样,我就可以在编译时保证我的数据结构是什么样的,并且图形元素的“宽度”字段是整数而不是浮点数。它不保证宽度是正的 - 但使用 getter/setter 接口将允许相应的类添加这样的不变保证。

能够依赖这一点使处理这些数据的代码更简单,并且可以在编译时或运行时早期发现格式违规(其中一些代码试图修改会违反不变量的数据)。

如何在 Clojure 中实现类似的“数据格式可靠性”?据我所知,没有办法执行编译时检查并在函数接口后面隐藏域数据似乎不鼓励使用非惯用语(或者我可能误解了?),那么 Clojure 开发人员会做些什么来感到安全传递给它们的函数的数据格式是什么?当保存功能注意到字体列表中有一个图形元素时,如何让代码尽快出错,而不是在用户编辑 20 多分钟并尝试保存到磁盘之后编辑器错误?

请注意,我对 Clojure 和学习很感兴趣,但还没有用它编写任何实际的软件,所以我可能只是感到困惑,答案很简单 - 如果是这样,抱歉浪费你的时间:)。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    我认为使用验证 API 来构造和操作您的数据没有任何错误或不习惯,如下所示。

    (defn text-box [text height width]
      {:pre [(string? text) (integer? height) (integer? width)]}
      {:type 'text-box :text text :height height :width width})
    
    (defn colorize [thing color]
      {:pre [(valid-color? color)]}
      (assoc thing :color color))
    
    ... (colorize (text-box "Hi!" 20 30) :green) ...
    

    此外,引用(vars、refs、atoms、agents)可以有一个关联的validator function,可用于确保始终处于有效状态。

    【讨论】:

    • 感谢您到目前为止的回答。由于这是一个相当开放的问题,我会在接受之前再等一会儿。验证器功能听起来像是一个有趣的解决方案,但是(继续使用示例)如果您有一个大文档作为您的状态,每次进行小的更改时完全验证它似乎效率低下 - 在这样的模型中,我猜使用验证操作函数会更好。
    【解决方案2】:

    好问题 - 我还发现从静态类型语言迁移到动态语言需要更加关注类型安全。幸运的是,TDD 技术在这方面有很大帮助。

    我通常会编写一个“验证”函数来检查您对数据结构的所有假设。我也经常在 Java 中为不变假设执行此操作,但在 Clojure 中它更重要,因为您还需要检查 thinks like types。

    然后您可以通过多种方式使用验证功能:

    • 作为 REPL 的快速检查:(validate foo)
    • 在单元测试中:(is (validate (new-foo-from-template a b c)))
    • 作为关键功能的运行时检查,例如检查(read-foo some-foo-input-stream) 是否有效

    如果你有一个复杂的数据结构,它是多个不同组件类型的树,你可以为每个组件类型编写一个验证函数,并让整个文档调用的验证函数递归地为每个子组件验证。一个不错的技巧是使用协议或多方法使 validate 函数对每种组件类型都具有多态性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-16
      相关资源
      最近更新 更多