设计分歧:安全检查
我们(两个人)正在使用Lua作为嵌入语言进行项目开发。
我的队友几乎在所有地方都使用参数类型检查:
function someFunction( a, b,c )
if a == nil then return end
--Some stuff here
if type( b ) ~= "function" then
Error( "blah" )
end
--More here
if someTable[ c ] == nil then someTable[ c ] = {}
end
我不是很喜欢这样做,我认为大部分检查都是不必要的,这有点违背了使用Lua的初衷。我认为这样做使得代码变得更长、更慢,也不太易读。
一般来说,我会这样做:
function someFunction( a, b,c )
--More here
if someTable[ c ] == nil then someTable[ c ] = {}
end
我省略了几乎所有类型/参数检查,仅对那些可能真正发生的检查进行了检查。
- 现在我们不确定哪种解决方案更好,决定向你提问:在Lua中进行安全检查-是或不是?
原文链接 https://stackoverflow.com/questions/4351015
我也不知道 Lua,而且你的问题有点不清楚,你是只想检查参数的类型[type(b)~="function"],还是也想检查它们的值[a==nil],但以下是我做的:
如果这个函数只会被你自己编写的其他函数调用,并且那些函数已经检查过参数了,那么就无需再次检查。另一方面,如果你的设计不能保证参数的安全性,那么你需要自己检查参数。
基本上,什么问题可能出现就会出现,但它会等到你测试并发布之后再出现。你不能冒险-你确实需要一份坚如铸铁的保证。选择保障的关键是检查你的设计并看看你真正需要什么。
(即使这个函数只被你自己的其他函数调用,如果你认为稍后可能会忘记所有这些并在没有检查的情况下从其他地方调用它,你仍然可能想要包括检查。)
我在我的 API 中对公共函数进行类型检查,但是不会对仅在内部使用的函数进行检查。
良好的类型检查:
function ( a , b )
assert ( type ( a ) == "number" , "Invalid a" )
b = b or {}
assert ( type ( b ) == "table" , "B must be a table" )
c = assert ( type ( c ) == "string" ) and c or "default"
end
请记住,Lua 也有一点“鸭子”类型:如果一个对象所需的全部都是可调用的,那么具有 __call 方法的表应该是可以被接受的。对于可索引的对象也是一样:表和 userdata 都可以被索引(更不用说其他类型了)。
我猜这取决于您接下来计划做什么: 如果其他人实际上需要编写 Lua 代码与您的代码配合使用,检查参数(或通过类似启用 Debug 功能的方式)将是有用的。我昨天遇到的一些有用的东西是 DecoratorsAndDocstrings,它使得在不改变实现的情况下可以对函数进行文档/类型检查。
另一个用于此目的的惯用语是:
argument = argument or default -- 或者
argument = type(argument)=="number" and argument or error'I should get a number'
现在我们不确定哪种解决方案更好,决定向您询问:Lua 中的安全检查 - 是还是不是?
它取决于项目的类型。如果您的项目很小 - 即您和您的团队成员将是唯一的项目管理者 - 可以跳过检查,因为您应该知道要传递给函数的参数,并且这将使代码变得简洁易读。缺点是当发生错误(可能发生在完全意外的地方)时,您将不得不花时间调试和跟踪函数。
另一方面,如果您正在创建一个要供他人使用的库/ API,则非常适合执行类型检查。对于您的库的用户,他们不知道内部情况,知道何时传递了错误的参数是非常有帮助的。
你需要在重要的地方(而在不重要的地方则无需)检查类型。通常,我会对大多数公共函数参数进行类型检查,并且在调试时遇到类型错误时添加检查。
为了缩短类型检查,我使用一个小的 arguments()
辅助函数:
https://github.com/lua-nucleo/lua-nucleo/blob/master/lua-nucleo/args.lua
示例:
https://github.com/lua-aplicado/lua-aplicado/blob/master/lua-aplicado/filesystem.lua#L63-66
local write_file = function(filename, new_data)
arguments(
"string", filename,
"string", new_data
)
local file, err = io.open(filename, "w")
if not file then
return nil, err
end
file:write(new_data)
file:close()
file = nil
return true
end
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
我对 Lua 不熟悉,但维基百科认为它是鸭子类型。我将用 Python 进行类比,如果不合适,请谅解。
在 Python 中,函数被设计成需要一个符合特定标准的对象。如果你传入一个与原作者预期不同的对象,只要它符合函数的标准,它应该可以工作。这意味着“如果它看起来像一只鸭子,走路像一只鸭子,叫声像一只鸭子,它就是一只鸭子。”(因此得名。)话虽如此,有一些少见的情况需要一个特定类型的对象,但这并不是一般情况。
总之,你似乎在“与语言作斗争”,这是我看来的代码气味。大多数语言都是设计和打算用于特定的方式-找出 Lua 社区使用的原则、设计/编码准则,并遵循它们。