Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

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

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос нашим менторам. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Инварианты

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

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

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

>>> 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

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

Хочу сразу предостеречь вас от следования культу карго. Несмотря на то, что идея с защитой данных выглядит очень здраво, в реальности подобные механизмы крайне легко обходятся с помощью Reflection API и даже без них, просто за счёт ссылочных данных. Поэтому подобная защита — она больше "от дурака". Второй момент связан с тем, что в мире немало языков (пример, JavaScript), в которых всё нормально с абстракциями, но нет механизмов для защиты данных — и ничего страшного не произошло. Другими словами, на практике, при использовании абстракций, никто особо и не пытается их нарушать специально. И я склоняюсь к мысли, что значение принудительной защиты данных сильно преувеличено.


<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят менторы из команды Хекслета или другие студенты.

Для полного доступа к курсу, нужна профессиональная подписка

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

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

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

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».

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

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Нажимая кнопку «Зарегистрироваться», вы даёте своё согласие на обработку персональных данных в соответствии с «Политикой конфиденциальности» и соглашаетесь с «Условиями оказания услуг».