【问题标题】:Is it ok to use spec/valid? for function input validation at runtime?可以使用规范/有效吗?在运行时进行函数输入验证?
【发布时间】:2026-01-12 09:05:01
【问题描述】:

我正在编写一个 clojure 库,并且正在考虑使用 clojure.spec。使用规范/有效是一种好习惯吗?在运行时输入函数?还是我应该使用破坏性和类型提示?我担心是否会有性能损失,是否被认为是对规范的不当使用,以及通常是不好的做法。

【问题讨论】:

    标签: clojure clojure.spec


    【解决方案1】:

    “在适当的情况下”检查有效输入总是合适的。这意味着什么?这是一个悬而未决的问题。

    一般来说,最“危险”的输入来自外部世界,位于程序的边界。这意味着来自网络/浏览器的输入,或者可能来自其他服务。

    “最安全”的输入在您的程序深处,在那里(大概)您有更多的控制权和信心。例如,您(可能)永远不会检查 + 函数的输入以确保每个 arg 都是一个数字。而且,即使一个无效的参数(可能是一个字符串)溜过,JVM 也会立即抛出一个异常。

    当然,您应该在运行单元测试时进行最大程度的检查,因此至少您知道您的代码在“正常”路径中正常工作。我喜欢为此使用Plumatic Schema,因为在单元测试期间始终运行验证很容易,但在“生产”运行期间默认关闭。

    话虽如此,我经常将断言语句放在函数的开头,因为错误的输入很难识别,或者以后真的会导致难以诊断的问题。

    这两种技术救了我很多次!

    请注意,即使是像 Java 这样的强类型语言也无法将您保存在这里。类型化变量可以确保输入是一个数字,但它可能是无效的,例如向sqrt 函数发送一个负值。其他函数可能有更严格的输入,例如仅对素数有效等。类型无法捕获这些详细要求。只有好的设计和好的测试才能避免这些问题。

    类型和断言不能防止所有问题,但它们就像道路上的护栏(或安全带和安全气囊)。它们可能无法防止碰撞,但可以提供早期预警并降低后果的严重性。


    附:您可以看到我喜欢如何平衡安全性和签入a libary I wrote 的成本之间的权衡。请务必see the file _bootstrap.clj,这是仅在单元测试期间打开 Plumatic Sc​​hema 测试的技巧。

    【讨论】:

    • 感谢您的详细回答,据我了解,我应该在运行时使用它,仅用于关键/复杂功能?检查类似 dsl 的库的输入结构会不会出错?例如检查输入是否是 2 个元素的向量,第一个元素是 int,第二个元素是 double。
    • 如有疑问,请核实。为什么不总是验证输入参数的类型,直到您确定不需要或不再负担得起?
    • 好吧,这对我有帮助,在我的困惑中,我开始像疯子一样指定每个功能☺️
    最近更新 更多