Должны ли методы иметь те же предварительные условия, что и методы, которые они вызывают? - PullRequest
1 голос
/ 20 декабря 2010

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

public Goal getNextGoal() {
    return goalStack.pop();
}

Если у goalStack.pop() есть предварительное условие, что стек не пустой, то нужно ли getNextGoal() явно иметь такое же предварительное условие?Кажется, что наследование предусловий сделало бы вещи хрупкими, а переход в очередь или другую структуру изменил бы предусловия на getNextGoal(), его вызывающих и вызывающих абонентов.Но кажется, что не наследование предварительных условий скрыло бы контракты, и вызывающие абоненты, и вызывающие абоненты, не знали бы о предварительных условиях.

То есть хрупкий код, когда все вызывающие абоненты знают и наследуют предусловия и постусловия кода, который они вызывают, или таинственный код, когда вызывающие абоненты никогда не знают, какие более глубокие предусловия и постусловия есть?

Ответы [ 2 ]

3 голосов
/ 21 декабря 2010

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

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


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

Кажется, что наследование предусловий сделало бы вещи ломкими, а переход в очередь или другую структуру изменил бы предусловия на getNextGoal (), его вызывающие и вызывающие абоненты.

Если вы выставите очередь для вызывающих и измените ее позже (на другую структуру, как вы сказали), ее вызывающие также должны будут измениться.Обычно это признак хрупкого кода.

Если бы вы предоставили интерфейс вместо конкретной реализации очереди , ваши предварительные условия также могли бы использовать интерфейс, и вам не пришлось бы менятьпредварительные условия каждый раз, когда ваша реализация меняется.В результате получается менее хрупкий код.

0 голосов
/ 20 декабря 2010

Исключения являются одним из решений, но, возможно, неосуществимым для вашей ситуации.

Документирование того, что происходит, если нет целей, является нормальным. Это то, что malloc () делает в C

Я могуне говорите, используете ли вы Java, C ++ или что-то еще, поскольку у каждого языка могут быть несколько более естественные способы для этого конкретного языка.

...