Является ли исключение допустимым постусловием?

Рассмотрим следующий интерфейс:

public interface AISPI
{
    public Path getPath(Entity entity, Entity target, World world) throws NoPathException;
}

При условии, что entity, target и world являются допустимыми входными данными. Но алгоритм, используемый для поиска пути (в данном случае это Astar), не может найти путь, например, из-за. положение цели окружено бетонными стенами.

Допустимо ли указать, что постусловие является либо Path от entity до target (от начала до цели), либо NoPathException (учитывая, что путь не был найден)?
 – Или в предварительном условии должно быть указано, что должен существовать допустимый путь от начала к цели?

Это не домашнее задание, а вопрос для улучшения нашего семестрового отчета по проекту. Я не собираюсь узнавать о каких-либо фреймворках, это чисто вопрос стандартов и формальностей в отношении проектирования по контракту. Спасибо за любые разъяснения по этому вопросу.


person LuqJensen    schedule 19.05.2016    source источник
comment
На мой взгляд, ни исключения, ни возвращаемые значения не являются постусловиями. Постусловие — это контракт, в котором говорится: «После того, как процедура завершена, имеет место X, где X — некоторое условие». Примером может быть процедура, которая фиксирует значение x в диапазоне [m, n]; постусловие состоит в том, что m ‹= x ‹= n. Либо будет возвращен путь, либо будет выдано исключение — это не постусловие; это буквально контракт, обеспечиваемый сигнатурой метода.   -  person trentcl    schedule 19.05.2016
comment
Я ценю ваши отзывы, но они не являются ответом на вопрос. Я мог бы отредактировать сообщение, включив в него исправление вашей терминологии, но это ничего не меняет в отношении самого вопроса. Это вопрос не восприятия, а правильности в соответствии со стандартом.   -  person LuqJensen    schedule 19.05.2016
comment
Согласен, это не ответ на вопрос. Вот почему я разместил это как комментарий, а не ответ. Вы можете свободно игнорировать меня, но я думаю, что вы получите лучшие ответы, если сформулируете свой вопрос более точно.   -  person trentcl    schedule 19.05.2016


Ответы (1)


Это зависит от определения термина постусловие. Как правило, предварительное условие — это отношение состояния ввода и входных значений при входе в подпрограмму, а постусловие — это отношение состояния ввода, входных значений и выходного состояния, а также выходных значений при выходе из подпрограммы.

Поскольку подпрограмма может завершаться как в обычном, так и в исключительном порядке, можно определить постусловие для нормального завершения и постусловие для аварийного завершения. Ясно, что оба включают входные значения, входное состояние и выходное состояние. Ключевое отличие заключается в выходных значениях. В первом случае это значение, указанное в сигнатуре подпрограммы, во втором - зависит от языка. В вашем примере это может быть NoPathException, но что, если есть ошибка выделения памяти, переполнение стека или другое исключение или сигнал, не указанный в подписи? Действительно может показаться возможным иметь предварительное условие, гарантирующее, что всегда существует допустимый результат, не включающий исключений. Но это не так, т.е. когда есть связь с внешним миром, параллелизм и т. д. Кроме того, если предварительное условие слишком затратно для вычисления, некрасиво выполнять одну и ту же работу дважды — на стороне клиента, чтобы убедиться, что вызов применим, и на стороне поставщика. сделать по существу те же вычисления, чтобы получить результат.

Согласно философии Design by Contract, постусловие — это то, на что клиент может безопасно положиться после вызова подпрограммы. Возвращаясь к исключительному случаю, с практической точки зрения имеет смысл сделать аномальное постусловие достаточно сильным, чтобы программа могла продолжить выполнение, но достаточно слабым, чтобы случаи, которые не указаны или не могут быть указаны в сигнатуре, но возможны на практике, допускаются.

Таким образом, если язык действительно не гарантирует все возможные исключительные случаи и ничего больше, наиболее важной частью является выходное состояние, которое не должно делать связанные объекты непригодными для использования. И это может быть выражено в явном или неявном постусловии или в виде инварианта класса.

Что касается конкретного примера с getPath, то ситуация, когда пути не существует, является нормальной, т.е. может случиться, ожидается. В некоторых руководствах рекомендуется использовать нормальные значения для обозначения нормальных случаев завершения. Здесь это будет значение null. Использование null может привести к другим проблемам на стороне вызывающей стороны, например, NullPointerException, если результат не проверяется на нуль, но в некоторых языках, которые гарантируют отсутствие таких исключений (например, void-safety в Eiffel ) это был бы предпочтительный способ указать на отсутствие пути (в этом случае возвращаемый тип будет detachable PATH).

person Alexander Kogtenkov    schedule 20.05.2016