Эйфель выступает за использование состояния объекта вместо исключений. В этом случае клиенты могут понять, чего они ожидают в случае ошибки, и обработать ее должным образом. Например,
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
в приведенном выше коде.
Если ошибка происходит глубоко в стеке, можно использовать механизм исключения с _4 _ / _ 5_. Однако это может привести к тесной связи между сетевым компонентом низкого уровня и пользовательским интерфейсом, которая не имеет ничего общего с деталями сбоя сети. В простейшем случае сетевой класс вызовет {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
ИЗМЕНИТЬ
Конкретный способ обработки вложенных ошибок зависит от дизайна приложения и не имеет отношения к языку. Возможные альтернативы:
(Если используется механизм исключения, не рекомендуется.). После перехвата исключения (нижнего уровня) и его обработки для восстановления инварианта класса создается новое исключение без отмены предыдущего. Затем запрос {EXCEPTION}.cause
можно (рекурсивно) использовать для доступа к вложенным объектам исключений.
Можно использовать механизм, аналогичный предыдущему. Однако вместо создания новых объектов класс может делегировать запрос подробностей классу более низкого уровня. Например,
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
Могут быть использованы лесозаготовительные сооружения. Они могут различать серьезность ошибки, указывать источники и т. Д.
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
person
Alexander Kogtenkov
schedule
16.11.2014
has_error
. Программа вызывает функцию с предварительным условием (требует)not has_error
. (Исключения используются из-за опасений, что коды возврата и т. Д. Могут быть проигнорированы. На некоторых других языках есть полиция, которую мы можем использовать через исключения, потому что их нельзя игнорировать, но они могут и часто так и есть. У Эйфеля есть полиция, которая выбрасывает исключение, если вы игнорируете ошибку.) - person ctrl-alt-delor   schedule 26.07.2015