设计分歧:安全检查

时间:2010-12-03 23:59:24

标签: lua

我们(两个人)正在使用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的安全检查 - 是或否?

6 个答案:

答案 0 :(得分:2)

我对Lua并不熟悉,但维基百科似乎认为它是鸭子型的。我打算用Python来比喻,如果它不合适,请原谅我。

在Python中,函数的设计原则是它们需要一个满足特定条件的对象。如果传入与原作者不同的对象,只要它符合函数的标准,它就应该有效。这个想法是,“如果看起来像一只鸭子,像鸭子一样走路,像鸭子一样呱呱叫,它就是一只鸭子。” (因此得名。)也就是说,有一些罕见的实例,你需要一个特定类型的对象,但这不是一般情况。

无论如何,你似乎是“对抗语言”,这是我书中的代码味道。大多数语言都是按照某些方式设计和使用的 - 弄清楚Lua社区使用的原则和设计/编码指南,并遵循这些原则。

答案 1 :(得分:1)

我在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还有一些“duck”类型:如果对象中所需的全部都是可调用的,那么应该允许带有__call方法的表。对于可索引对象也是如此:表和userdata都可以被索引(更不用说其他类型)。

答案 2 :(得分:0)

我也不认识Lua,而且你是否只询问检查参数 types [type(b)〜=“function”]还是有点不清楚或者你想要检查他们的价值[a == nil],但这就是我的工作:

如果该函数只能由您自己的某些其他函数调用,并且其他函数已经检查了该参数,则无需再次检查它。另一方面,如果您的设计不能保证论证的安全性,那么您需要自己检查。

基本上,可能出错的地方会出错,但它会等到你完成测试并发货之后。你不能冒险 - 你需要铸铁保证。选择保证的关键是检查您的设计,看看您真正需要什么。

(即使该函数仅由您自己的其他函数调用,如果您认为以后可能会忘记所有这些并在未经检查的情况下从其他地方调用它,您可能仍希望包含检查。)

答案 3 :(得分:0)

我想这取决于你打算下一步做什么:如果其他人真的应该编写Lua代码来处理你的代码,那么检查参数(或者通过使用像enableDebug之类的东西来实现它)会很有用。我昨天遇到的有用的东西是DecoratorsAndDocstrings,它可以在不改变实现的情况下记录/检查函数。

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

argument = argument or default -- or
argument = type(argument)=="number" and argument or error'I should get a number'

答案 4 :(得分:0)

  

现在我们不确定哪种解决方案更好,并决定问你:Lua的安全检查 - 是或否?

这取决于项目的类型。如果你的项目很小 - 也就是只有你和你的队友要管理它 - 可以跳过检查,因为你应该知道你正在传递给函数,它会使代码变得小而且可读。缺点是当发生错误时 - 它可能发生在某个完全意外的地方 - 你将不得不花时间调试和追踪你的功能。

另一方面,如果要创建供其他人使用的库/ API,则进行类型检查非常合适。对于不知道内部结构的图书馆用户,了解他何时传递错误的参数非常有帮助。

答案 5 :(得分:0)

您需要检查重要的类型(并且不应检查重要的位置)。通常我会检查大多数公共函数参数,并在调试时遇到类型错误的任何地方添加一个检查。

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