Трудные для ООП иерархии классов
От: Кодёнок  
Дата: 20.09.07 11:17
Оценка: 2 (2)
Я ищу примеры классов объектов, которые вызывают трудности при объектном моделировании в современных ЯП типа C++ или C#. В качестве примера, я знаю всего две классические задачи:

1. Построить иерархию классов для прямоугольника и квадрата, с изменяющимися размерами. Трудность в том, что хотя квадрат всегда является прямоугольником (наследуется), он не захочет наследовать его реализацию (зачем ему раздельно хранить ширину и высоту?). Другая трудность в том, что прямоугольник иногда может являться квадратом, но классические отношения между классами, которые предлагают ЯП (наследование и implicit-conversion) не могут выразить такого отношения.

2. Комплексное число и вещественное число. Хотя вещественное число является комплексным (наследование), вы не станете наследовать его от комплексного по многим причинам: вам не нужна его реализация (два float в памяти вместо одного), вы вряд ли будете рады тому что sqrt(4) вместо 2.0 вернёт тупл из двух комплексных чисел, и т.п.

Также буду рад услышать названия языков, которые попытались реализовать более богатый набор отношений, чем даёт классическое понимание объектно-ориентированного проектирования.
Re: Трудные для ООП иерархии классов
От: elmal  
Дата: 20.09.07 11:40
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Я ищу примеры классов объектов, которые вызывают трудности при объектном моделировании в современных ЯП типа C++ или C#. В качестве примера, я знаю всего две классические задачи:


ИМХО и в первом и во втором случае имеем неправильную иерархию. Уже писал когда-то по поводу квадрата здесь
Автор: elmal
Дата: 07.03.07


Комплексные и обычные числа — тоже самое:
Наследоваться нужно от класса 'число' (если уж вообще возникла необходимость в наследовании). Далее их можно разделить на всякие — натуральные, мнимые, действительными, положительные и т.д. Соответственно 'обычные' чиcла являются действительными, а комплексные — мнимыми.

Все описанные тобой проблемы ИМХО из-за того, что неправильно иерархии строят. Если уж строить, то строить по аналогии со школьным учебником, а там иерархии гораздо сложнее, чем в твоем примере. И тогда построить непротиворечивую эффективную иерархию не проблема, только несколько более громоздкой она получится.
Re: Трудные для ООП иерархии классов
От: Cephalopod  
Дата: 20.09.07 11:49
Оценка: 3 (1)
Здравствуйте, Кодёнок, Вы писали:

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


Coq. HOL. Axiom.

P.S. OOP stinks
Re[2]: Трудные для ООП иерархии классов
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.09.07 11:52
Оценка: 2 (1)
Здравствуйте, Cephalopod, Вы писали:

C>P.S. OOP stinks


А вот статейка на эту тему
Re[2]: Трудные для ООП иерархии классов
От: Кодёнок  
Дата: 20.09.07 12:23
Оценка:
Здравствуйте, elmal, Вы писали:

E>Наследоваться нужно от класса 'число' (если уж вообще возникла необходимость в наследовании). Далее их можно разделить на всякие — натуральные, мнимые, действительными, положительные и т.д. Соответственно 'обычные' чиcла являются действительными, а комплексные — мнимыми.


То есть предлагаешь иерархию использовать только для классификации их всех как "чисел", а автоматическую совместимость между ними реализовать через implicit conversion?

А как решить проблему sqrt?
Re[3]: Трудные для ООП иерархии классов
От: Кодёнок  
Дата: 20.09.07 12:38
Оценка:
Здравствуйте, Курилка, Вы писали:

C>>P.S. OOP stinks

К>А вот статейка на эту тему

Что-то не очень убедительная статья. Есть заявления в стиле "так вот, на самом деле это плохо и должно быть наоборот", но нет аргументов, почему. Безапелляционные утверждения — не лучший способ убедить.
Re[2]: Трудные для ООП иерархии классов
От: Кодёнок  
Дата: 20.09.07 12:41
Оценка:
Здравствуйте, Cephalopod, Вы писали:

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


C> Coq. HOL. Axiom.


Спасибо, я посмотрю.
Re[4]: Трудные для ООП иерархии классов
От: Курилка Россия http://kirya.narod.ru/
Дата: 20.09.07 12:48
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Здравствуйте, Курилка, Вы писали:


C>>>P.S. OOP stinks

К>>А вот статейка на эту тему

Кё>Что-то не очень убедительная статья. Есть заявления в стиле "так вот, на самом деле это плохо и должно быть наоборот", но нет аргументов, почему. Безапелляционные утверждения — не лучший способ убедить.


Почему безапелляционные?
Возьмём 4-й пункт "У объектов есть private состояние" — с самим утверждением не будешь спорить, надеюсь?
Джо говорит, что состояние — одна из проблем, состояние увеличивает зависимости, уменьшает расспараллеливаемость и т.д.
"Обычные" языки пытаются "спрятать" состояние (с помощью модификаторов и т.п.), тогда как в декларативных функциональных есть подаваемые данные на вход и результат на выходе.

И что здесь тебе показалось "безапелляционным"?
Скорее твоё утверждение таковым назвать следует
Re[3]: Трудные для ООП иерархии классов
От: elmal  
Дата: 20.09.07 12:58
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>То есть предлагаешь иерархию использовать только для классификации их всех как "чисел", а автоматическую совместимость между ними реализовать через implicit conversion?

В общем да, а вот в деталях может оказаться что и нет . От деталей реализации все зависит.

Кё>А как решить проблему sqrt?

А какая проблема с sqrt? sqrt(Number number) и должен возвращать набор чисел. sqrt(4) = 2 и -2 насколько я помню. И собственно когда мы его будем возвращать — эти числа должно быть наиболее адекватного типа. Ну а sqrt(-1) должен возвратить комплексное число, вроде оно наже одно (блин, уже школьную программу забываю — ужас). Если для корня определенного числа возвратится несколько значений разных типов (например одно комплексное, другое действительное), а мне нужен допустим только действительные — я могу лишние отбросить. Я бы например сделал, чтобы sqrt возвращал объект класса 'Корни'. И у этого класса можно сделать методы фильтрации по содержимому — возвратить только положительные, возвратить только действительные и т.д, возвратить как список, как массив, получить итератьр и т.д.
Re: Трудные для ООП иерархии классов
От: no4  
Дата: 20.09.07 13:35
Оценка:
Здравствуйте, Кодёнок, Вы писали:


Кё>1. Построить иерархию классов для прямоугольника и квадрата, с изменяющимися размерами. Трудность в том, что хотя квадрат всегда является прямоугольником (наследуется), он не захочет наследовать его реализацию (зачем ему раздельно хранить ширину и высоту?).


Почему прямоугольник должен ХРАНИТЬ ширину и высоту?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Трудные для ООП иерархии классов
От: no4  
Дата: 20.09.07 13:35
Оценка:
Здравствуйте, Кодёнок, Вы писали:


Кё>1. Построить иерархию классов для прямоугольника и квадрата, с изменяющимися размерами. Трудность в том, что хотя квадрат всегда является прямоугольником (наследуется), он не захочет наследовать его реализацию (зачем ему раздельно хранить ширину и высоту?).


Почему прямоугольник должен ХРАНИТЬ ширину и высоту?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Трудные для ООП иерархии классов
От: deniok Россия  
Дата: 20.09.07 14:24
Оценка: 16 (3)
Здравствуйте, Кодёнок, Вы писали:

[]

У Олега Киселёва есть на эту тему замечательные статья:

Does OOP really separate interface from implementation?

и её продолжение:

Subclassing errors, OOP style and practically checkable rules to prevent them

ЗЫ: в мире функционального программирования понимание человеком тонкостей систем типов измеряют в миллиОлегах.
Re: Трудные для ООП иерархии классов
От: COFF  
Дата: 20.09.07 15:13
Оценка: +1
Кё>1. Построить иерархию классов для прямоугольника и квадрата, с изменяющимися размерами. Трудность в том, что хотя квадрат всегда является прямоугольником (наследуется), он не захочет наследовать его реализацию (зачем ему раздельно хранить ширину и высоту?). Другая трудность в том, что прямоугольник иногда может являться квадратом, но классические отношения между классами, которые предлагают ЯП (наследование и implicit-conversion) не могут выразить такого отношения.

Кё>2. Комплексное число и вещественное число. Хотя вещественное число является комплексным (наследование), вы не станете наследовать его от комплексного по многим причинам: вам не нужна его реализация (два float в памяти вместо одного), вы вряд ли будете рады тому что sqrt(4) вместо 2.0 вернёт тупл из двух комплексных чисел, и т.п.


Мне кажется, что иерархия объектов — это не что-то объективно существующее, а всего лишь модель, которая позволяет нам более-менее адекватно описывать предметную область. Соответственно и примеры, данные выше, надо рассматривать в контексте области применения.
Вот предположим, что у нас есть прямоугольник, который может произвольным образом менять свои размеры, соответственно, максимум, что мы можем тут сделать — это ввести признак isSquare. Если же объекты у нас создаются один раз, а потом рисуются и метод рисования квадрата отличается от метода рисования прямоугольника (эффективнее), то класс квадрата и класс прямоугольника могут быть связаны только через общий класс-предок (например, фигура), и выбирать, объект какого класса должен быть создан должна соответствующая фабрика. Ну и так далее...
С комплексными числами то же самое. Подумайте, зачем они вам нужны и принимайте решение, исходя из этого.
Re: Трудные для ООП иерархии классов
От: Igor Trofimov  
Дата: 20.09.07 18:22
Оценка: 3 (1) +4
Кё>1. Построить иерархию классов для прямоугольника и квадрата, с изменяющимися размерами. Трудность в том, что хотя квадрат всегда является прямоугольником (наследуется), он не захочет наследовать его реализацию (зачем ему раздельно хранить ширину и высоту?). Другая трудность в том, что прямоугольник иногда может являться квадратом, но классические отношения между классами, которые предлагают ЯП (наследование и implicit-conversion) не могут выразить такого отношения.

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

Рассмотрим, что вам нужно в программе:

1) У любой фигуры есть положение (Location).
2) У фигуры "прямоугольник" задается ширина и высота. Это два независимых параметра, которые можно менять.
3) У фигуры "квадрат" задается размер стороны. Этот параметр можно менять.

Вот исходя из этих исходных данных можно совершенно определенно сказать, что "квадрат" никак не может являться "прямоугольником"!
Потому что у него нет двух независимых параметров "ширина" и "высота".

Откуда вы вообще взяли, что "квадрат всегда является прямоугольником"? Кто вам сказал этот бред?
Вот здесь кроется ошибка!
Вы это взяли из ДРУГОЙ МОДЕЛИ, из геометрии. Но там квадрат и прямоугольник — это СОВСЕМ ДРУГОЕ. Нечто, совсем непохожее, как бы вам не казалось на первый взгляд!
Там вообще нет таких понятий как "менять высоту", например Там это вообще — не объект с параметрами и поведением, а некое геометрическое место точек И с позиции тех свойств, в той модели, да, квадрат, определенно является прямоугольником. Но при чем тут ваша программа?!

Надеюсь, доходчиво объяснил, почему эта иерархия не трудна для ООП
Re[2]: Трудные для ООП иерархии классов
От: deniok Россия  
Дата: 20.09.07 18:38
Оценка: +3 :)
Здравствуйте, Igor Trofimov, Вы писали:

iT>Очень много проблем от того, что интуитивно вы смешиваете ту модель, которая вам нужна в программе с той моделью, которая у вас в голове, от реального мира, от геометрии, и т.п.

iT>Вот про вторую надо забыть

На всякий случай : я полностью согласен с поскипаным объяснением.

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

ОО проектирование легко позволяет моделировать окружающий мир. Видим в нём сотрудников — делаем класс Employee, видим начальника — делаем класс Manager, поскольку начальник is a сотрудник (в окружающем мире так) пользуем наследование.

Так вот проблемы с квадратом и прямоугольником как раз показывают, что по большому счёту эта простая схема — впендюринг.
Re: Трудные для ООП иерархии классов
От: mkizub Литва http://symade.tigris.org
Дата: 20.09.07 20:26
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>Я ищу примеры классов объектов, которые вызывают трудности при объектном моделировании в современных ЯП типа C++ или C#. В качестве примера, я знаю всего две классические задачи:


Кё>1. Построить иерархию классов для прямоугольника и квадрата, с изменяющимися размерами. Трудность в том, что хотя квадрат всегда является прямоугольником (наследуется), он не захочет наследовать его реализацию (зачем ему раздельно хранить ширину и высоту?). Другая трудность в том, что прямоугольник иногда может являться квадратом, но классические отношения между классами, которые предлагают ЯП (наследование и implicit-conversion) не могут выразить такого отношения.


Кё>2. Комплексное число и вещественное число. Хотя вещественное число является комплексным (наследование), вы не станете наследовать его от комплексного по многим причинам: вам не нужна его реализация (два float в памяти вместо одного), вы вряд ли будете рады тому что sqrt(4) вместо 2.0 вернёт тупл из двух комплексных чисел, и т.п.


3. List<String> и List<Object>.

Вообще вышеприведённые примеры показывают трудности объектного моделирования как такового, а не просто в современных языках.

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


А какие ещё отношения ты знаешь?

Идея наследования — это идея расширения (или сужения, в зависимости от ко- или контр-вариантного наследования) интерфейса, сиречь операций которые можно произвести с данным объектом. Какое ещё действие по отношению к интерфейсу ты можешь себе вообразить (кроме операции добавить/убавить набор операций)? Перетасовать их?
SOP & SymADE: http://symade.tigris.org , блог http://mkizub.livejournal.com
Re[2]: Трудные для ООП иерархии классов
От: deniok Россия  
Дата: 20.09.07 21:33
Оценка:
Здравствуйте, mkizub, Вы писали:

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


M>А какие ещё отношения ты знаешь?


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


Ну в Haskell есть Multi-parameter type classes:

-- Интерфейс, задающий отношение изоморфизма между типами
class Iso a b where
 iso :: a -> b
 osi :: b -> a

-- Пример реализации
instance Iso a a where
 iso = id
 osi = id


Фишка в том, что интерфейс выставляется не одним типом, а двумя. VTBL приклеивается не к "объекту", а к методам интерфейса.
Re[3]: Трудные для ООП иерархии классов
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.09.07 03:06
Оценка: +3
Здравствуйте, deniok, Вы писали:

D>Однако есть один момент. Когда ООП-ники говорят про преимущества ООП, одним из основных аргументов служит следующий:


D>ОО проектирование легко позволяет моделировать окружающий мир. Видим в нём сотрудников — делаем класс Employee, видим начальника — делаем класс Manager, поскольку начальник is a сотрудник (в окружающем мире так) пользуем наследование.


Прикольно. Самое смешное, что я не могу вспомнить такого аргумента. Ну то есть я знаю, что это наверняка из-за того, что я читал мало книжек. Но вообще-то, основной аргумент за ООП никак не связан с моделированием реального мира. Основной аргумент — это борьба со связностью программы, благодаря инкапсуляции и полиморфизму. Вышеописанный подход — это какое-то неправильное ООП. В реальном программировании так никогда не делается. Где вы видели отнаследованного от сотрудника начальника?
В нормальном ООП, скорее всего, и сотрудник и начальник будут просто строчками в базе данных, при этом никто ни от кого не будет наследоваться, а будет связь между человеком и позицией, причем один-ко-многим, и будет интерфейс IHumanResources, отвечающий за назначение должностей и прочие простые штуки. И будет куча реализаций этого интерфейса — поверх XML файла для микроконтор, и поверх MS SQL Server Enterprize Edition для корпораций. И будет отнаследованный от него интерфейс типа IAdvancedHumanResources, в котором помимо базовой функциональности будет масса возможностей вроде поддержки организации проектных команд, планирования аттестаций и учета вакансий.
Очевидно, что ни один из этих классов не имеет никаких аналогов в реальном мире. Тем не менее, преимущества ООП по сравнению с, к примеру, процедурным программированием, также очевидны.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Трудные для ООП иерархии классов
От: Igor Trofimov  
Дата: 21.09.07 05:45
Оценка: 8 (2) +5
D>Однако есть один момент. Когда ООП-ники говорят про преимущества ООП, одним из основных аргументов служит следующий:
D>ОО проектирование легко позволяет моделировать окружающий мир. Видим в нём сотрудников — делаем класс Employee, видим начальника — делаем класс Manager, поскольку начальник is a сотрудник (в окружающем мире так) пользуем наследование.

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

Какая, нах, модель реального мира? Какие объекты из реального мира моделирует компилятор? База данных? Или игра "тетрис"?
Программа реализует некоторую модель вашей предметной области, которая может иметь весьма мало общего с реальным миром.
Процедурный подход реализует модель "тетриса" процедурно. ООП — реализует ту же, по сути, модель, но объектно, что действительно удобно, т.к. конструкции языка ближе к структуре самой модели.


D>Так вот проблемы с квадратом и прямоугольником как раз показывают, что по большому счёту эта простая схема — впендюринг.


Думаю, даже не впендюринг, а реально заблуждение некоторых. Маленькая такая неточность, которая иногда может вылиться в большие проблемы (это вообще свойственно маленьким неточностям).
Re[2]: Трудные для ООП иерархии классов
От: Кодёнок  
Дата: 21.09.07 06:46
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Очень много проблем от того, что интуитивно вы смешиваете ту модель, которая вам нужна в программе с той моделью, которая у вас в голове, от реального мира, от геометрии, и т.п.

iT>Вот про вторую надо забыть

Это с какой стати? Вообще-то я моделирую предметную область с помощью средств языка программирования. С какого перепуга я должен забыть о предметной области?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.