Блуждая по интернету, можно заметить одну интересную особенность. Все парадигмы программирования воспринимаются людьми совершенно спокойно. Про процедурное программирование говорят спокойно и про модульное. Декларативное программирование — никаких бурь, волнений или холиваров. Функциональное — то же самое. И только вокруг ООП не утихают бури. Одни визжат от него в восторге, другие, наоборот, хаят.
И, честно сказать, совершенно непонятно, почему на ООП весь мир клином сошелся.
Если показалось, что я — скорее противник, чем сторонник ООП, то это не так (впрочем, это можно понять по заголовку). Я скорее противник «серебряных пуль», хайпа, возведения какой-либо методологии или человека на престол и всяческого вождения хороводов.
Вы же не водите хороводы вокруг, скажем, гаечного ключа или газонокосилки. И не пишете, я надеюсь, публикаций, почему дрель или молоток — отстой.
Но сегодня день весь интернет кишит именно напыщенными, гиперэмоциональными, радикалистскими статьями по поводу ООП. Если один говорит, что ООП — «зер гут» и вообще всем гутам гут — то другой обязательно вещает, что ООП необходимо срочно выкинуть на помойку. Третьего не дано.
Я же хочу именно привнести третий элемент. Спокойно, без хайпа и ругани рассказать, почему ООП — не эликсир от всех болезней, но также, как и ПП, ФП или ЛП имеет право на существование.
Итак, спокойная статья про ООП рабоче-крестьянским языком. В ней я попытаюсь рассмотреть основные доводы противников ООП и обосновать их несостоятельность.
1 Все, что есть в ООП, уже давно есть в других парадигмах
Почти все языки программирования— тьюринг-полные, за исключением языков разметок: HTML, XML, CSS и т.д.
Если говорить крестьянским языком, тьюринг-полный язык — на котором можно написать абсолютно любую программу. Из этого следует довольно-таки всеобщий тезис: то, что есть в любом выбранном языке, есть во всех остальных языках.
То же можно сказать и про парадигмы. Все отличия языков (и парадигм) — это разные способы реализации тех или иных команд, не считая отдельных лексических особенностей.
Кстати, этот же тезис (все, что есть в N, есть и в M, и в K, и в R и т.д.) можно сформулировать так: молоток уже состоит из железа и дерева, зачем же нам еще и пассатижи? Но ведь так никто не станет утверждать.
2 ООП смешивает данные и действия над ними. Это плохо
Аргумент высосан из пальца. Во-первых, где ООП смешивает данные и функции? Во-вторых, утверждение, что это плохо, тоже взято от фонаря. Из бочки «настоящий мужик так не делает», а почему — да потому, что гладиолус.
ООП в каком-то роде моделирует реальный мир, где данные присущи объекту — никто ведь не станет утверждать, что у стула отсутствует цвет, и у него не четыре ноги.
И никаких смешений данных и операций здесь не происходит, объект — это не функция и не оператор. Это абстракция.
3 Наследование закрепощает программу, делает трудным внесение изменений
Тут нужно немного притормозить. Наследование вовсе не предполагает выстраивание километровых деревьев с целью замедлять разработку. Наследование придумано для того, чтобы выделять общие свойства и методы в суперкласс, причем делать это нужно с классами, представляющими однотипные объекты. Ошибкой будет создавать, например, два класса, один из которых — наследник другого, ибо здесь нет выделения общего кода в суперкласс просто потому, что здесь нет ничего общего.
Если не предполагается расширять родительский класс третьим классом — такое наследование попросту бессмысленно. Если вы создаете магазин спиртных напитков, то классы Beer, Vodka и Vine можно унаследовать от класса Alcohol, но совершенно не нужно создавать еще и класс Drinks, если только вы не хотите продавать еще, скажем, парагвайский чай.
Также ошибкой будет создание иерархий, в которых классы никак не относятся друг к другу.
Ну зачем, расскажите мне, городить башню, где классы «Муха» и «Котлета» наследуются от суперкласса «Сыр», который, в свою очередь, наследуется от суперкласса «Пятница»?! Но это уже не недостаток ООП, а кривые руки того, кто такое сочиняет.
4 Инкапсуляция не имеет смысла
Вот тут я частично согласен. С точки зрения работы программы инкапсуляция действительно ни на что не влияет. Если я закрою переменную с помощью private
— ну и что, я все равно смогу ее открыть, просто убрав private
, а потом менять там все, что душе заблагорассудится.
Но это верно лишь чисто технически.
Философия ООП гласит: правильно организованный и инкапсулированный класс можно рассматривать как черный ящик.
Представьте себе коробку, на одной стороне которой разнообразные кнопки, слоты для подачи данных, а на другой — выходной слот, который возвращает информацию. Возьмем, к примеру, стек. Представьте коробку, на одной стороне которой есть один слот для вставки данных и кнопка push рядышком. На обратной стороне — кнопка pop. Вы подаете туда записку с числом 8 и давите кнопку push. Затем подаете еще бумажку и второй раз давите push. И так N раз, а затем жмете pop. Из ящика вылетает бумажка с числом 76 (или другое, в общем, то, которое вы подали). Нужно еще число? Второй раз давите pop. И так до тех пор, пока ящик не опустеет. А если вы продолжите давить pop, механизм из ящика завоет: стек пуст! Именно так и выглядит объект.
Но после того, как вы создали и настроили класс, вам уже фиолетово, как он там работает — он просто правильно работает, а большего и желать не нужно. А инкапсулируя все эти структуры, вы не держите все подряд в памяти. Они (множество ящиков) просто общаются между собой так, как вы настроите.
Инкапсуляция — своеобразный костыль, поддерживающий сотню столпов вашей программы в то время, пока вы конструируете сто первый. В крупных проектах (а именно для их создания и придумали ООП) без этого, увы, никак.
Хотя вряд ли это «увы» здесь вообще уместно.
5 В реальном мире нет иерархий отношения, повсюду лишь иерархии включения
Да разве? Но ведь никто не мешает создать, например, иерархию, где все реки мира (Конго, Сена, Темза, Амазонка, Колыма и т.д.) — объекты одной всеобъемлющей «Реки», которой присущи свойства (например, состоит из воды) и действия (например, течет), а уже она будет наследоваться от «Водоема», который тоже состоит из воды, а от «Водоема» можно унаследовать еще и «Озеро», объектами которого будут отдельные озера (Байкал, Каспийское море, Титикака и т.д.).
Схема довольно грубая. Но иерархии отношения — это тоже абстракция. Что-то вроде платоновской идеи, если хотите. В реальном мире их нет, они существуют только в уме, это обобщение, и не более того. Но ведь именно так человек очень часто мыслит. Мы ведь можем сказать «носок», без уточнения, каков у него цвет, из какого материала соткан и т.д., но существует ли этот «носок» в действительности?
И, все же, нас не должно смущать, что нет ни «объекта», ни «носка».
6 Методология ООП изначально ошибочна
Абсолютно необоснованный аргумент. ООП создавалось для того, чтобы моделировать своеобразный виртуальный мир, состоящий из объектов, как и наш мир. Например: человек — объект из реального мира. Он может ходить, бегать, кушать, спать, играть в футбол, смотреть футбол, но, к сожалению, я тут не могу все перечислить, да и, честно сказать, все перечислять было бы противно.
Тот же самый человек обладает свойствами: наличие/отсутствие волос, цвет волос, если они есть, цвет глаз, цвет кожи, количество пальцев на руках и т.д. Если правильно сконструировать все поля и методы, как я уже писал выше, то программный объект сможет моделировать те или иные свойства реального объекта.
Человек очень даже хорошо мыслит в таких категориях — именно поэтому ООП и стало распространенным. Оно очень помогает при написании больших проектов, так как привносит модульность и позволяет разбивать программный пакет на отдельные компоненты, взаимодействующие друг с другом.
7 Но даже миллионы мух не убедят нас, что навоз — это вкусно
Самый популярный аргумент против ООП. Мол, массы в большинстве своем глупы (все же, я не думаю, что это относится и к программистам), бегают по «модным шмоткам» и восхищаются ими.
Но задумайтесь, а если бы на пьедестал взошло не ООП, а, скажем, ЛП? Думаете, было бы все по-другому? Ничего подобного! Нашлись бы и фанаты, и злостные противники, а на ООП смотрели бы как на инструмент (к этому я, вообще-то, и призываю), а не как на таблетку, сотворенную самим Богом и потому незаменимую.
Почему эта статья в защиту ООП?
Все современные разговоры про парадигмы программирования, как мне видится, сводятся к двум диаметральным посылкам: оставим ООП и выкинем все остальное, или же выкинем ООП и… ну, вы поняли меня.
Я не хочу, чтобы вполне годную парадигму посчитали достойной свалки, но я и не хочу, чтобы вокруг нее водили хороводы, а все остальное забыли. Я думаю, что второе сделать проще, а против первого и направлена эта статья.
Если вам не нравится ООП
Кому — ООП, кому — ФП, кому — ПП. А кому-нибудь, может быть, вообще более всего мил свиной хрящик. Если вы не любите кошек — наверное, вы просто не умеете их готовить.
Читайте также: Некоторые языки уродуют разум: как программирование на самом деле влияет на ваш мозг
Это текст из личного блога, опубликованный с разрешения автора.
Этот материал – не редакционный, это – личное мнение его автора. Редакция может не разделять это мнение.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: