Что такое инвариант в программировании
Перейти к содержимому

Что такое инвариант в программировании

  • автор:

12.2.7.1 Инварианты.

Значение членов или объектов, доступных с помощью членов класса, называется состоянием объекта (или просто значением объекта). Главное при построении класса — это: привести объект в полностью определенное состояние (инициализация), сохранять полностью определенное состояние обЪекта в процессе выполнения над ним различных операций, и в конце работы уничтожить объект без всяких последствий. Свойство, которое делает состояние объекта полностью определенным, называется инвариантом.

Поэтому назначение инициализации — задать конкретные значения, при которых выполняется инвариант объекта. Для каждой операции класса предполагается, что инвариант должен иметь место перед выполнением операции и должен сохраниться после операции. В конце работы деструктор нарушает инвариант, уничтожая объект. Например, конструктор String::String( const char *) гарантирует, что p указывает на массив из, по крайней мере, sz элементов, причем sz имеет осмысленное значение и v[sz-1]==0. Любая строковая операция не должна нарушать это утверждение.

При проектировании класса требуется большое искусство, чтобы сделать реализацию класса достаточно простой и допускающей наличие полезных инвариантов, которые несложно задать. Легко требовать, чтобы класс имел инвариант, труднее предложить полезный инвариант, который понятен и не накладывает жестких ограничений на действия разработчика класса или на эффективность реализации. Здесь «инвариант» понимается как программный фрагмент, выполнив который, можно проверить состояние объекта. Вполне возможно дать более строгое и даже математическое определение инварианта, и в некоторых ситуациях оно может оказаться более подходящим. Здесь же под инвариантом понимается практическая, а значит, обычно экономная, но неполная проверка состояния объекта.

Понятие инварианта появилось в работах Флойда, Наура и Хора, посвященных пред- и пост-условиям, оно встречается во всех важных статьях по абстрактным типам данных и верификации программ за последние 20 лет. Оно же является основным предметом отладки в C++.

Обычно, в течение работы функции-члена инвариант не сохраняется. Поэтому функции, которые могут вызываться в те моменты, когда инвариант не действует, не должны входить в общий интерфейс класса. Такие функции должны быть частными или защищенными.

Как можно выразить инвариант в программе на С++? Простое решение — определить функцию, проверяющую инвариант, и вставить вызовы этой функции в общие операции. Например:

class String < int sz; int* p; public: class Range <>; class Invariant <>; void check(); String(const char* q); ~String(); char& operator[](int i); int size() < return sz; > //. >; void String::check() < if (p==0 || szthrow Invariant; > char& String::operator[](int i) < check(); // проверка на входе if (ithrow Range; // действует check(); // проверка на выходе return v[i]; >

Этот вариант прекрасно работает и не осложняет жизнь программиста. Но для такого простого класса как String проверка инварианта будет занимать большую часть времени счета. Поэтому программисты обычно выполняют проверку инварианта только при отладке:

inline void String::check() < if (!NDEBUG) if (p==0 || szthrow Invariant; >

Мы выбрали имя NDEBUG, поскольку это макроопределение, которое используется для аналогичных целей в стандартном макроопределении С assert(). Традиционно NDEBUG устанавливается с целью указать, что отладки нет. Указав, что check() является подстановкой, мы гарантировали, что никакая программа не будет создана, пока константа NDEBUG не будет установлена в значение, обозначающее отладку. С помощью шаблона типа Assert() можно задать менее регулярные утверждения, например:

templateclass T, class X> inline void Assert(T expr,X x) < if (!NDEBUG) if (!expr) throw x; >

вызовет особую ситуацию x, если expr ложно, и мы не отключили проверку с помощью NDEBUG. Использовать Assert() можно так:

class Bad_f_arg < >; void f(String& s, int i) < Assert(0

Шаблон типа Assert() подражает макрокоманде assert() языка С. Если i не находится в требуемом диапазоне, возникает особая ситуация Bad_f_arg.

С помощью отдельной константы или константы из класса проверить подобные утверждения или инварианты - пустяковое дело. Если же необходимо проверить инварианты с помощью объекта, можно определить производный класс, в котором проверяются операциями из класса, где нет проверки, см. упр.8 в $$13.11.

Для классов с более сложными операциями расходы на проверки могут быть значительны, поэтому проверки можно оставить только для "поимки" трудно обнаруживаемых ошибок. Обычно полезно оставлять по крайней мере несколько проверок даже в очень хорошо отлаженной программе. При всех условиях сам факт определения инвариантов и использования их при отладке дает неоценимую помощь для получения правильной программы и, что более важно, делает понятия, представленные классами, более регулярными и строго определенными. Дело в том, что когда вы создаете инварианты, то рассматриваете класс с другой точки зрения и вносите определенную избыточность в программу. То и другое увеличивает вероятность обнаружения ошибок, противоречий и недосмотров. Мы указали в $$11.3.3.5, что две самые общие формы преобразования иерархии классов состоят в разбиении класса на два и в выделении общей части двух классов в базовый класс. В обоих случаях хорошо продуманный инвариант может подсказать возможность такого преобразования. Если, сравнивая инвариант с программами операций, можно обнаружить, что большинство проверок инварианта излишни, то значит класс созрел для разбиения. В этом случае подмножество операций имеет доступ только к подмножеству состояний объекта. Обратно, классы созрели для слияния, если у них сходные инварианты, даже при некотором различии в их реализации.

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.

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

Инвариант (программирование)

Инвариа́нтом в программировании называется логическое выражение, истинное после каждого прохода тела цикла (после выполнения фиксированного оператора) и перед началом выполнения цикла, зависящее от переменных, изменяющихся в теле цикла. [1]

Инварианты используются в теории верификации программ для доказательства правильности выполнения цикла. Порядок доказательства работоспособности цикла с помощью инварианта сводится к следующему:

  1. Доказывается, что выражение инварианта истинно перед началом цикла.
  2. Доказывается, что выражение инварианта сохраняет свою истинность после выполнения тела цикла; таким образом, по индукции, доказывается, что по завершении цикла инвариант будет выполняться.
  3. Доказывается, что при истинности инварианта после завершения цикла переменные примут именно те значения, которые требуется получить (это элементарно определяется из выражения инварианта и известных конечных значениях переменных, на которых основывается условие завершения цикла).
  4. Доказывается (возможно — без применения инварианта), что цикл завершится, то есть условие завершения рано или поздно будет выполнено.
  5. Истинность утверждений, доказанных на предыдущих этапах, однозначно свидетельствует о том, что цикл выполнится за конечное время и даст желаемый результат.

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

Понятие инварианта также используется в объектно-ориентированном программировании для обозначения непротиворечивого состояния объекта. Подразумевается, что вызов любого метода оставляет объект в состоянии инварианта.

Примечания

  1. Построение цикла с помощью инварианта
  • Формальные методы

Wikimedia Foundation . 2010 .

  • Инвариант (математика)
  • Инвариант (физика)

Полезное

Смотреть что такое "Инвариант (программирование)" в других словарях:

  • Инвариант — или инвариантность термин, обозначающий нечто неизменяемое. Конкретное значение термина зависит от той области, где он используется: Инвариант (математика) Инвариант узла в топологии Инвариант (физика) Инвариант (программирование) Инвариант … Википедия
  • ПРОГРАММИРОВАНИЕ ТЕОРЕТИЧЕСКОЕ — математическая дисциплина, изучающая математич. абстракции программ, трактуемых как объекты, выраженные на формальном языке, обладающие определенной информационной и логич. структурой и подлежащие исполнению на автоматич. устройствах. П. т.… … Математическая энциклопедия
  • Конструктор (программирование) — У этого термина существуют и другие значения, см. Конструктор. В объектно ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) специальный блок инструкций, вызываемый при создании объекта.… … Википедия
  • ДРАКОН — Эта статья предлагается к удалению. Пояснение причин и соответствующее обсуждение вы можете найти на странице Википедия:К удалению/28 сентября 2012. Пока процесс обсуждения не завершён, статью мож … Википедия
  • ДРАКОН (алгоритмический язык) — У этого термина существуют и другие значения, см. Дракон (значения). Пример блок схемы алгоритма на языке ДРАКОН дракон схемы ДРАКОН (Дружелюбный Русский Алгоритмический язык, Который Обеспечивает Наглядность) визуальный… … Википедия
  • Конструктор класса — В объектно ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) специальный блок инструкций, вызываемый при создании объекта, причём или при его объявлении (располагаясь в стеке или в статической… … Википедия
  • Конструктор объекта — В объектно ориентированном программировании конструктор класса (от англ. constructor, иногда сокращают ctor) специальный блок инструкций, вызываемый при создании объекта, причём или при его объявлении (располагаясь в стеке или в статической… … Википедия
  • Ковариантность и контравариантность — Ковариантность и контравариантность математическое и физическое понятие, которое описывает то, как величины изменяются при преобразовании системы координат. Координаты геометрического вектора измеряются в какой нибудь конкретной системе… … Википедия
  • КУЛЬТУРА — (лат. cultura возделывание, воспитание, почитание) универсум искусственных объектов (идеальных и материальных предметов; объективированных действий и отношений), созданный человечеством в процессе освоения природы и обладающий структурными,… … Философская энциклопедия
  • Шаблон — О шаблонах в Википедии смотрите страницу Википедия:Шаблоны. Шаблон в технике пластина (лекало, трафарет и т. п.) с вырезами, по контуру которых изготовляются чертежи или изделия либо инструмент для измерения размеров. Шаблон в… … Википедия
  • Обратная связь: Техподдержка, Реклама на сайте
  • �� Путешествия

Экспорт словарей на сайты, сделанные на PHP,
WordPress, MODx.

  • Пометить текст и поделитьсяИскать в этом же словареИскать синонимы
  • Искать во всех словарях
  • Искать в переводах
  • Искать в ИнтернетеИскать в этой же категории

Инвариант класса - Class invariant

В компьютерном программировании, в частности, объектно-ориентированном программировании, класс инвариант (или инвариант типа ) - это инвариант, используемый для ограничения объектов из класса. Методы класса должны сохранять инвариант. Инвариант класса ограничивает состояние, хранящееся в объекте.

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

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

  • 1 Инварианты классов и наследование
  • 2 Поддержка языков программирования
    • 2.1 Утверждения
    • 2.2 Встроенная поддержка
    • 2.3 Ненативная поддержка
    • 3.1 Нативная поддержка
      • 3.1.1 D
      • 3.1.2 Eiffel
      • 3.2.1 C ++
      • 3.2.2 Java

      Инварианты классов и наследование

      Полезный эффект инвариантов классов в объектно-ориентированном ПО усиливается при наличии наследования. Инварианты классов наследуются, то есть «инварианты всех родителей класса применяются к самому классу».

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

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

      Поддержка языков программирования

      Утверждения

      Общие языки программирования, такие как Python, JavaScript, C ++ и Java, по умолчанию поддерживают утверждения, которые можно использовать для определения инварианты классов. Обычный шаблон для реализации инвариантов в классах состоит в том, что конструктор класса генерирует исключение, если инвариант не выполняется. Поскольку методы сохраняют инварианты, они могут предполагать действительность инварианта и не должны явно проверять его.

      Встроенная поддержка

      Инвариант класса является важным компонентом проектирования по контракту. Итак, языки программирования, которые обеспечивают полную нативную поддержку дизайна по контракту, например Rust, Eiffel, Ada и D, также будет обеспечивать полную поддержку инвариантов классов.

      Неродная поддержка

      Для C ++ Loki Library предоставляет основу для проверки инвариантов классов, инвариантов статических данных и безопасности исключений.

      Для Java существует более мощный инструмент под названием Java Modeling Language, который обеспечивает более надежный способ определения инвариантов классов.

      Примеры

      Встроенная поддержка

      D

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

      class Date = 1 day = 0 hour >
      Eiffel

      В Eiffel инвариант класса появляется в конце класса после ключевое слово инвариант .

      class DATE create make feature - Инициализация make (a_day: INTEGER; a_hour: INTEGER) - Инициализировать `Current 'с помощью ʻa_day' и ʻa_hour '. require valid_day: a_day>= 1 и a_day = 0 и a_hour = 1 и a_day = 0 и a_hour = 1 и day = 0 и hour 
      

      Поддержка неродных версий

      C ++

      Библиотека Loki (C ++) предоставляет платформу, написанную для проверки инвариантов классов, инвариантов статических данных и уровня безопасности исключений.

      Это пример того, как класс может использовать Loki :: Checker для проверки того, что инварианты остаются верными после изменения объекта. В этом примере объект географической точки используется для сохранения местоположения на Земле в качестве координат широты и долготы.

      • широта не может быть больше 90 ° северной широты.
      • широта не может быть оставлена ss, чем -90 ° южной широты.
      • долгота не может быть больше 180 ° восточной долготы.
      • долгота не может быть меньше -180 ° западной долготы.
      #include // Требуется для проверки инвариантов классов. #include class GeoPoint = 90,0) широта_ = 90,0; если (широта_ = 180,0) долгота_ - = 360,0; while (longitude_ private: /** @note CheckFor performs validity checking in many functions to determine if the code violated any invariants, if any content changed, or if the function threw an exception. */ using CheckFor = ::Loki::CheckFor; /// Эта функция проверяет все инварианты объекта. bool IsValid () const = -90.0); assert (latitude_ = -180.0) ; assert (longitude_ Degrees latitude_; ///< Degrees from equator. Positive is north, negative is ///< south. Degrees longitude_; ///< Degrees from Prime Meridian. Positive is east, ///
      Java

      Это пример инварианта класса в языке программирования Java с языком моделирования Java. Инвариант должен сохраняться, чтобы Значение true после завершения работы конструктора и при входе и выходе всех общедоступных функций-членов. Открытые функции-члены должны определять предварительное условие и постусловие, чтобы обеспечить инвариант класса.

      открытый класс Дата = 1 день = 0 час = 1 d = 0 h /*@ @requires d>= 1 d /*@ @requires h>= 0 h >

      Инварианты — Python: Абстракция с помощью данных

      Абстракция позволяет нам не думать о деталях реализации и сосредоточиться на ее использовании. Также при необходимости реализацию абстракции можно всегда переписать и не бояться сломать использующий ее код. Но есть еще одна важная причина, по которой нужно использовать абстракцию — соблюдение инвариантов.

      В этом уроке мы познакомимся с инвариантами, нормализацией и понятием data hiding.

      Инварианты

      Инвариант в программировании — логическое выражение, которое определяет непротиворечивость состояния — набора данных.

      Разберемся на примере. Когда мы описали конструктор и селекторы для рациональных чисел, то неявно подразумевали выполнение следующих инвариантов:

      num = make_rational(numer, denom) numer == get_numer(num) # True denom == get_denom(num) # True 

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

      Инварианты существуют относительно любой операции. И иногда они довольно хитрые. Например, рациональные числа можно сравнивать между собой, но не прямым способом. Одни и те же дроби можно представлять разными способами: 1/2 и 2/4. Код, который не учитывает этого факта, работает некорректно:

      num1 = make_rational(2, 4) num2 = make_rational(8, 16) num1 == num2 # False 

      Нормализация

      Задача приведения дроби к нормальной форме называется нормализацией. Реализовать ее можно разными способами. Самый очевидный — выполнять нормализацию во время создания дроби, внутри функции make_rational . Другой — выполнять нормализацию уже при обращении через функции get_numer и get_denom .

      Последний способ обладает недостатком — вычисление нормальной формы происходит на каждый вызов. Избежать этого можно с помощью техники мемоизация.

      Учитывая новые вводные, становится понятно, что инвариант, который связывает конструктор и селекторы, нуждается в модификации. Функции get_numer и get_denom должны вернуть не переданные значения, а значения после нормализации:

      num = make_rational(10, 20) get_numer(num) # 1 get_denom(num) # 2 

      Если дробь уже нормализована, то это будут те же самые значения.

      Абстракция не только прячет от нас реализацию, но и отвечает за соблюдение инвариантов. Если работать в обход абстракции, то внутренние преобразования не будут учтены:

      # Обход конструктора # Эти данные не нормализованы, # потому что не использовался конструктор num = "numer": 10, "denom": 20> # Возвращается не то, что должно # (ожидается нормализованный возврат) get_numer(num) # 10 get_denom(num) # 20 # Прямая модификация num = make_rational(10, 20) # Тут не может быть нормализации, # так как прямое изменениe num['numer'] = 40 get_numer(num) # 40 get_denom(num) # 20 

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

      Сокрытие данных

      Можно сделать так, чтобы обойти абстракцию было нельзя. Такой подход называют сокрытием данных — data hiding.

      Чтобы обеспечить сокрытие, в языках используется специальный синтаксис. Однако защиту данных можно организовать и без специальных средств, только за счет функций высшего порядка. Такой способ основан на создании абстракций с помощью анонимных функций, замыканий и передачи сообщений. Если вы хотите узнать об этом больше, то пройдите курс Python: Составные данные.

      В реальности подобные механизмы легко обходятся с помощью Reflection API. Это можно сделать даже без них — за счет ссылочных данных. Также есть немало языков, например, JavaScript, в которых все нормально с абстракциями, но нет механизмов для защиты данных. При этом ничего страшного не произошло.

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

      Открыть доступ

      Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

      • 130 курсов, 2000+ часов теории
      • 1000 практических заданий в браузере
      • 360 000 студентов

      Наши выпускники работают в компаниях:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *