首页 > 解决方案 > 可以使用规范/有效吗?在运行时进行函数输入验证?

问题描述

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

标签: clojureclojure.spec

解决方案


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

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

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

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

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

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

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

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


PS 你可以看到我喜欢在安全性和签入我编写的库的成本之间取得平衡。请务必查看文件_bootstrap.clj,这是仅在单元测试期间打开 Plumatic Sc​​hema 测试的技巧。


推荐阅读