Это зависит от определения термина постусловие. Как правило, предварительное условие — это отношение состояния ввода и входных значений при входе в подпрограмму, а постусловие — это отношение состояния ввода, входных значений и выходного состояния, а также выходных значений при выходе из подпрограммы.
Поскольку подпрограмма может завершаться как в обычном, так и в исключительном порядке, можно определить постусловие для нормального завершения и постусловие для аварийного завершения. Ясно, что оба включают входные значения, входное состояние и выходное состояние. Ключевое отличие заключается в выходных значениях. В первом случае это значение, указанное в сигнатуре подпрограммы, во втором - зависит от языка. В вашем примере это может быть NoPathException
, но что, если есть ошибка выделения памяти, переполнение стека или другое исключение или сигнал, не указанный в подписи? Действительно может показаться возможным иметь предварительное условие, гарантирующее, что всегда существует допустимый результат, не включающий исключений. Но это не так, т.е. когда есть связь с внешним миром, параллелизм и т. д. Кроме того, если предварительное условие слишком затратно для вычисления, некрасиво выполнять одну и ту же работу дважды — на стороне клиента, чтобы убедиться, что вызов применим, и на стороне поставщика. сделать по существу те же вычисления, чтобы получить результат.
Согласно философии Design by Contract, постусловие — это то, на что клиент может безопасно положиться после вызова подпрограммы. Возвращаясь к исключительному случаю, с практической точки зрения имеет смысл сделать аномальное постусловие достаточно сильным, чтобы программа могла продолжить выполнение, но достаточно слабым, чтобы случаи, которые не указаны или не могут быть указаны в сигнатуре, но возможны на практике, допускаются.
Таким образом, если язык действительно не гарантирует все возможные исключительные случаи и ничего больше, наиболее важной частью является выходное состояние, которое не должно делать связанные объекты непригодными для использования. И это может быть выражено в явном или неявном постусловии или в виде инварианта класса.
Что касается конкретного примера с getPath
, то ситуация, когда пути не существует, является нормальной, т.е. может случиться, ожидается. В некоторых руководствах рекомендуется использовать нормальные значения для обозначения нормальных случаев завершения. Здесь это будет значение null
. Использование null
может привести к другим проблемам на стороне вызывающей стороны, например, NullPointerException
, если результат не проверяется на нуль, но в некоторых языках, которые гарантируют отсутствие таких исключений (например, void-safety в Eiffel ) это был бы предпочтительный способ указать на отсутствие пути (в этом случае возвращаемый тип будет detachable PATH
).
person
Alexander Kogtenkov
schedule
20.05.2016