Я читаю Coders at Work , и в нем много говорят об инвариантах. Насколько я понял, инвариант - это условие, которое выполняется до и после выражения. Они, помимо прочего, полезны для доказательства правильности цикла, если я правильно помню курс по логике.
Мое описание верно, или я что-то пропустил? Вы когда-нибудь использовали их в своей программе? И если да, то как они выиграли?
invariants
gablin
источник
источник
Ответы:
В ООП инвариант - это набор утверждений, которые всегда должны выполняться в течение жизни объекта, чтобы программа была действительной. Он должен быть истинным с конца конструктора до начала деструктора всякий раз, когда объект не выполняет метод, который изменяет свое состояние.
Примером инварианта может быть то, что ровно одна из двух переменных-членов должна быть нулевой. Или что если у одного есть заданное значение, то набор допустимых значений для другого является тем или иным ...
Я иногда использую функцию-член объекта, чтобы проверить, что инвариант держится. Если это не так, утверждается. И метод вызывается в начале и выходе каждого метода, который изменяет объект (в C ++ это только одна строка ...)
источник
Хорошо, материал, который я вижу в этой теме, великолепен, но у меня есть определение «инварианта», которое мне очень помогло на работе.
Это определение полезно, потому что оно разбивает условия на две группы: те, которым компилятору можно доверять с применением, и те, которые должны быть задокументированы, обсуждены, прокомментированы или иным образом доведены до участников, чтобы они могли взаимодействовать с базой кода без появления ошибок. ,
Также это определение полезно, потому что оно позволяет использовать обобщение «Инварианты плохие».
Например, механизм переключения передач в автомобиле с механической коробкой передач спроектирован так, чтобы избежать инварианта. Если бы я хотел, я мог бы построить трансмиссию с одним рычагом для каждой передачи. Этот рычаг может быть вперед («включен») или назад («отключен»). В такой системе я создал «инвариант», который можно задокументировать так:
И так, можно было бы обвинить сломанные передачи на небрежном вождении. Современные автомобили, однако, используют одну палку, которая вращается среди передач. Он сконструирован таким образом, что на современном автомобиле с переключением передач невозможно задействовать две передачи одновременно.
Таким образом, мы могли бы сказать, что передача была разработана для «удаления инварианта», потому что она не позволяет механически конфигурировать себя таким образом, который нарушает логическое правило.
Каждый такой инвариант, который вы удаляете из своего кода, является улучшением, потому что он снижает когнитивную нагрузку при работе с ним.
источник
Инвариант (в обычном смысле) означает некоторые условия, которые должны выполняться в определенный момент времени или даже всегда, когда ваша программа выполняется. Например, PreConditions и PostConditions могут использоваться для утверждения некоторых условий, которые должны быть истинными, когда функция вызывается и когда она возвращается. Инварианты объекта могут использоваться для подтверждения того, что объект должен иметь действительное состояние в течение всего времени его существования. Это дизайн по принципу контракта.
Я использовал инварианты неформально, используя проверки в коде. Но в последнее время я играю с библиотекой контрактов кода для .Net, которая напрямую поддерживает инварианты.
источник
Основываясь на следующей цитате из Coders At Work ...
... Я думаю, "invariant" = "условие, которое вы хотите поддерживать, чтобы обеспечить желаемый эффект".
Кажется, что инвариант имеет два смысла, которые отличаются тонким способом:
Так что 1 похоже на утверждение; Я думаю, что 2 - это инструмент для проверки правильности, производительности или других свойств. См. Статью Wikipedia для примера 2 (доказательство правильности решения головоломки MU).
На самом деле третье чувство инварианта это:
0,3. Что должна делать программа (или модуль или функция); другими словами, его цель.
Из того же интервью Coders At Work:
источник
Инвариант подобен правилу или предположению, которое можно использовать для определения логики вашей программы.
Например, предположим, у вас есть какое-то программное приложение, которое отслеживает учетные записи пользователей. Предположим также, что пользователь может иметь несколько учетных записей, но по какой-либо причине вам необходимо различать основную учетную запись пользователя и учетные записи «псевдонимов».
Это может быть запись в БД или что-то еще, но сейчас давайте предположим, что каждая учетная запись пользователя представлена объектом класса.
class userAccount {private char * pUserName; private char * pParentAccountUserName;
...}
Инвариантом может быть предположение, что если pParentAccountUserName имеет значение NULL или пусто, то этот объект является родительской учетной записью. Вы можете использовать этот инвариант для различения разных типов учетных записей. Вероятно, существуют более эффективные методы для различения различных типов учетных записей пользователей, поэтому имейте в виду, что это всего лишь пример, показывающий, как можно использовать инвариант.
источник
Исходя из фона физики, в физике у нас есть инварианты, которые по существу являются величинами, которые не меняются в течение всего вычисления / моделирования. Например, в физике для замкнутой системы полная энергия сохраняется. Или снова в физике, если две частицы сталкиваются, полученные фрагменты должны содержать точно ту энергию, с которой они начали, и точно такой же импульс (векторную величину). Обычно не хватает инвариантов, чтобы полностью указать результат. Например, в двухчастичном столкновении у нас есть четыре инварианта, три компонента импульса и компонент энергии, но система имеет шесть степеней свободы (шесть чисел, чтобы описать ее состояние). Инварианты должны быть сохранены с точностью до ошибки округления, но их сохранение не доказывает, что решение является правильным.
Поэтому, как правило, эти вещи важны как проверки работоспособности, но сами по себе они не могут доказать правильность.
источник