我正在寻找风格指导。在 Python 中,异常被用作“正常”操作:
try:
z = x/y
except ZeroDivisionError:
z = 73.0 # set z if y is zero
Run Code Online (Sandbox Code Playgroud)
我们不是检查 y 是否接近零,而是进行除法并捕获异常。
这种类型的方法在 John Barnes 的“Programming in Ada 2012”中的 Ada 中有说明:
begin
Tomorrow := Day'Succ(Today);
exception
when Constraint_Error =>
Tomorrow := Day'First;
Run Code Online (Sandbox Code Playgroud)
但是,这本书接着说“这是一个非常糟糕的例子。异常应该用于很少发生的情况......”。
我是 Ada 的新手,像我们在 Python 中所做的那样,使用异常来避免 if 语句是一种好的 Ada 编程风格吗?或者异常真的只是在 Ada 中用于令人讨厌的事情?
与 Python 的主要区别在于,在 Ada 中,异常不是数据类型。您可以与异常实例关联的唯一数据是字符串:
raise My_Exception with "some string";
Run Code Online (Sandbox Code Playgroud)
因此,在捕获异常时,我们只能知道抛出了哪种异常,并获取一些可能对日志有用的字符串,但对于以编程方式更详细地分析出了什么问题就没有那么多了。
这也意味着我们没有办法链接异常,就像它经常在 Java 中完成的那样,其中一个异常通常被包装在另一个异常中以隐藏细节,同时仍然能够在堆栈跟踪中看到到底出了什么问题.
这样做的原因是该语言是为几乎不使用异常而设计的。与 Python 不同,Ada 旨在针对裸机,您可能出于性能原因想要禁用运行时检查。如果你这样做,你不会得到Constraint_Error除以零,程序将有未定义的行为。因此,使用异常会对代码可移植性产生负面影响。
一些编译器提供了额外的选项,比如No_Exception_PropagationGNAT 中的限制,它只允许在同一子例程中捕获异常时才允许异常。
尽管如此,异常仍然是一种有用的工具,可以在不完全阻碍代码中的正常程序流程的情况下传达失败信息(如果您曾经编写过 Go 或 C,就会明白我的意思)。但总的来说,Ada 风格指南建议
异常应用作抽象的一部分,以指示抽象无法防止或纠正的错误情况。因为抽象无法纠正这样的错误,所以它必须向用户报告错误。
这意味着,如果您确实有可能在不使用异常的情况下纠正问题,那么您应该这样做,因为它应该是正常的、非异常的程序流程的一部分。
Ada 异常处理语法不使用 try-catch 机制。因此,异常处理程序通常与引发异常的代码通过多行源代码分开。Ada 异常预计将用于真正异常的问题。Ada 更容易接受的样式如下所示。
if Today < Day'Last then
Tomorrow := Day'Succ(Today);
else
Tomorrow := Day'First;
end if;
Run Code Online (Sandbox Code Playgroud)
此 Code Pattern 保留了源代码中两个非常接近的条件之间的关系。这两种情况都不是错误情况或异常情况。
从历史上看,Ada 风格更注重可读性而不是书写的紧凑性,但是 Ada 2012 标准确实允许条件表达式,例如
Tomorrow := (if Today < Day'Last then Day'Succ(Today) else Day'First);
Run Code Online (Sandbox Code Playgroud)
是否使用条件表达式可能是个人喜好的问题。