Eiffel中的错误处理示例

时间:2014-11-16 12:08:02

标签: exception error-handling eiffel

我在Eiffel中找不到任何错误处理的实例。我发现的例子既可以是微不足道的,也可以完全忽略错误,或者将错误处理留给读者。我很想知道在没有异常的情况下错误如何通过调用堆栈传递。例如,我想知道发送网络请求的应用程序如何通知用户在调用链中检测到的网络问题。这样的事情。

-

编辑:我确实知道Eiffel中的错误处理的基础知识(状态和例外)。但是,我找不到任何关于应用程序如何通过状态处理错误的实质性示例。如何将故障状态链接起来?

2 个答案:

答案 0 :(得分:3)

Eiffel提倡使用对象状态而不是异常。在这种情况下,客户可以找出他们在出现错误时所期望的并正确处理它。例如,

has_error: BOOLEAN
        -- Has operation terminated with an error?

error_code: INTEGER
        -- Last error code or `no_error'.

is_closed: BOOLEAN
        -- Is connection closed?

response: detachable RESPONCE
        -- Last response if `not has_error'.

send_request (data: REQUEST)
    require
        is_open: not is_closed
    do
        ...
    ensure
        is_closed: is_closed implies (has_error and not connection.is_open)
        is_successful: not has_error implies attached response
    end

然后,客户可以推断供应商对象的状态,并以可预测的方式继续使用它:

interface.send_request (...)
if interface.is_closed then
    ... -- The connection is unusable and should be reestablished.
elseif interface.has_error then
    ... -- Inspect `interface.error_code', possibly trying to resend the request.
else
    ... -- Use `interface.response' to continue processing.
end

在存在例外的情况下,除了某些文档之外,不能推断在什么情况下应该做什么。此外,它还可以防止使用自动工具轻松检查response在上述代码中是否完全有效。

如果在堆栈内部发生错误,则rescue / retry可以使用异常机制。然而,它可能引入低级网络组件和用户界面之间的紧密耦合,这与网络故障的细节无关。在最简单的情况下,网络类将使用适当的消息调用{EXCEPTIONS}.raise。更具体的方法是创建类型为EXCEPTION(或后代)的对象,通过调用set_description来设置相应的消息,并通过调用raise来引发异常。处理异常的用户代码可能如下所示。

local
    is_retried: BOOLEAN
    e: EXCEPTIONS
do
    if is_retried then
            -- There was an exception, handle it.
        create e
        if e.developer_exception_name ~ "This error" then
            ... -- Do something.
        elseif e.developer_exception_name ~ "That error" then
            ... -- Do something else.
        else
            ... -- Report yet another error.
        end
    else
        ... -- Some code that may fail with an exception.
    end
rescue
    if not is_retried then
        is_retried := True
        retry
    end
end

修改

处理嵌套错误的特定方法取决于应用程序设计,似乎与语言无关。可能的替代方案是:

  1. 如果使用异常机制,不推荐使用。)捕获(低级别)异常并处理它以恢复类不变量后,会引发新的异常而不取消前一个。然后可以(递归地)使用查询{EXCEPTION}.cause来访问嵌套的异常对象。

  2. 可以使用与前一个类似的机制。但是,类不是创建新对象,而是可以将详细请求委托给较低级别​​的类。例如,

    class A feature
        has_error: BOOLEAN
            do
                Result := nested.has_error
            end
        error: STRING
            do
                Result := "Cannot complete operation X. Reason: " + nested.error
            end
    feature {NONE}
        nested: B
    end
    
    class B feature
        has_error: BOOLEAN
            do
                Result := nested.has_error
            end
         error: STRING
            do
                Result := "Cannot complete operation Y. Reason: " + nested.error
            end
    feature {NONE}
       nested: C
    end
    
  3. 可以使用记录设施。他们可以区分错误严重性,指定来源等。

    class A feature
        do_something
            do
                nested.whatever
                if nested.has_error then
                    log.error ("Cannot complete operation X.")
                end
            end
        has_error: BOOLEAN do Result := nested.has_error end
    feature {NONE}
        nested: B
    end
    
    class B feature
        whatever
            do
                nested.try_something
                if nested.has_error then
                    -- An error has been reported by "nested".
                elseif something_else_goes_wrong then
                    has_inner_error := True
                    log.error ("Something goes wrong.")
               elseif has_minor_issues then
                     log.warning ("Be careful.")
                end
            end
        has_error: BOOLEAN do Result := nested.has_error or has_inner_error end
        has_inner_error: BOOLEAN
                -- Some error that is not one of the errors reported by `nested'.
    feature {NONE}
       nested: C
    end
    

答案 1 :(得分:2)

除了亚历山大的答案之外,有时使用例外很方便。在埃菲尔,我们不倾向于捕捉它们(通常类别不变量已经变得无效),但对于某些应用程序,您只是不想处理错误。如果出现错误,您只需停止,并依赖程序外部的重试。使用该方法的图书馆的例子是ecli和eposix。