Плюсы, минусы и перспективы ООП в современной разработке
Авторизуйтесь
Плюсы, минусы и перспективы ООП в современной разработке
Директор Exiting Vim, амбассадор всероссийского конкурса для IT-специалистов «Цифровой прорыв» — флагманского проекта президентской платформы «Россия — страна возможностей».
Давайте применим концепцию MVP к рассмотрению объектно-ориентированного программирования, а чтобы не быть субъективными, также взглянем на функциональное и прототипное программирование. Прежде всего, интересно, что разработано на них. А также какие перспективы ждут разработчиков — то есть количество открытых вакансий на рынке труда.
Прототипные языки программирования
Императивная парадигма, где реализация программного продукта осуществляется за счет оперирования иерархиями объектов. Это полезно для компактных программ с небольшим объёмом кода.
Самая известная реализация прототипной спецификации ECMAScript — язык JavaScript. Традиционная его ниша — фронтенд. Но с недавних пор ведётся также активная разработка на этом языке и бэкенд-решений.
Вот как выглядит поиск по вакансиям программистов на прототипных языках:
Функциональные языки программирования
Декларативная парадигма программирования, которая строится на функциях, что удобно для параллельной и распределенной разработки. Программам, написанным с использованием данной парадигмы, свойственны такие свойства, как высокая степень параллелизации вычислений, повышенные требования к производительности и надежности.
Haskell применяется в финансовом программировании, при анализе рисков, в системах поддержки принятия решений. Erlang применяется в телекоммуникациях.
Смотрим вакансии (кстати, уровень зарплаты по ним выше среднего):
Объектно-ориентированное программирование
Императивная парадигма, где реализация программного продукта осуществляется за счёт оперирования иерархиями классов и объектов. Базируется на таких подходах, как полиморфизм, инкапсуляция, абстракция и наследование.
Всё построено на повторном использовании кода, что ускоряет разработку. Кроме того, найти программистов на ООП несложно, потому что это очень развитый рынок — и в продуктовом, и в HR-смыслах. Это хорошо видно по количеству вакансий:
ООП используется при написании операционных систем, СУБД, компиляторов, драйверов, множества прикладных программ. Например, достаточно сказать, что почти все известные браузеры, Microsoft Office, Adobe Photoshop и Illustrator — продукты объектно-ориентированного программирования.
Похоже, его рано списывать со счетов. Однако многие критикуют ООП. Какие претензии предъявляют очевидному лидеру, чем он не угодил?
Критика объектно-ориентированного программирования
ООП не раз подвергалось критике. Одно из самых ярких обвинений прозвучало от британского программиста — Джо Армстронга.
Проблема с объектно-ориентированными языками заключается в том, что у них есть вся эта неявная среда, которую они носят с собой. Вы хотели банан, но получили гориллу, держащую банан и все джунгли.
Это во многом справедливо. Помимо недостаточно качественной поддержки параллельных и распределенных систем, ООП отличается относительно низким качеством конечного продукта.
В процессе трансляции объектно-ориентированных программ в исполняемый код центрального процессора возникает ряд неоптимальностей по использованию памяти и вычислительного времени процессорных ядер.
ООП предоставляет вам множество способов замедлить работу ваших программ.
А небезызвестный Линус Торвальдс часто критиковал ООП и С++ в частности, упоминая в том числе отсутствие ограничений. Речь о том, что большое количество инструментов и методов позволяет добиваться функционально одинаковых реализаций множеством различных способов. Это можно было бы считать преимуществом, но появляется риск ошибок, обнаружить которые очень сложно. Наследование объектов может привести к тому, что баг «вылезет» в неожиданном месте, далеко от исходной неточности в описании «родителя».
Как же получилось, что такой уязвимый, избыточный, громоздкий подход к программированию стал основным в глобальном масштабе и до сих пор сохранил свои позиции?
Преимущества объектно-ориентированного программирования
Первые программы на языках программирования высокого уровня, по сути, не были структурированы, и это не вызывало проблем, потому что объёмы кода были, по современным меркам, ничтожны. Кроме того, тогда ещё не существовало репозитариев, не было интернета, и тиражирование исходных кодов программных продуктов было крайне затруднительным.
По мере того, как наперегонки развивались Hardware и Software, объёмы исходных кодов в программах начали стремительно расти. Теперь для его поддержки уже требовалась определенная архитектура. Стали применяться различные подходы к оформлению исходных кодов, и в конечном счёте появились парадигмы программирования. ООП выделялось сразу несколькими критично важными отличиями:
Повторяемость кода ООП привела к созданию библиотек классов. Можно тратить всё меньше времени на получение уже полученных ранее результатов — причём даже не очень важно, кем именно и на каких проектах были сделаны прежние разработки. Так и начал формироваться парадокс банана: с одной стороны — упрощение разработки за счёт тиражирования уже реализованных классов. С другой — неоптимальное использование аппаратных ресурсов.
В ходе развития программного продукта могут потребоваться расширения и дополнения, уже реализованные в подключенных библиотеках, и тогда остаётся только их задействовать. Нечто похожее сейчас используется во многих коммерческих продуктах, причём не только софтверных.
Сама идея «разработки про запас» довольно удобна с точки зрения продаж. Как и выбор высокого темпа вместо перфекционизма в качестве кода. Лучше продать сегодня и сдать проект завтра, чем растянуть всё на годы и вылететь с рынка.
При всех своих недостатках объектно-ориентированное программирование позволяет быстрее, экономичнее и гораздо удобнее в плане управления процессом распределённой разработки получать работающий код. Да, возможно, в нём есть значительные неоптимальности, возможно их даже много. Но зато проект уже работает, по крайней мере, в виде прототипа. Этого достаточно для презентаций, получения первых клиентов и внедрений.
Всё равно первоначальные маркетинговые, интерфейсные и многие другие идеи придётся ещё неоднократно дорабатывать, а возможно, и менять. С точки зрения компании и особенно стартапа, выгоднее двигаться быстрее.
Резюме
В нулевых годах начали массово распространяться многоядерные и многопроцессорные системы. Возникла потребность в распределенных вычислениях, а чуть позже в вычислениях на графических процессорах. Оказалось, что ООП справляется с такими задачами значительно хуже, чем функциональные программы. Даже исходя из одного этого фактора, можно усомниться в бесконечном доминировании ООП.
Конечно, пропорции в разработке будут меняться. Это уже происходит. Кроме того, рано или поздно появятся принципиально другие, новые подходы — и они могут оказаться недостижимо более производительными, особенно на модернизированном железе.
Тем не менее, пока что ООП остается надёжным, удобным инструментом. Похоже, в ближайшие годы ничего не предвещает серьезных подвижек, так что можно смело использовать объектно-ориентированное программирование и в качестве личного карьерного плана, и для запуска проектов.
Основы объектно-ориентированного программирования
Достоинства ООП
От любой методики разработки программного обеспечения мы ждем, что она поможет нам в решении наших задач. Но одной из самых значительных проблем проектирования является сложность. Чем больше и сложнее программная система, тем важнее разбить ее на небольшие, четко очерченные части. Чтобы справиться со сложностью, необходимо абстрагироваться от деталей. В этом смысле классы представляют собой весьма удобный инструмент.
Полиморфизм оказывается полезным преимущественно в следующих ситуациях.
Часто многоразового использования программного обеспечения не удается добиться из-за того, что существующие компоненты уже не отвечают новым требованиям. ООП помогает этого достичь без нарушения работы уже имеющихся компонентов, что позволяет извлечь максимум из многоразового использования компонентов.
Недостатки ООП
Методы, как правило, короче процедур, поскольку они осуществляют только одну операцию над данными, зато их намного больше. В коротких методах легче разобраться, но они неудобны тем, что код для обработки сообщения иногда «размазан» по многим маленьким методам.
Многие считают, что ООП является неэффективным. Как же обстоит дело в действительности? Мы должны проводить четкую грань между неэффективностью на этапе выполнения, неэффективностью в смысле распределения памяти и неэффективностью, связанной с излишней универсализацией.
Неэффективность на этапе выполнения. В языках типа Smalltalk сообщения интерпретируются во время выполнения программы путем осуществления их поиска в одной или нескольких таблицах и за счет выбора подходящего метода. Конечно, это медленный процесс. И даже при использовании наилучших методов оптимизации Smalltalk-программы в десять раз медленнее оптимизированных C-программ.
В гибридных языках типа Oberon-2, Object Pascal и C++ отправка сообщения приводит лишь к вызову через указатель процедурной переменной. На некоторых машинах сообщения выполняются лишь на 10% медленнее, чем обычные процедурные вызовы. И поскольку сообщения встречаются в программе гораздо реже других операций, их воздействие на время выполнения влияния практически не оказывает.
Излишняя универсальность. Неэффективность также может означать, что в программе реализованы избыточные возможности. В библиотечном классе часто содержится больше методов, чем это реально необходимо. А поскольку лишние методы не могут быть удалены, они становятся мертвым грузом. Это не влияет на время выполнения, но сказывается на размере кода.
Заключение
Что выбрать: функциональное программирование или ООП?
Достоинства функционального программирования (FP) и объектно-ориентированного программирования (ООП) кажутся бесконечными спорами на любом техническом онлайн-форуме. Хотя сложно сказать однозначно, какой из них лучше, вы можете оценить их различия, чтобы увидеть, какой из них лучше.
Функциональное и объектно-ориентированное программирование: чем они отличаются?
Объектно-ориентированное программирование и функциональное программирование преследуют одну и ту же цель — разрабатывать гибкие программы, которые легко понять и не содержат ошибок. Но они основаны на разных подходах.
Объектно-ориентированного программирования
ООП — это парадигма, основанная на идее «объектов», содержащих данные в форме полей, часто называемых атрибутами; и код в форме процедур, часто называемых методами. Объектно-ориентированное программирование утверждает, что упрощает понимание того, как работает программа, объединяя данные и связанное с ними поведение в одном месте (называемом «объектом»).
Объектно-ориентированное программирование основывается на четырех ключевых принципах:
Объектно-ориентированное программирование эффективно, если у вас есть фиксированная серия операций над вещами, и по мере добавления новых вещей ваш код развивается. Однако вы не сможете легко определить, есть ли у объекта вызванная функция, если не отследите, произошло ли это с самого начала.
Функциональное программирование
FP — это процесс создания программного обеспечения путем составления чистых функций. Все объекты неизменяемы, а это означает, что однажды созданное не может быть изменено. Функциональное программирование утверждает, что данные и поведение — разные вещи и для ясности их следует разделять.
FP основывается на шести концепциях:
Ключевые отличия
Плюсы и минусы объектно-ориентированного программирования
Плюсы
ООП так популярно, потому что позволяет защитить вещи от нежелательного внешнего использования. Он скрывает переменные внутри класса и, таким образом, предотвращает доступ извне. Кроме того, ООП допускает модульность (возможность разделения функций программы на независимые модули) и управление общими состояниями.
Объекты можно легко повторно использовать в другом приложении. Легко создавать новые объекты для одного и того же класса, легко поддерживать и изменять код.
В ООП есть управление памятью. Это дает большое преимущество, когда дело доходит до создания больших программ, поскольку позволяет легко разделять вещи на более мелкие части и помогает различать компоненты, которые необходимо выполнить определенным образом.
Минусы
ООП нельзя использовать повторно. Поскольку некоторые функции зависят от класса, который их использует, их трудно использовать с другим классом. Кроме того, он менее эффективен, и с ним сложнее справиться. Многие объектно-ориентированные программы также предназначены для моделирования массивных архитектур и могут быть сложными.
Плюсы и минусы функционального программирования
Плюсы
FP предлагает такие преимущества, как ленивое вычисление, код без ошибок, вложенные функции, параллельное программирование. Он использует более декларативный подход, который концентрируется на том, что нужно сделать, и меньше на том, как это делать, с упором на эффективность и оптимизацию.
В функциональном программировании гораздо проще узнать, какие изменения были внесены, поскольку сам объект теперь является новым объектом с другим именем. Это эффективно, когда у вас есть фиксированный набор операций, и по мере развития вашего кода вы добавляете новые операции к существующим вещам.
Он хорошо работает, когда границы либо не требуются, либо уже предопределены. Это наиболее полезно в ситуациях, когда состояние не является фактором и переменные данные практически не задействованы.
В функциональном программировании проще моделировать реальные процессы, чем объекты. Его математическое происхождение делает его подходящим для случаев, требующих вычислений или всего, что включает преобразование и обработку. ООП в таких случаях будет неэффективным.
Минусы
FP — это манипулирование данными, и для написания кода требуется другое мышление. Хотя легко мыслить объектно-ориентированными терминами, преобразование реального сценария в простой потребует дополнительных умственных усилий.
Поскольку ФП труднее выучить, меньше людей программируют таким образом и, следовательно, естественно меньше информации по теме.
Какая из них лучше?
Очевидно, что разработчики ООП утверждают, что ООП — лучший подход к разработке программного обеспечения, в то время как команды FP утверждают, что FP лучше.
Хотя и объектно-ориентированное программирование, и функциональное программирование являются важными парадигмами. Преследующими одну и ту же цель разработки понятных программ без ошибок, их подходы различны. ООП следует модели императивного программирования, основанной на наборе примитивов, предоставляемых языком программирования. FP, с другой стороны, тесно связан с декларативным стилем, который подразумевает, что вы определяете только то, что необходимо выполнить, не указывая, как это сделать.
Похоже, что все согласны с тем, что ООП и ФП эффективны в любой конкретной ситуации, поэтому разработчики всегда должны выбирать парадигму программирования, которая делает процесс продуктивным и простым. Даже в этом случае мы не услышим в ближайшее время об окончании этих дебатов.
Что такое объектно-ориентированное программирование
Рассказываю об одной из важнейших парадигм в программировании.
Парадигмы программирования и их виды
Парадигма разработки – это набор правил и критериев, соблюдаемых разработчиками, чтобы выдержать конкретную стилистику и модель написания кода.
Единая парадигма помогает избегать ошибок, упрощает работу в команде и ускоряет разработку. Ориентируясь на одну парадигму, можно корректно структурировать код приложения, зная четкие правила, выбранные командой, которая работает над конкретным проектом.
Существуют различные типы парадигм, например процедурный, ориентированный на работу с функциями, или логический, подразумевающий решение базовых логических задач в духе «если А = true, то и B = true». Но есть и более интересный подход к решению задач разработки, и это ООП-парадигма.
Что такое ООП?
Объектно-ориентированное программирование, ООП – это одна из парадигм разработки, подразумевающая организацию программного кода, ориентируясь на данные и объекты, а не на функции и логические структуры.
Обычно объекты в подобном коде представляют собой полноценные блоки с данными, которые имеют определенный набор характеристик и возможностей. Объект может олицетворять что угодно – от человека с именем, фамилией, номером телефона, паролем и другой информацией до мелкой утилиты с минимумом характеристик из реального мира, но увеличенным набором функций. Объекты могут взаимодействовать друг с другом, пользователем и любыми другими компонентами программы.
ООП заставляет разработчиков фокусироваться на объектах, которыми нужно манипулировать, а не на той логике, что позволяет изменять данные и как-то с ними взаимодействовать. Такой подход хорошо работает в случае с комплексными программными решениями, требующими постоянной поддержки со стороны большого числа программистов.
Структура объектно-ориентированного программирования
Программный код, написанный с учетом принципов ООП, четко структурируется на 4 основных элементах (иногда выделяют и больше, включая в список элементов модули и другие структуры, связанные с объектно-ориентированной парадигмой, но мы обратимся к ним позже, говоря о преимущества и принципах описываемой модели).
Объекты
И хотя в структуре ООП объекты находятся не на первом месте, мы начнем с них, так как это упрощает общее понимание парадигмы.
Объект – это кусок кода, описывающий элемент с конкретным набором характеристик и функций. Например, вы делаете видеоигру, в которой есть персонаж. Ваш герой.
Этот персонаж в коде может быть отдельным объектом с такими характеристиками, как здоровье, сила, выносливость, ловкость и урон, а также функциями (методами) – это могут быть магические способности или особые приемы, используемые персонажем.
Объекты могут описывать других персонажей и средства передвижения.
Методы
Методы – это функции, описанные внутри объекта или класса. Они относятся к конкретному объекту и позволяют взаимодействовать с ними или другими частями кода. Выше мы уже затронули «способности» персонажа-объекта, вот они и являются наиболее понятным описанием методов. Когда ваш персонаж выполняет действие в игре, он задействует метод, описанный в его объекте.
Атрибуты
Атрибуты – это конкретные характеристики объекта. Если вы хоть немного знакомы с программированием, то атрибуты можно представить в виде переменных с данными. Вернувшись к примеру с игровым персонажем, в качестве атрибутов можно представить характеристики в духе уровня выносливости, скорости и других статических показателей.
Классы
Это наиболее абстрактная и обобщенная форма в ООП. Что-то в духе шаблона, на базе которого строятся другие элементы структуры кода.
Снова поясню на примере игры. В какой-нибудь онлайн-РПГ может быть куча разных героев: воины, лучники, люди, орки. Описывать каждого по отдельности сложно и нецелесообразно, ведь у них много общих характеристик и методов.
Поэтому мы можем создать класс – то есть объект, способный стать базой для других объектов. Например, класс – персонаж. Он умеет ходить, драться, имеет характеристики наподобие уровня здоровья или количества маны, то есть атрибуты, что есть у любых рас и классов в нашей РПГ. А уже человек-воин (объект) с ником Nagibator777 будет содержать более специфичные характеристики и методы, зависящие от решений игрока и других внешних факторов. Класс – это пример абстракции и наследования, упрощающий генерацию новых объектов.
На картинках и схемах эта структура выглядит куда понятнее.
Ключевые принципы ООП
Объектно-ориентированное программирование исповедует ряд принципов, лежащих в основе правил создания и использования всех структурных элементов, включая классы, объекты, методы и прочие компоненты.
Инкапсуляция
Этот принцип гласит, что вся важная информация, необходимая для работы объекта, в нем же и хранится. И только определенные данные доступны для внешних функций и объектов.
Данные конкретного объекта или класса хранятся в пределах этого объекта или класса. Вносить в них изменения, используя другие классы, нельзя. У окружения есть право только запрашивать «публичные» методы и атрибуты.
Такой подход обеспечивает повышенный уровень безопасности, а также сокращает шансы на случайное повреждение данных внутри какого-то класса или объекта со стороны.
Наследование
Это как раз основная суть взаимоотношений между классами и объектами, описанная выше. Чтобы не создавать кучу одинаковых объектов или классов, можно создать класс над классами с более общими характеристики и функциями, а потом постепенно наследовать от него те или иные возможности. Используя специальную конструкцию, программист может забрать из класса ряд атрибутов или методов, оставить их в прежнем виде и дополнить новыми или же слегка переосмыслить на свое усмотрение, а потом создать из них уникальный объект или подкласс для дальнейшего наследования опций.
Это проще понять на примере со средствами передвижения:
Берем абстрактный класс «Средство передвижения» с возможностью набирать скорость и перевозить людей.
Из него формируем подкласс «Автобус», наследующий базовые характеристики и уточняющий их определенным количеством мест для людей и пределом скорости.
Затем создаем объект «Икарус» с более конкретной скоростью, планировкой, количеством дверей, типом сигнала и другими специфичными параметрами.
Не нужно каждый раз создавать новый класс или объект с полным набором опций. Достаточно воспользоваться конструкцией в духе export class Bus extends Vehicle() и дополнить код конкретикой.
Абстракция
Каждый верхний слой над объектом (классы) более абстрактный, чем его «младшая версия». Это позволяет не переписывать по 10 раз один и тот же объект, указывая одни и те же атрибуты и методы. Напротив, абстрактные классы позволяют создавать все более конкретные классы и вытекающие из них объекты, не описывая реализацию функций заранее (в этом и суть абстракции), а оставляя исключительно базовый шаблон для дальнейших надстроек.
Абстрактный класс должен оставаться публичным и не содержать реализации методов. Этим он отличается от дочерних классов.
Полиморфизм
Один из ключевых принципов ООП, позволяющий использовать одни и те же методы для обработки различных типов данных. Полиморфизм в разных языках программирования отличается: есть строго типизированные языки в духе C++, где задействуется «перегрузка», а есть такие языки, как JavaScript, где по умолчанию функции могут обрабатывать разные типы информации без необходимости указывать тип заранее.
Полиморфизм позволяет с помощью идентичных методов обрабатывать разные типы данных, например двузначные числа и числа с плавающей точкой. Также полиморфизмом считается возможность переопределять методы в дочерних классах для обработки других видов данных или выполнения дополнительных действий при вызове аналогичного метода.
Преимущества ООП
Основными преимуществами парадигмы разработчики считают следующие особенности:
Модульность: инкапсуляция объектов в себе упрощает разработку, уменьшает количество ошибок и ускоряет разработку при участии большого количества программистов, так как каждый может работать независимо друг от друга.
Реюзабельность кода: благодаря абстракциям, полиморфизму и наследованиям можно не писать один и тот же код много раз, что заметно ускоряет создание нового ПО.
Высокая скорость разработки: классы и интерфейсы в ООП могут легко трансформироваться в подобие полноценных библиотек, которые можно переиспользовать в новых проектах.
Расширяемость: ООП-код легче развивать, дополнять и менять. Этому способствует независимая модульная структура.
Простота восприятия: использование ООП упрощает понимание кода за счет взаимодействия с объектами, а не логикой. Не нужно углубляться в то, как построено ПО, чтобы модифицировать его.
Безопасность: инкапсулированный код недоступен извне, поэтому «поломать» ООП-программу сложнее.
Гибкость: полиморфизм позволяет быстро адаптировать ООП-код под свои нужды, не описывая новые функции и объекты.
Недостатки ООП
Разработчики ругают объектно-ориентированную парадигму за то, что та ставит во главе угла объекты и не уделяет достаточно внимания вычислениям и алгоритмам. По мнению некоторых программистов, такой подход местами заставляет писать больше кода, чем понадобилось бы при использовании функциональной парадигмы. Также ООП-код негативно сказывается на скорости компиляции кода.
Языки, исповедующие объектно-ориентированную парадигму
Существует множество языков программирования, подходящих для применения ООП-парадигмы. Среди них:
Ruby – высокоуровневый язык с динамической типизацией, созданный в середине 90-х японским разработчиком Юкихиро Мацумото.
С++ – статически типизированный язык программирования общего назначения, в первую очередь направленный на работу с ООП.
JavaScript – популярный язык с динамической типизацией, одинаково хорошо подходящий для различных парадигм разработки, включая ООП.
Также в число языков с акцентом на ООП-парадигме входят: C#, Python, Java, PHP, JADE, Scala и другие.
Вместо заключения
Объектно-ориентированное программирование – популярная практика среди разработчиков, позволяющая делать сложные приложения и часто использующаяся в крупных корпорациях. Это интересная модель, с которой стоит ознакомиться всем, кто хочет делать логические модульные структуры и сокращать количество потенциальных ошибок и проблем с безопасностью в своих программах.








