True OOP
От: Poudy Россия  
Дата: 16.01.05 12:20
Оценка: 4 (1)
Хочу вынести на обсуждение одну спорную идею о принципах программирования объектов.

Долго размышлял над сутью споров о статической/динамической типизации, использовании шаблонов и C++ vs динамические языки. И в данной ветке мне не хочется в очередной раз пережевывать "разные языки для разных задач". Есть вполне прагматичная и правильная точка зрения профессионалов и полиглотов о том, чтобы использовать разные языки и подходы (прототипируем на Smalltalk, переписываем на С++), тут всё ясно.

Часто вспоминаю слова Алана Кея о том, что всё есть объект, и как важна идея посылки сообщения. Для меня очевидно, что исключения из правил "объектности" несут проблемы во многих языках. Примеры: в C++ класс — это не объект (как Type в C#), bool — это не объект и в C++ и в Java.

В свою очередь для ОО-библиотек есть похожие несуразности, которые я отношу к звеньям той же цепи:
1. Библиотека не последовательна в функциональности классов. Пример: в System.Windows.Forms.MenuItem нет Tag, а в std::string нет toUpper/toLower.
2. Иерархия классов странная (больше относится к custom библиотекам). Каждое десятый пост в форуме Проектирование о том, как спроектировать очередную странную иерархию, где Readonly, Admin, Web и прочая функциональность сильно переплетены, и автор непременно хочет заморозить всё это в статичном виде.

Обсудить хочу следующий принцип для разработки ОО-библиотек:

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

Примеры использования этого принципа я вижу в System.Windows.Forms.Control и System.IO.Stream. Примеры из других библиотек приводить не буду, потому что толком в них не шарю.

Как аргумент в защиту принципа могу привести умственный опыт: представим библиотеку, в которой работа с файлами ведется при помощи InputSystemFile, OutputTextFile, IONetworkFile, SequentialBinaryIOFile и т.д. При этом абстрактный класс (или интерфейс), лежащий в корне иерархии, содержит только Name (getName) и Close() (close()).
Re: True OOP
От: McSeem2 США http://www.antigrain.com
Дата: 16.01.05 15:27
Оценка: 11 (3) +9
Здравствуйте, Poudy, Вы писали:

P>В свою очередь для ОО-библиотек есть похожие несуразности, которые я отношу к звеньям той же цепи:


P>1. Библиотека не последовательна в функциональности классов. Пример: в System.Windows.Forms.MenuItem нет Tag, а в std::string нет toUpper/toLower.


Ничего странного в этом нет. Функциональности на все-про-все не напасешься. Это следует из принципов устройства нашей Вселенной — нам не дано знать будущее. Другое дело, как в случае необходимости расширить функциональность. Обычно начинающие лихо делают новый класс-потомок и добавляют туда требуемые функции. то есть, делается string_ex и используется везде, где только можно (сам так делал и очень быстро прекратил). Это очень плохая практика, приводящяя к полному бардаку и появлению нелепых конструкций, типа
((string_ex*)(&str))->toLower();

Наиболее правильным было бы сделать просто функцию toLower(std::string& s). Наследование нелепо еще и потому, что в данных случаях приводит к искусственным иерарархиям классов. Программисты из одного отдела сделали string_ex и "законодательно" объявили о замораживании интерфейса. Программистам из другого отдела понадобилась еще какая-то функция, вот у нас уже появилась string_ex2. И так далее.
В случае использования простых функций не требуется никаких левых иерархий и никаких дополнительных имен классов (что IMO даже более важно, чем наличие левых иерерхий само по себе). Применительно к std::string нет никакой разницы между записями str.toLower() и toLower(str). Для данного случая, расуждения о важности идеи посылки сообщений — не более чем демагогоия.

Можно возразить, что например, требуется сделать синхронизированную, thread safe строку. Следовательно, надо в классе хранить mutex. Но ведь это не добавление функциональности. Это глобальное изменение функциональности! И наследование здесь тем более неуместно. Здесь нужна инкапсуляция с аккуратным переопределением всех методов. Много писать? Да, много. Но все другие варианты — еще хуже. Заметьте, что при этом та же самая шаблонная toLower() проболжает без каких-либо изменений функционировать для обейх вариантов string. На мой взгляд, корень проблемы находится в нечетком понимании (а часто — в полном непонимании) принципов декомпозиции функциональности.

P>2. Иерархия классов странная (больше относится к custom библиотекам). Каждое десятый пост в форуме Проектирование о том, как спроектировать очередную странную иерархию, где Readonly, Admin, Web и прочая функциональность сильно переплетены, и автор непременно хочет заморозить всё это в статичном виде.


Вот в том-то и недостаток идеи наследования. После того, как иерархия создана, нет ни малейшей возможности проявить хоть какую-то гибкость. Взять ту же MFC. Есть класс CDC, у которого есть потомки, типа CClientDC и др. В нем так же есть функция PolyPolygon, которую я хочу заменить своей (более правильной, быстрой, причина на важна). Так каким образом не трогая исходников, я могу включить свой класс (с этой переопределенной функцией) в иерархию между CDC и CClientDC? Никаким! Таким образом, библиотека любой сложности, основанная на принципах иерерхий классов, является абсолютно черным ящиком и использовать ее можно лишь одним единственным способом: "щелкни кобылу в нос — она махнет хвостом".

P>Обсудить хочу следующий принцип для разработки ОО-библиотек:

P>

P>Каждый проблемный домен должен содержать свой центральный класс, содержащий наиболее полную (а не наиболее непротиворечивую) для данного домена функциональность.


Понятие "наиболее полная функциональность" — это абсурд в силу принципов организации нашей Вселенной... Так, я это уже говорил...

Нужно заботиться не о "наиболее полной" функциональности, а прежде всего — о возможности расширения функциональности. А использование иерерхий классов в корне противоречит идее о возможностях расширения.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: True OOP
От: Poudy Россия  
Дата: 16.01.05 16:41
Оценка: 1 (1)
Тебя качнуло совсем в другую сторону от той, о которой я писал.

Здравствуйте, McSeem2, Вы писали:

P>>В свою очередь для ОО-библиотек есть похожие несуразности, которые я отношу к звеньям той же цепи:

P>>1. Библиотека не последовательна в функциональности классов. Пример: в System.Windows.Forms.MenuItem нет Tag, а в std::string нет toUpper/toLower.

MS>Ничего странного в этом нет. Функциональности на все-про-все не напасешься.

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

MS>Обычно начинающие лихо делают новый класс-потомок и добавляют туда требуемые функции. ...

MS>...Наиболее правильным было бы сделать просто функцию toLower(std::string& s).
Согласен.

MS>Наследование нелепо еще и потому, что в данных случаях приводит к искусственным иерарархиям классов. ... В случае использования простых функций не требуется никаких левых иерархий и никаких дополнительных имен классов (что IMO даже более важно, чем наличие левых иерерхий само по себе).

Что ж теперь, назад в джунгли? Вообще забыть о наследовании? Это будетс слишком необдуманно и резко .

MS>Применительно к std::string нет никакой разницы между записями str.toLower() и toLower(str). Для данного случая, расуждения о важности идеи посылки сообщений — не более чем демагогоия.

Как-то ты.... эта-а.. стоп. str.toLower() — это не важная посылка сообщения. Посылка сообщения — это инкапсуляция + полиморфизм. Инкапсулируется способ исполнения запроса и позволяется, чтобы он был разным для разных объектов. Важность посылки сообщения была вообще не о str.toLower(), а о том, чтобы расширять функциональность по-возможности паттерном стратегия или мост. А также применительно к динамическим языкам, которые не требуют явного указания, может ли объект принять указанное сообщение, и потому удобны для быстрого прототипирования.

MS>Можно возразить, что например, требуется сделать синхронизированную, thread safe строку. ... Здесь нужна инкапсуляция с аккуратным переопределением всех методов. Много писать? Да, много. Но все другие варианты — еще хуже.

Да, всё верно.

MS>Вот в том-то и недостаток идеи наследования. После того, как иерархия создана, нет ни малейшей возможности проявить хоть какую-то гибкость.

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


P>>Обсудить хочу следующий принцип для разработки ОО-библиотек:

P>>

P>>Каждый проблемный домен должен содержать свой центральный класс, содержащий наиболее полную (а не наиболее непротиворечивую) для данного домена функциональность.


MS>Понятие "наиболее полная функциональность" — это абсурд в силу принципов организации нашей Вселенной... Так, я это уже говорил...

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

MS>Нужно заботиться не о "наиболее полной" функциональности, а прежде всего — о возможности расширения функциональности. А использование иерерхий классов в корне противоречит идее о возможностях расширения.

Вот вот тут вот (касаемо "в корне протеворечит") я совсем и категорически не согласен . Иногда противоречат некоторые реализации — вот моё мнение.
Re[3]: True OOP
От: McSeem2 США http://www.antigrain.com
Дата: 16.01.05 18:02
Оценка: 2 (2)
Здравствуйте, Poudy, Вы писали:

P>Тебя качнуло совсем в другую сторону от той, о которой я писал.


Значит я вообще не понял смысла вопроса.

MS>>Наследование нелепо еще и потому, что в данных случаях приводит к искусственным иерарархиям классов. ... В случае использования простых функций не требуется никаких левых иерархий и никаких дополнительных имен классов (что IMO даже более важно, чем наличие левых иерерхий само по себе).

P>Что ж теперь, назад в джунгли? Вообще забыть о наследовании? Это будетс слишком необдуманно и резко .

Ну, скажет так. В C++, единственное, для чего нужно наследование — это переопределить одну или несколько виртуальных функций. Ну еще — для спецификации исключений. Я тоже использую наследование в случаях отличных от этих. Но по здравому размышлению понимаю, что так я поступил просто-напросто от лени, и там где используется наследование — нужна инкапсуляция. У меня есть проект, хоть и небольшой, но довольно-таки сложный: http://www.antigrain.com/agdoc/index.html, где вообще нет наследования. При этом я могу утверждать, что он сделан в рамках классического ООП. И при этом — прекрасно расширяем.

MS>>Вот в том-то и недостаток идеи наследования. После того, как иерархия создана, нет ни малейшей возможности проявить хоть какую-то гибкость.

P>Да нет, конечно же. Ты сам прекрасно понимаешь, что все дело в неправильном использовании наследования для задачи, которая требует большой гибкости. И ты сам правильно написал о неглубоком понимании. Так что наследование не при чем во всех этих наивных яблоках и грушах, наследованных от фрукта.

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

MS>>Нужно заботиться не о "наиболее полной" функциональности, а прежде всего — о возможности расширения функциональности. А использование иерерхий классов в корне противоречит идее о возможностях расширения.

P>Вот вот тут вот (касаемо "в корне протеворечит") я совсем и категорически не согласен . Иногда противоречат некоторые реализации — вот моё мнение.

Я бы сказал практически все реализации. Значит идея наследования неверно понята всем миром и используется неправильно
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: True OOP
От: Mika Soukhov Stock#
Дата: 16.01.05 18:20
Оценка: :))) :))) :)
Здравствуйте, Poudy, Вы писали:

P>....И все деньги не заработаешь.


Часть придется украсть
Re[4]: True OOP
От: Poudy Россия  
Дата: 16.01.05 18:46
Оценка:
Здравствуйте, McSeem2, Вы писали:

P>>Что ж теперь, назад в джунгли? Вообще забыть о наследовании? Это будетс слишком необдуманно и резко .


MS>Ну, скажет так. В C++, единственное, для чего нужно наследование — это переопределить одну или несколько виртуальных функций. Ну еще — для спецификации исключений. Я тоже использую наследование в случаях отличных от этих. Но по здравому размышлению понимаю, что так я поступил просто-напросто от лени, и там где используется наследование — нужна инкапсуляция. У меня есть проект, хоть и небольшой, но довольно-таки сложный: http://www.antigrain.com/agdoc/index.html, где вообще нет наследования. При этом я могу утверждать, что он сделан в рамках классического ООП. И при этом — прекрасно расширяем.


С твоим проектом я хорошо знаком. Буквально сегодня днем читал обновления документации. Действительно, это вполне ОО библиотека, поскольку классы четко делегируют обязанности друг другу. Механизм обработки любого запроса изменяем и поток обработки данных хорошо контролируется и расширяется.

Ну а насчет наследования — если рассматривать только наследование реализации, то это и есть инструмент для "ленивых". Примерно такой же, как компилятор. Если же рассматривать наследование интерфейса, то просто в C++ очень всё перепутано с концепциями AI, и люди долго боролись за приведение мыслей в порядок. Java & C#, кто бы что не говорил, являются очень большой подвижкой в сторону нормальной работы с иерархиями (куча, object и interface).

MS>Именно! И если подумать дальше, то получится, что область применения наследования — очень и очень ограничена.

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

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

Смешно. .

P>>Вот вот тут вот (касаемо "в корне протеворечит") я совсем и категорически не согласен . Иногда противоречат некоторые реализации — вот моё мнение.

MS>Я бы сказал практически все реализации. Значит идея наследования неверно понята всем миром и используется неправильно
То, что MFC на твой взгляд неправильно понимает наследование, не покрывает все существующие системы. Кроме того, тут есть разница между AGG и MFC.
• Ты пишешь продукт, который можно встроить в чужой продукт. Строишь его расширяемым. Пишешь долго, но качественно.
• Чуваки из MS пишут фичу Windows. Им не нужно позволять другим кампаниям ничего встаивать или расширять. И пишут они в жутко замыленном режиме. Вот и всё.
Re: True OOP
От: c-smile Канада http://terrainformatica.com
Дата: 16.01.05 19:19
Оценка: +3
Здравствуйте, Poudy, Вы писали:

P>Обсудить хочу следующий принцип для разработки ОО-библиотек:

P>

P>Каждый проблемный домен должен содержать свой центральный класс, содержащий наиболее полную (а не наиболее непротиворечивую) для данного домена функциональность.

P>Примеры использования этого принципа я вижу в System.Windows.Forms.Control и System.IO.Stream. Примеры из других библиотек приводить не буду, потому что толком в них не шарю.

Опять глобальные вселенские принципы приносящие щастье всем и бесплатно?
Опять 100 летняя война алой и белой розы: "Все есть объект" versus "Все есть handle/pointer"?

"Философского камня" нет.

Есть конкретные задачи/кластеры задач/библиотеки и методы их использования где работает динамический полиморфизм (виртуальное наследование)
Соответсвенно есть это все другое где статический полиморфизм (templates, everything is a abstract typename) "играет всеми гранями".
Есть еще функциональный подход — everything is a handle (HWND, HDC, void*, etc.)

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

Искусство проектирования и базовый принцип — стоять выше "ООП/не ООП" или конкретных языков
ибо цель проектирования (грамотного, нацеленного на результат) — создание оптимальных систем оптимальным образом.

Да, есть System.Windows.Forms.Control, а есть также HWND.
Да, есть System.IO.Stream, а есть FILE*...

Ну давайте поспорим что лучше...
Re[2]: True OOP
От: Poudy Россия  
Дата: 16.01.05 21:12
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Опять глобальные вселенские принципы приносящие щастье всем и бесплатно?

CS>Опять 100 летняя война алой и белой розы: "Все есть объект" versus "Все есть handle/pointer"?
CS>"Философского камня" нет.
CS>Есть конкретные задачи/кластеры задач/библиотеки и методы их использования где работает динамический полиморфизм (виртуальное наследование)
Вот я как раз написал, что хочу избежать флуда об ууух! mature таких программерах/архитектах, юзающих удачно все технологии в нужном контексте . Вопрос был применительно к ООП языкам.

CS>Соответсвенно есть это все другое где статический полиморфизм (templates, everything is a abstract typename) "играет всеми гранями".

CS>Есть еще функциональный подход — everything is a handle (HWND, HDC, void*, etc.)
По мне так everything is a handle/pointer не шибко отличается от "Все есть объект". Никакого versus. Просто соображения эффективности на уровне ядра или под 80486 .

CS>И есть искусство проектирования состоящее из того чтобы определить наиболее подходящую(ие) модель(и) из вышеизложенных (и не только) для конретной области примененеия.

Да да да. +20 баллов тебе .

CS>Да, есть System.Windows.Forms.Control, а есть также HWND.

CS>Да, есть System.IO.Stream, а есть FILE*...
CS>Ну давайте поспорим что лучше...
Я вапче говорил не об этом. Примем за аксиому, что все технологии полезны, и успокоимся. Я скорее имел в виду это
Автор: Rumata
Дата: 03.01.05
, это
Автор:
Дата: 21.12.04
или даже это
Автор: borisman2
Дата: 01.10.04
.
Re[3]: True OOP
От: c-smile Канада http://terrainformatica.com
Дата: 16.01.05 21:29
Оценка:
Здравствуйте, Poudy, Вы писали:

P>Я вапче говорил не об этом. Примем за аксиому, что все технологии полезны, и успокоимся. Я скорее имел в виду это
Автор: Rumata
Дата: 03.01.05
, это
Автор:
Дата: 21.12.04
или даже это
Автор: borisman2
Дата: 01.10.04
.


Ага! Теперь ближе к делу: т.е. не "Каждый проблемный домен должен содержать свой центральный класс...",
а вполне конкретные задачи и случаи.

Это как раз понятно и имеет смысл обсуждать.

А то "Девочка, а девочка, ты кого больше любишь — папу или маму?" ...
"центральный класс или прослойку?"...

Всякий раз как слышу нечто типа "А ты какую руку больше любишь — левую или правую?" у меня закрадываются очень нехорошие подозрения...
Re[4]: True OOP
От: Poudy Россия  
Дата: 16.01.05 21:48
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Ага! Теперь ближе к делу: т.е. не "Каждый проблемный домен должен содержать свой центральный класс...",

CS>а вполне конкретные задачи и случаи.
Ну конечно конкретные ! А то! Хых. .
Я выдвинул.... так скааать... рекомендацию. В форме принципа. Рекомендацию новичкам и заблудшим душам при проектировании запутанных иерархий. Необязательную. Так правильно?
Re: True OOP
От: Gaperton http://gaperton.livejournal.com
Дата: 16.01.05 22:03
Оценка:
Здравствуйте, Poudy, Вы писали:

P>В свою очередь для ОО-библиотек есть похожие несуразности, которые я отношу к звеньям той же цепи:

P>1. Библиотека не последовательна в функциональности классов. Пример: в System.Windows.Forms.MenuItem нет Tag, а в std::string нет toUpper/toLower.
Вообще-то в std::string нет toUpper/toLower совсем не потому, что кто-то забый ее туда добавить. Предполагается что ты воспользуешься стандартным алгоритмом transform и соответствующей функцией. И сделано так не случайно. В этом проявляется другой принцип проектирования, противоположный тому, который ты предлагаешь. Жизнь непростая штука
Re[2]: : True OOP
От: Poudy Россия  
Дата: 16.01.05 22:26
Оценка:
Здравствуйте, Gaperton, Вы писали:

G>Вообще-то в std::string нет toUpper/toLower совсем не потому, что кто-то забый ее туда добавить. Предполагается что ты воспользуешься стандартным алгоритмом transform и соответствующей функцией. И сделано так не случайно. В этом проявляется другой принцип проектирования, противоположный тому, который ты предлагаешь. Жизнь непростая штука


Хороший принцип? Если ты о том же, о чем говорил McSeem2, то это всего лишь вариант реализации, а не принцип. В .Net есть ToUpper потому, что все строки в юникоде. А трансляция производится при помощи Encoding. И это правильнее, чем переводить translate'ом строку из неизвестной кодировки. А если в строку зашить указатель на кодировку, то опять нет проблем сделать ToUpper. Я сильно не прав?

Мне кажется просто, что STL и прочее писалось в бородатые года и как только появлялась необходимость в расширяемости народ качало из шаблонов в процедуры и назад, вместо использования стратегий и других паттернов. А почему? А потому что нет сборки мусора и вообще проблема с объектами (то он в куче, то в стеке). Я не спорю, что для C++ всё это верно. Я говорю, что это особенности реализации, а не принцип.
Re[3]: : Re[2]: : True OOP
От: Павел Кузнецов  
Дата: 17.01.05 00:19
Оценка: +3
Poudy,

> В .Net есть ToUpper потому, что все строки в юникоде. А трансляция производится при помощи Encoding. И это правильнее, чем переводить translate'ом строку из неизвестной кодировки. А если в строку зашить указатель на кодировку, то опять нет проблем сделать ToUpper. Я сильно не прав?


Сильно. std::translate вообще ничего не знает о кодировках. Это просто функция, применяющяя некоторое преобразование к каждому из элементов последовательности. Само преобразование задается функтором, который передается в std::translate извне.

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


Тебе кажется неправильно. Стандартная библиотека C++ вообще и STL в частности изобилует примерами различных паттернов проектирования. Например, применительно к std::translate, можно легко распознать Iterator и (сюрприз?) Strategy.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: [3]: : Re[2]: : True OOP
От: Poudy Россия  
Дата: 17.01.05 08:25
Оценка:
Забавно, как это ты сразу распознал во мне оппонента, и уже не видишь, что же я говорю.

Здравствуйте, Павел Кузнецов, Вы писали:

>> В .Net есть ToUpper потому, что все строки в юникоде. А трансляция производится при помощи Encoding. И это правильнее, чем переводить translate'ом строку из неизвестной кодировки. А если в строку зашить указатель на кодировку, то опять нет проблем сделать ToUpper. Я сильно не прав?


ПК>Сильно. std::translate вообще ничего не знает о кодировках. Это просто функция, применяющяя некоторое преобразование к каждому из элементов последовательности. Само преобразование задается функтором, который передается в std::translate извне.


Так я и словом же не обмолвился, что translate делает всё сам. Я только сказал, что строка в std:: не хранит кодировки, и видимо это не позволило реализовать ToUpper сразу как штатную функцию, хоть бы само преобразование и задавалось где-то пользователем.

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


ПК>Тебе кажется неправильно. Стандартная библиотека C++ вообще и STL в частности изобилует примерами различных паттернов проектирования. Например, применительно к std::translate, можно легко распознать Iterator и (сюрприз?) Strategy.


Опять же, я даже не намекнул, что Алекс Степанов ничего не понимал в паттернах. Но реализовывал он их на шаблонах и процедурах (ну функторах). Оно для C++ неплохо, вероятно. Производительность, там, то да сё. Но работать с такой реализацией слегка, пусть на 0.01%, менее удобно, чем с "полнофункциональными" объектами. Вот такими 0.01% в тысяче мест .Net и переманивает сейчас программистов определенных задач, где поначалу господствовал практически один C++. И продолжает в том же духе
Автор: ZveN
Дата: 12.01.05
.
Re[2]: : True OOP
От: Poudy Россия  
Дата: 17.01.05 09:03
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Вот в том-то и недостаток идеи наследования. После того, как иерархия создана, нет ни малейшей возможности проявить хоть какую-то гибкость. Взять ту же MFC. Есть класс CDC, у которого есть потомки, типа CClientDC и др. В нем так же есть функция PolyPolygon, которую я хочу заменить своей (более правильной, быстрой, причина на важна). Так каким образом не трогая исходников, я могу включить свой класс (с этой переопределенной функцией) в иерархию между CDC и CClientDC? Никаким! Таким образом, библиотека любой сложности, основанная на принципах иерерхий классов, является абсолютно черным ящиком и использовать ее можно лишь одним единственным способом: "щелкни кобылу в нос — она махнет хвостом".


Выходит, по твоему TRUE OOP — это язык без статического наследования? Или Python?
Re[5]: : Re[4]: [3]: : Re[2]: : True OOP
От: alexeiz  
Дата: 17.01.05 10:35
Оценка: 8 (1) +2
"Poudy" <12097@users.rsdn.ru> wrote in message news:990259@news.rsdn.ru
> Опять же, я даже не намекнул, что Алекс Степанов ничего не понимал в
> паттернах. Но реализовывал он их на шаблонах и процедурах (ну
> функторах). Оно для C++ неплохо, вероятно.
> Производительность, там, то да сё. Но работать с такой реализацией
> слегка, пусть на 0.01%, менее удобно, чем с "полнофункциональными"
> объектами.

Менее удобно? "Полнофункциональные" объекты, т.е OOP — полезная штука, но она не всесильна. Во многих случаях более подходящими оказываются другие парадигмы. Где ты был 10 лет назад, когда STL была спроективована? Думаешь не было OO библиотек для достижения той-же самой цели? Были и много. Но не выжили. Для C++ болезнь OOP — это уже давно пройденный этап. Другие языки прийдут к этому позднее (если вообще прийдут).

А вот, кстати, мнение самого Степанова:

Question:
This mean a radical change of mind from both imperative and OO thinking. What are the benefits, and the drawbacks, of this paradigm compared to the "standard" OO programming of SmallTalk or, say, Java?

Answer:
My approach works, theirs does not work. Try to implement a simple thing in the object oriented way, say, max. I do not know how it can be done. Using generic programming I can write [...]. Try doing it in Java. You can't write a generic max() in Java that takes two arguments of some type and has a return value of that same type. Inheritance and interfaces don't help. And if they cannot implement max or swap or linear search, what chances do they have to implement really complex stuff? These are my litmus tests: if a language allows me to implement max and swap and linear search generically — then it has some potential.

Posted via RSDN NNTP Server 1.9
Re[6]: : Re[4]: [3]: : Re[2]: : True OOP
От: Poudy Россия  
Дата: 17.01.05 11:53
Оценка: :)
Здравствуйте, alexeiz, Вы писали:

A>Менее удобно? "Полнофункциональные" объекты, т.е OOP — полезная штука, но она не всесильна. Во многих случаях более подходящими оказываются другие парадигмы. Где ты был 10 лет назад, когда STL была спроективована?

Я тогда еще не родился.

A>Думаешь не было OO библиотек для достижения той-же самой цели? Были и много. Но не выжили. Для C++ болезнь OOP — это уже давно пройденный этап. Другие языки прийдут к этому позднее (если вообще прийдут).

А что ты имеешь тут в виду под ООП? Наследование?

A>А вот, кстати, мнение самого Степанова:

A>

Question:
A>This mean a radical change of mind from both imperative and OO thinking. What are the benefits, and the drawbacks, of this paradigm compared to the "standard" OO programming of SmallTalk or, say, Java?
Это чистая правда.

A>Answer:
A>My approach works, theirs does not work. Try to implement a simple thing in the object oriented way, say, max. I do not know how it can be done. Using generic programming I can write [...]. Try doing it in Java. You can't write a generic max() in Java that takes two arguments of some type and has a return value of that same type. Inheritance and interfaces don't help. And if they cannot implement max or swap or linear search, what chances do they have to implement really complex stuff? These are my litmus tests: if a language allows me to implement max and swap and linear search generically — then it has some potential.

Ну заете ли... Можно и так сказать:

Попробуйте-ка реализовать динамический вызов Smalltalk или полиморфный стек StrongTalk на шаблонах C++, и чтобы скорость была приемлемой. Ха! Обломитесь. Мой подход работает, а их — нет. И вообще, для меня критекрием хорошего языка является то, что он называется Smalltalk. Если язык называется Smalltalk — в нем есть потенциал.


Он тут явно использует семантическую подмену "Inheritance and interfaces don't help" на "Inheritance and interfaces are useless".
Re[7]: : Re[4]: [3]: : Re[2]: : True OOP
От: _vovin http://www.pragmatic-architect.com
Дата: 17.01.05 12:51
Оценка: 5 (2)
Poudy wrote:

> A>А вот, кстати, мнение самого Степанова:

> A>

Question:
> A>This mean a radical change of mind from both imperative and OO thinking. What are the benefits, and the drawbacks, of this paradigm compared to the "standard" OO programming of SmallTalk or, say, Java?
> Это чистая правда.
>
> A>Answer:
> A>My approach works, theirs does not work. Try to implement a simple thing in the object oriented way, say, max. I do not know how it can be done. Using generic programming I can write [...]. Try doing it in Java. You can't write a generic max() in Java that takes two arguments of some type and has a return value of that same type. Inheritance and interfaces don't help. And if they cannot implement max or swap or linear search, what chances do they have to implement really complex stuff? These are my litmus tests: if a language allows me to implement max and swap and linear search generically — then it has some potential.


Тут Степанов перебарщивает.
Такое ощущение, что ООП он значет только по Java.

Например, вот реализация max в Smalltalk:
Magnitude>>max: operand
    ^self < operand
        ifTrue:  [operand]
        ifFalse: [self]


Magnitude является базовым классом для всех числовых типов, а так же для
даты и времени.

Тут еще может возникнуть вопрос, что реализация привязана к конкретной
иерархии. Но и он разрешим статической/динамической композиции классов,
реализуемой с помощью Traits/Mixins.

Если же взять CLOS, то там можно сделать что-то подобное
(defmethod max ((operand1 number) (operand2 number))
     (if (< operand1 operand2) operand2 operand1))


В нем ООП реализовано посредством generic functions, что снимает и
проблему симметрии получателя-параметров.
Posted via RSDN NNTP Server 1.9
Re[8]: Согласен
От: Poudy Россия  
Дата: 17.01.05 13:28
Оценка:
Но всё-таки я хотел обсудить детали реализации на C++/C#/Java.
Выработать совет при построении иерархий в этих языках, считая что template'ов как бы нет в природе.
Re[9]: Согласен
От: _vovin http://www.pragmatic-architect.com
Дата: 17.01.05 13:33
Оценка: +1
> Но всё-таки я хотел обсудить детали реализации на C++/C#/Java.
> Выработать совет при построении иерархий в этих языках, считая что template'ов как бы нет в природе.

Совет — нечего мучаться.
Posted via RSDN NNTP Server 1.9
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.