设计分歧:安全检查

我们(两个人)正在使用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

点赞
stackoverflow用户101999
stackoverflow用户101999

我对 Lua 不熟悉,但维基百科认为它是鸭子类型。我将用 Python 进行类比,如果不合适,请谅解。

在 Python 中,函数被设计成需要一个符合特定标准的对象。如果你传入一个与原作者预期不同的对象,只要它符合函数的标准,它应该可以工作。这意味着“如果它看起来像一只鸭子,走路像一只鸭子,叫声像一只鸭子,它就是一只鸭子。”(因此得名。)话虽如此,有一些少见的情况需要一个特定类型的对象,但这并不是一般情况。

总之,你似乎在“与语言作斗争”,这是我看来的代码气味。大多数语言都是设计和打算用于特定的方式-找出 Lua 社区使用的原则、设计/编码准则,并遵循它们。

2010-12-04 00:06:27
stackoverflow用户387490
stackoverflow用户387490

我也不知道 Lua,而且你的问题有点不清楚,你是只想检查参数的类型[type(b)~="function"],还是也想检查它们的值[a==nil],但以下是我做的:

如果这个函数只会被你自己编写的其他函数调用,并且那些函数已经检查过参数了,那么就无需再次检查。另一方面,如果你的设计不能保证参数的安全性,那么你需要自己检查参数。

基本上,什么问题可能出现就会出现,但它会等到你测试并发布之后再出现。你不能冒险-你确实需要一份坚如铸铁的保证。选择保障的关键是检查你的设计并看看你真正需要什么。

(即使这个函数只被你自己的其他函数调用,如果你认为稍后可能会忘记所有这些并在没有检查的情况下从其他地方调用它,你仍然可能想要包括检查。)

2010-12-04 00:33:16
stackoverflow用户282536
stackoverflow用户282536

我在我的 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 都可以被索引(更不用说其他类型了)。

2010-12-04 09:26:54
stackoverflow用户513763
stackoverflow用户513763

我猜这取决于您接下来计划做什么: 如果其他人实际上需要编写 Lua 代码与您的代码配合使用,检查参数(或通过类似启用 Debug 功能的方式)将是有用的。我昨天遇到的一些有用的东西是 DecoratorsAndDocstrings,它使得在不改变实现的情况下可以对函数进行文档/类型检查。

另一个用于此目的的惯用语是:

argument = argument or default -- 或者
argument = type(argument)=="number" and argument or error'I should get a number'
2010-12-04 09:30:54
stackoverflow用户221509
stackoverflow用户221509

现在我们不确定哪种解决方案更好,决定向您询问:Lua 中的安全检查 - 是还是不是?

它取决于项目的类型。如果您的项目很小 - 即您和您的团队成员将是唯一的项目管理者 - 可以跳过检查,因为您应该知道要传递给函数的参数,并且这将使代码变得简洁易读。缺点是当发生错误(可能发生在完全意外的地方)时,您将不得不花时间调试和跟踪函数。

另一方面,如果您正在创建一个要供他人使用的库/ API,则非常适合执行类型检查。对于您的库的用户,他们不知道内部情况,知道何时传递了错误的参数是非常有帮助的。

2010-12-04 14:55:59
stackoverflow用户6236
stackoverflow用户6236

你需要在重要的地方(而在不重要的地方则无需)检查类型。通常,我会对大多数公共函数参数进行类型检查,并且在调试时遇到类型错误时添加检查。

为了缩短类型检查,我使用一个小的 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
2010-12-28 03:17:28