Этот пример в Wiki - это реализация инвариантов с JML, который является очень специфической, экзотической и, возможно, хорошо продуманной исследовательской технологией, но вообще не является необходимым мейнстримом.Кроме того, речь идет не только об инвариантах, но и о том, что утверждение мутатора сделало то, что ожидалось, а это не то, о чем я думаю, когда думаю об инвариантах.Я не читал Coders at Work, но я сомневаюсь, что кто-нибудь в Coders at Work использовал JML.
В любом случае, я всегда думал, что инварианты - это отличный способ «рано рухнуть» и не дать вашему коду пытаться делать разумные вещикогда фактически состояние программы находится в необоснованном (незапланированном) состоянии.
Хороший пример инварианта в коде C # может состоять в том, чтобы никогда не отдавать объект в N-Hibernate для сохранения, если этот объект не был переданна его инварианты, которых должно быть много, чтобы не допустить попадания нечувственных данных в базу данных.Давайте посмотрим, смогу ли я вспомнить другие примеры ...
Предположим, у вас есть класс User, который всегда должен иметь свойство основного адреса электронной почты, а затем инвариант, который нужно проверить перед сохранением.может быть, чтобы убедиться, что поле адреса электронной почты не пустое.В противном случае другая логика приложения, предполагающая, что адреса электронной почты существуют для всех пользователей, может испортиться при попытке отправить пользователю электронное письмо позже.
Предположим, что у объекта пользователя "много«Объекты электронной почты, и предположим, что для электронной почты не имеет смысла существовать без принадлежащего ей пользователя, тогда инвариант класса электронной почты может быть для того, чтобы ссылка электронной почты на его пользователя всегда была не нулевой, иначе выпотерянный объект электронной почты, который может привести к исключениям нулевого указателя при попытке обратиться к владельцу электронной почты.
Предположим, вы пишете графический интерфейс, который должен отображать статус AmazonS3 объект в обычной форме WPF.Инвариант в форме может заключаться в том, чтобы убедиться, что форма правильно связана с ее объектом, прежде чем выполнять какие-либо обработчики событий в этой форме.
Предположим, вы пишете StackOverflow.Инвариант здесь может заключаться в том, чтобы убедиться, что уровень репутации пользователя никогда не бывает отрицательным, даже если пользователь применяет штрафы за репутацию.Отрицательная репутация может сломать те симпатичные графики, которые отображают опыт как функцию времени (если только эти графики не подготовлены для построения линий ниже оси 0, что вполне может быть ...).
Что касается того, когда проверять инварианты, вы можете сделать это в конце любого метода, который изменяет состояние данных.На самом агрессивном и параноидальном уровне защитного программирования вы можете проверить инвариант до и после всех методов.