erlang中的错误传播

时间:2014-04-01 21:22:32

标签: error-handling erlang

我对erlang中的错误处理有一些概念性的问题。举个例子,我们可以使用一些返回{ok, Result}{error, Err}的数据库调用。我有一个库包装调用这个数据库,所以我可以做一些前/后处理。当这个库调用数据库时,它应该执行

A)严重崩溃,否则返回结果:

{ok, Result} = db:call(), postprocess(Result).

B)严重崩溃,否则返回包装结果:

{ok, Result} = db:call(), {ok, postprocess(Result)}.

C)实际处理错误并将其返回:

case db:call() of
{ok, Result} -> {ok, postprocess(Result)};
{error, Err} -> {error, Err}
end.

D)其他东西

作为一个后续问题,如果我有另一个调用此库的库,使用什么错误传播?我的想法是图书馆应该与其回归价值保持一致,我只是不清楚如何决定这些应该是什么。

1 个答案:

答案 0 :(得分:1)

嗯,这取决于错误的类型以及应该如何处理。

B)似乎最不可能在任何地方使用。由于您无法返回任何错误值,因此将它包装在ok元组中是没有意义的。

A)似乎是数据库连接库的一个很好的例子。例如,您可能会遇到与数据库连接的问题。通常,您不希望每次有人调用您的代码来预测此类情况,并重新启动服务器。 erlang方式是让用户崩溃,并让它的主管在良好的环境中重新启动它,并重做请求。这种方法允许用户端的快乐路径编码,以及应用程序逻辑和负责设置(并以相同方式重新启动)wright环境的代码之间的强大分离。

使用C)方法可以实现类似的结果(客户端仅匹配ok元组),但坚持A)可能会让用户更多地了解您的方面会发生什么

当库客户端可以完全挖掘(从逻辑点)处理错误时,可以使用C)处理。好的示例可能是proplist:get_value/2 ,您可以在{Key, Value}响应中模式匹配,也可以获得一个原子undefined。返回没有ok个原子,但Key足以找到快乐的路径。通常,此代码的客户端可以轻松处理undefined(这是一种错误),以完全挖掘其逻辑的方式。当然,他们只能在快乐的道路上进行模式匹配,并让它发挥作用。这个想法不仅仅是为了处理错误而处理错误;你只实现你的应用案例。

再说一遍。在C)示例中,您只允许处理{error, Error}个错误。如果您想传递所有错误,这可能是更好的方法:

case db:call() of
   {ok, Result} -> 
         {ok, postprocess(Result)};
   Else -> 
         Else
end.