Skip to content

Latest commit

 

History

History
135 lines (80 loc) · 11.4 KB

File metadata and controls

135 lines (80 loc) · 11.4 KB

Лекция 15. 04.03.2022

Запись

Темы

  • Методологии программирования
    • Процедурное
    • Модульное
    • Объектное
    • Объектно-ориентированное
  • Объекты и классы
  • Принципы объектно-ориентированного программирования
    • Абстракция
    • Инкапсуляция
    • Иерархия
    • Модульность
    • Полиморфизм
    • Типизация
    • Параллелизм
    • Сохраняемость
  • Принципы объектно-ориентированного проектирования
    • Принцип единственности абстракции
    • Принцип инверсии зависимости
    • Принцип подстановки Лисковой
    • Принцип разделения интерфейсов
    • Принцип ацикличности зависимостей

Методологии программирования

Процедурная - когда нужно декомпозировать задачу на набор функций и реализовать их.

Модульная - когда программа определяется на какие-то составные компоненты, которые реализуют её (так в Python).

Объектная - когда есть какие-то объекты и мы их описываем (моделирование из реального мира), что позволяет нам мыслить в более человеческих терминах

Объектно-ориентированная - продолжение объектного, так как потребовалось обобщение этих объектов (на данный момент, самый распространённый подход).

Объекты и классы

Объектно-ориентированное программирование обеспечивает:

  • расширяемость системы (extensibility)
  • лёгкость поддержки системы в дальнейшем (maintainability)
  • создание переиспользуемых компонент (reusability)

Объект - сущность, обладающая идентичностью, поведением и состоянием.

Состояние является результатом суммарного поведения.

Класс это множество объектов с общим поведением и состоянием.

Принципы объектно-ориентированного программирования

Абстракция

Абстракция - это отделение существенных свойств объекта от несущественных. Не стоит путать с абстрактными классами.

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

Инкапсуляция

Инкапсуляция - это разделение интерфейса и реализации.

Интерфейс - контракт, определяющий, какие сообщения может принимать объект (= какие методы можно вызывать у нашего объекта / что можно делать с этим объектом). Контракт не зависит от реализации, что позволяет обеспечивать слабую связность между компонентами. Иначе говоря, чтобы поменять одну часть кода, не придётся переписывать весь код.

Иерархия

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

  • Иерархия наследования классов
  • Иерархия объектов
  • Иерархия модулей

Например:

Самолёт - Двигатель + Фюзеляж + Шасси + Крылья + Хвостовое оперенье.

Двигатель - цилиндр + система сжигания + стартер и т. д

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

Модульность

Модульность это разделение программы на тесно связанные внутри и слабо связанные снаружи модули

Полиморфизм

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

Типизация

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

В основном, в C++ статическая типизация (но присутствует и динамическая в виртуальном полиморфизме).

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

Параллелизм

Параллелизм - возможность иметь несколько активных объектов.

Сохраняемость

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

Принципы объектно-ориентированного проектирования

Принцип единственности абстракции

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

При нарушении данного принципа ваш код становится менее переиспользуемым, т. е появляется привязка к каким-то деталям (например, привязка только лишь к формату BMP в классе Image); добавляются лишние зависимости в коде.

Принцип инверсии зависимости

Модули высокого уровня не должны зависеть от модулей низкого. И те, и другие, должны зависеть от абстракций. Абстракции не должны зависеть от деталей реализации.

Принцип Деметера

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

Принцип подстановки Лисковой

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

Примером нарушения этого принципа является наследование квадрата от прямоугольника (в зависимости от типа, переданного в функцию для вычисления площади работало по-разному). В качестве самопроверки можно попробовать подставить какой-нибудь класс-наследник, вместо того, что вы ожидаете или dynamic_cast.

Принцип разделения интерфейсов

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

Принцип ацикличности зависимостей

Структура зависимостей между элементами (классами, пакетами, методами) должна представлять собой направленный ациклический граф**.**