Об ООП

Наконец-то сформулировал, что меня не устраивает в объектно-ориентированном программировании.

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

Инструкции процессор пока что исполняет по очереди, ну и ещё он умеет прыгать по разным адресам. Возможность в языках программирования использовать всевозможные ветвления и остроумные циклы вроде foreach вместо повсеместного goto — это не парадигма, а просто удобный синтаксис. Иногда нам удобен if, иногда — case, иногда — while, иногда — for, а иногда, как ни крути, goto. Но всё это сводится к jmp, jz и подобным.

Возможность использования подпрограмм — это ещё чуть более сложная абстракция от прыганий по адресам в памяти, на этот раз ещё и с использованием стека. Она настолько важная, что реализована прямо в железе, и поэтому сводится к call и ret.

Но ничего принципиально нового в теорию алгоритмов все эти конструкции не вносят, они лишь дают возможность формулировать эти алгоритмы более наглядно. Глупо, скажем, вообще всё, что угодно, в программе реализовывать через функции. Для некоторых задач удобнее макросы, а для некоторых даже простой copy/paste кода. Синтаксически операторы часто удобнее и нагляднее функций: a = b+c понятнее, чем a = sum (b, c);

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

Проиллюстрируем сказанное на примере:

// a = sin (b);

s = new Sinusor ();
s -> angle = b;
s -> initiateEvaluation ();
a = s -> extractValue ();
Дальше
20 комментариев
Медвед 2006

Поскольку это всего лишь синтаксис, то использовать его нужно только тогда, когда это удобно, а не вообще всегда.

Чёрт возьми, кто бы мог подумать? =)
А приер про синус просто убивает своей наглядностью.

Максим Вуец 2006

Наконец-то сформулировал, что меня не устраивает в объектно-ориентированном программировании.

Четкого ответа я так и не нашел.

ООП — это не синтаксис, а стиль и принцип программирования. Хоть как ты это называй, а оно так и есть. Возможно ты не достаточно хорошо знаешь идеи и принципы ООП.

Есть функциональное программирование, есть императивное (процедурное), есть логическое… а есть объектно-ориентированое. И если ты видишь разницу только в синтаксисе, то могу только посочувствовать.

goto — это не парадигма, а просто удобный синтаксис

goto — это не парадигма, и не синтаксис. Это одна из команда, одного из ЯП (или нескольких). А синтаксис — это правила записи этой команды в рамках конкретного языка.

на настолько важная, что реализована прямо в железе, и поэтому сводится к call и ret.

А push и pop уже не рулят, да? (:

Но ничего принципиально нового в теорию алгоритмов все эти конструкции не вносят

А и не должны. Причем тут алгоритмы к парадигмам? Один и тот же алгоритм можно записать на русском, на Си, на Бейсике, на Форте… плюс, в процедурном стиле, в ОО, в функциональном…

Поскольку это всего лишь синтаксис, то использовать его нужно только тогда, когда это удобно, а не вообще всегда.

Вот с этим соглашусь. Абсолютно.

Кстати, Медвед прав. Пример у тебя некчемный! Можно так и подписать: «Let’s kill OOP!».

binary animal 2006

Хххахаха ржунимагу =))

«Инициация эвалюации» (главное не перепутать с «инициация эякуляции») — я это где-нить на людях сказану по накурке, посмотрим что с ними будет =)))

На самом деле если исходить из определения синуса, то там нужно два значения — длину катета и длину гипотенузы, а для этого надо заводить объект треугольник и у треугольника инициализировать все стороны, точнее даже надо от объекта «треугольник» унаследовать объект «прямоугольный треугольник» =)))

ахаха вот тебе и ооп, из одного синуса целый набор модулей можно развернуть =)

Евгений 2006

Какие-то вы все странные:)))

Илья, ты очень оригинально понимаешь ооп парадигму:)
Это видно и из примера.
Ваще-то, если рассматривать a=sin(b); как оо-конструкцию, то объекты здесь a и b, а не sin.
(можно конечно и наоборот, только тогда ооп никогда бы никто не использовал)

И получилось бы что-то примерно такое:

a->operator =(b->sin()); // необязательно в одну строчку. главное смысл.

А в том, что для этой операции ооп не нужно, ты прав.

Да, ооп — это абстракция, которая очень часто позволяет удобно организовать сложный проект и процесс его разработки. Как эта абстракция реализована (синтаксис+семантика+грамматика или drag/drop’ом кубиков-объектов в графической оболочке или еще каким дурацким способом) не важно. Или скорее важно в каждом конкретном случае.

Илья Бирман

К сожалению, мы каждый день сталкиваемся с объектами типа WikiFormatter, когда по идее объектом должен являться форматируемый текст, а не форматирователь его, но в коде дело обстоит совсем иначе. Так объектно-ориентированное программирование понимаю не я. Так им пользуются люди вокруг. Это и вызывает раздражение.

А использование по назначению всем только на пользу.

Евгений 2006

Ну так я же тебя комментирую, а не код от wiki или еще чего другого.

Т. е. когда ты пишешь

Наконец-то сформулировал, что меня не устраивает в объектно-ориентированном программировании.

ты имеешь в виду не ооп как явление, а конкретных отморозков?
ну тогда ладно:))

PS: может быть иногда и такие странные конструкци чем-то оправданы.

Илья Бирман

«Конкретные отморозки» являются существенной составной частью «ООП как явления».

Андрей Мус 2006

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

Тезисы же приведенные в заметки Ильи слегка… Ну…

!!Инструкции процессор пока что исполняет по очереди.!!
Если бы.

!!Возможность использования подпрограмм — это ещё чуть более сложная абстракция от прыганий по адресам в памяти, на этот раз ещё и с использованием стека. Она настолько важная, что реализована прямо в железе, и поэтому сводится к call и ret.!!
Возможность использования подпрограмм — это ещё чуть более сложная абстракция, чем представляеется Илье Бирману. Рядом c push и pop тут лежат task и call gate’ы, длинные и короткие прыжки и другие прелести.

!!Но ничего принципиально нового в теорию алгоритмов все эти конструкции не вносят.!!
Ну вроде Logo для управления черепашкой — тоже Turing complete language.

!!они лишь дают возможность формулировать эти алгоритмы более наглядно.!!
Здесь лежит главное.

!!Глупо, скажем, вообще всё, что угодно, в программе реализовывать через функции. Для некоторых задач удобнее макросы.!!
Это вроде такие маленькие функции, которые на этапе собирания программы вставляются в код? Все нормальные компиляторы давно делают это сами. Иногда им даже не требуется слова inline.

Про главное. Действительно, ООП позволяет некоторые вещи представить более наглядно. Именно для этого он и был придуман. Когда наши предки слезли-таки с деревьев и начали писать сложные системы, они испытывали перманентную фрустрацию. Ведь чем сложнее и больше программный продукт, тем сложнее в нем разобраться. За спасательный круг ООП тогда ухватились многие. И он спасательный всё ещё. Недавно была такая мулька для java — анализирует связанность классов. Большинство крупных проектов имеет ужасно большую связность. Почему? Потому что ООП — плохо и часто не подходит для решения наших задач. Но эти проекты большие и они работают. Почему? Потому что ООП — хорошо.

Впрочем это не тема для обсуждения с человеком, который называет foreach остроумным циклом, и судя по всему не видит принципиальной разницы между программированием на ассемблере и программированием на высокоуровневом языке, со столь милыми сердцу lambda-expressions, inline SQL, работой со списками и множественным наследованьем. ;)

Baka 2006

Насколько я помню, в ООП главное — «три источника и три составные части» —
инкапсуляция, наследование, полиморфизм
(что это такое — надеюсь, все (кому надо) знают).

Мне кажется, это не только синтаксис.

(Представил себе класс «Гиперболический синус» как потомок обычного синуса. Ужаснулся.
Главное, чтобы ночью виртуальный деструктор не приснился.
)

p1uton 2006
  1. Операторы — это часть ООП. Можно складывать числа, а можно — объекты (векторы, например). Если требуется, монно перегрузить операторы и сделать так, чтобы они работали как нужно.
  1. А как насчет готовых объектных моделей, типа DOM. Гораздо приятнее обратиться к любому элементу документа по его id, чем каждый раз парсить HTML-код.

А синус, кстати, всегда был функцией.

aaa 2006

Илья, ты понимаешь ООП не оригинально, а правильно. Синтаксис, люди! Ау! Есть ли жизнь на марсе (взболтнул стакан)...

МГ 2006

Убейте меня, но объект WikiFormatter гораздо разумнее и полезнее, чем объект — форматируемый текст. Хуже того, если объект FormattedText предоставляет сервисы, которые можно перенести в WikiFormatter, то их нужно перенести в WikiFormatter.

Макс Лапшин 2006

Пример с синусом поражает своей наглядностью. Более наглядно продемонстрировать собственное неумение писать код сложно.

Для sin уже есть функция, однако рассмотрим нестандартный алгоритм: число Фибонначи.

f = Math::Fibonnachi.count(20)

Дальше не нужно ничего. То, что написали вы, как раз наглядно демонстрирует, что вы так ничего в ООП и не поняли.
Совет: бросьте PHP. В нем ООП — это действительно, не парадигма, а синтаксис.

Илья Бирман

Но почему не ##f = fibonnaci (20)##, чёрт возьми? Объясните мне, какой объект какой предметной области скрывается за объектом Math. Math — это что? Как он выглядит? Что он делает? Какое это имеет отношение к чему кроме кривого синтаксиса? Для sin «уже есть функция» только потому, что когда понадобился людям синус, их мозги ещё не были забиты всем::этим.бредом.

И, при чём тут моё неумение писать код? Так выглядит 90% «объектно-ориентированного» кода вокруг.

Кстати, спасибо за очень ценный совет.

Spectator 2006

Я вас всех помирю

%%def fibonnaci (x):
return Math::Fibonnachi.count (x)%%

Илья Бирман

Так и делаю, в общем-то.

Андрей Мус 2006

Пожалуй, я вам расскажу.

%%f = Math::Fibonnachi.count(20)%%

Дело в том, что числа Fibonacci считаются как

%%a, b = 0, 1
while b < n:
print b,
a, b = b, a+b%%

Нетрудно заметить, что вычисление происходит в цикле. И чтобы получить n-ое число нужно посчитать все предыдущие. А если нужно посчитать fib(1000) а потом fib(1001)? Здесь то мы и подходим к объектам. Простой паттерн проектирования и мы заворачиваем нашу функцию в объект, который-то и помнит все предыдущие числа.

На самом-то деле это, конечно же, от Лукавого и такую штуку мы умеем делать ещё со времен старого доброго функционального программирования. Пример на python’е будет похож на что-нибудь вроде http://python.paracoda.com/search/hypermail/python-1994q1/0449.html хотя class там, безусловно, лишнее слово.

Math:: — расширение области видимости, использование модуля или как оно в таких языках называется. Илья, такое впечатление, что Вы путаете этот ненавистный C++ и C-подобный синтаксис с ООП.

Да, это такая фича e2 — неработающие «Последние комментарии к этой заметке»? ;)

Илья Бирман

##f = Math::Fibonnachi.count(1000)##
##f = Math::Fibonnachi.count(1001)##

Вы говорите, что второй вызов сработает очень быстро, так как он хранит предыдущий результат. Хорошо.

##f = Math::Fibonnachi.count(999)##

Что произойдёт теперь?

Если оно, когда считало для 1000, сохранило все числа куда-то, то это исключительно глупо, так как куча памяти расходуется впустую. Допустим, это какие-то несколько килобайт, но если вы в принципе так пишете программы — сами понимаете, это становится проблемой.

Если оно сохраняет только результат последнего вызова, то это оптимизация для одного конкретного случая (который ещё фиг знает, будет иметь место или нет) из-за которой пришлось городить целый класс!

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

Что касается фичи в e2 — спасибо, начиная с v1490 этой фичи больше нет :-)

Макс Лапшин 2006

Андрей, совершенно верно. Причем, если этого не сделать, то получится свалка в глобальном пространстве имен.
P.S. Есть по меньшей мере два логарифмических способа посчитать нужное число, но сути это не меняет.

Илья. Почему не просто функцию? Авторы PHP тоже думали, что им не понадобятся пространства имен и можно будет просто обойтись маленькой, не сильно пахнущей кучкой функций. Этого не получилось. Пространства имен в PHP появились, но очень глупые и неудачные (array_, string_, mb_).

Если так выглядит 90% кода, написанного вокруг вас, то это значит только то, что эти люди не очень умело пишут код. ООП тут не при чем.

Андрей Мус 2006

Про примиряющий код:

%%fibonacci=Math::Fibonacci.count%%.

Или на худой конец, такая штука:

%%
def fib(n,dic={}):
if (n<=1): return n
else: return dic.setdefault(n,fib(n-1)+fib(n-2))
%%

Snal 2006

Программирование — это не парадигма, а просто синтаксис, но многие его считают парадигмой и чуть ли не молятся на него. Так как все компьютеры — это всего лишь продвинутые машины Тьюринга.

Евгений 2006

Но почему не f = fibonnaci (20), чёрт возьми?

Потому что здесь функцию за каким-то чёртом завернули в объект. Может быть зря. А может быть так было нужно по каким-то соображениям. Не стоит дуться на концепцию из-за того, что её не всегда правильно и к месту применяют. Этак можно любой стиль программирования изругать.

К сожалению, мы каждый день сталкиваемся с объектами типа WikiFormatter, когда по идее объектом должен являться форматируемый текст, а не форматирователь его

Хей. А вот это зависит от... Например от того, как часто мы планируекм в дальнейшем изменять правила форматирования. Или от того, что ещё, кроме банального текста, мы собираемся форматировать.

В данном случае, это реализация паттерна Strategy. Он позволяет изменять алгоритмы независимо от клиентов, которые ими пользуются.

Евгений 2006

Позволю себе вас же и процитировать:
«Внимание! У этого подхода есть и некоторые недостатки. Если вы нашли один из них, не нужно думать, что вы большой герой, и громко про это кричать. Недостатки — это нормальное явление для всего.»

Евгений 2006

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

Oleg Andreev 2010

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

Мои книги