hard

Объектно-ориентированное программирование: на пальцах

Статья не мальчика, но мужа.

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

Из этого термина можно сделать вывод, что ООП — это такой подход к программированию, где на первом месте стоят объекты. На самом деле там всё немного сложнее, но мы до этого ещё доберёмся. Для начала поговорим про ООП вообще и разберём, с чего оно начинается.

Обычное программирование (процедурное)

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

Объектно-ориентированное программирование: на пальцах

Например, в интернет-магазине может быть функция «Проверить email». Она получает на вход какой-то текст, сопоставляет со своими правилами и выдаёт ответ: это правильный электронный адрес или нет. Если правильный, то true, если нет — то false.

Объектно-ориентированное программирование: на пальцах

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

Что не так с процедурным программированием

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

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

Объектно-ориентированное программирование: на пальцах

Тут приходит продакт-менеджер и говорит: «Хочу, чтобы пользователь точно знал, в чём ошибка при вводе электронного адреса». Теперь вам нужно научить функцию выдавать не просто true — false, а ещё и код ошибки: например, если в адресе опечатка, то код 01, если адрес спамерский — код 02 и так далее. Это несложно реализовать.

Вы залезаете внутрь этой функции и меняете её поведение: теперь она вместо true — false выдаёт код ошибки, а если ошибки нет — пишет «ОК».

И тут ваш код ломается: все десять мест, которые ожидали от проверяльщика true или false, теперь получают «ОК» и из-за этого ломаются.

Объектно-ориентированное программирование: на пальцах

Теперь вам нужно:

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

Задача, конечно, решаемая за час-другой.

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

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

Объектно-ориентированное программирование: на пальцах

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

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

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

Объектно-ориентированное программирование: на пальцах

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

Объект можно представить как независимый электроприбор у вас на кухне. Чайник кипятит воду, плита греет, блендер взбивает, мясорубка делает фарш. Внутри каждого устройства куча всего: моторы, контроллеры, кнопки, пружины, предохранители — но вы о них не думаете. Вы нажимаете кнопки на панели каждого прибора, и он делает то, что от него ожидается. И благодаря совместной работе этих приборов у вас получается ужин.

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

Инкапсуляция — объект независим: каждый объект устроен так, что нужные для него данные живут внутри этого объекта, а не где-то снаружи в программе. Например, если у меня есть объект «Пользователь», то у меня в нём будут все данные о пользователе: и имя, и адрес, и всё остальное. И в нём же будут методы «Проверить адрес» или «Подписать на рассылку».

Абстракция — у объекта есть «интерфейс»: у объекта есть методы и свойства, к которым мы можем обратиться извне этого объекта. Так же, как мы можем нажать кнопку на блендере. У блендера есть много всего внутри, что заставляет его работать, но на главной панели есть только кнопка. Вот эта кнопка и есть абстрактный интерфейс.

В программе мы можем сказать: «Удалить пользователя». На языке ООП это будет «пользователь.удалить()» — то есть мы обращаемся к объекту «пользователь» и вызываем метод «удалить». Кайф в том, что нам не так важно, как именно будет происходить удаление: ООП позволяет нам не думать об этом в момент обращения.

Например, над магазином работают два программиста: один пишет модуль заказа, а второй — модуль доставки. У первого в объекте «заказ» есть метод «отменить». И вот второму нужно из-за доставки отменить заказ. И он спокойно пишет: «заказ.отменить()». Ему неважно, как другой программист будет реализовывать отмену: какие он отправит письма, что запишет в базу данных, какие выведет предупреждения.

Объектно-ориентированное программирование: на пальцах

Наследование — способность к копированию. ООП позволяет создавать много объектов по образу и подобию другого объекта. Это позволяет не копипастить код по двести раз, а один раз нормально написать и потом много раз использовать.

Например, у вас может быть некий идеальный объект «Пользователь»: в нём вы прописываете всё, что может происходить с пользователем. У вас могут быть свойства: имя, возраст, адрес, номер карты. И могут быть методы «Дать скидку», «Проверить заказ», «Найти заказы», «Позвонить».

На основе этого идеального пользователя вы можете создать реального «Покупателя Ивана». У него при создании будут все свойства и методы, которые вы задали у идеального покупателя, плюс могут быть какие-то свои, если захотите.

Идеальные объекты программисты называют классами.

Полиморфизм — единый язык общения. В ООП важно, чтобы все объекты общались друг с другом на понятном им языке. И если у разных объектов есть метод «Удалить», то он должен делать именно это и писаться везде одинаково. Нельзя, чтобы у одного объекта это было «Удалить», а у другого «Стереть».

При этом внутри объекта методы могут быть реализованы по-разному. Например, удалить товар — это выдать предупреждение, а потом пометить товар в базе данных как удалённый. А удалить пользователя — это отменить его покупки, отписать от рассылки и заархивировать историю его покупок. События разные, но для программиста это неважно. У него просто есть метод «Удалить()», и он ему доверяет.

Объектно-ориентированное программирование: на пальцах

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

Плюсы и минусы ООП

У объектно-ориентированного программирования много плюсов, и именно поэтому этот подход использует большинство современных программистов.

  1. Визуально код становится проще, и его легче читать. Когда всё разбито на объекты и у них есть понятный набор правил, можно сразу понять, за что отвечает каждый объект и из чего он состоит.
  2. Меньше одинакового кода. Если в обычном программировании одна функция считает повторяющиеся символы в одномерном массиве, а другая — в двумерном, то у них большая часть кода будет одинаковой. В ООП это решается наследованием.
  3. Сложные программы пишутся проще. Каждую большую программу можно разложить на несколько блоков, сделать им минимальное наполнение, а потом раз за разом подробно наполнить каждый блок.
  4. Увеличивается скорость написания. На старте можно быстро создать нужные компоненты внутри программы, чтобы получить минимально работающий прототип.

А теперь про минусы:

  1. Сложно понять и начать работать. Подход ООП намного сложнее обычного процедурного программирования — нужно знать много теории, прежде чем будет написана хоть одна строчка кода.
  2. Требует больше памяти. Объекты в ООП состоят из данных, интерфейсов, методов и много другого, а это занимает намного больше памяти, чем простая переменная.
  3. Иногда производительность кода будет ниже. Из-за особенностей подхода часть вещей может быть реализована сложнее, чем могла бы быть. Поэтому бывает такое, что ООП-программа работает медленнее, чем процедурная (хотя с современными мощностями процессоров это мало кого волнует).

Что дальше

Впереди нас ждёт разговор о классах, объектах и всём остальном важном в ООП. Крепитесь, будет интересно!

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать бесплатно
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
Блокировщик соцсетей, который спасёт вашу продуктивность

И поднимет осознанность.

easy
10 полезных CSS-свойств и инструментов для их создания
10 полезных инструментов для создания роскошного CSS

В копилку всем, кто делает сайты.

medium
Задача про соседских тараканов
Задача про соседских тараканов

Простая математика, но непростая логика. Проверьте, получится ли у вас.

easy
Что под капотом у ChatGPT и других чатов с большими языковыми моделями
Что под капотом у ChatGPT и других чатов с большими языковыми моделями

Почему это работает так хорошо

hard
5 навыков, которые нужны программисту на базовом уровне
5 навыков, которые нужны программисту на базовом уровне

Помогут вырасти и в профессии, и в карьере

easy
Плюс в кружке — что он означает в математике
Плюс в кружке — что он означает в математике

У айтишников есть своё толкование

easy
Как быстро освоить новую технологию
Как быстро освоить новую технологию

Пробуем метод разработчика из Яндекс.Практикума.

Нужно ли вам учить Swift?

Что особенного в этом языке и чем он выгоден.

easy
Что такое куки

8 вопросов, которые вы всегда хотели задать, но боялись куки.

easy
hard