Автор Тема: Почему наследование не может быть основой ОС?  (Прочитано 53556 раз)

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #30 : Январь 27, 2013, 07:01:31 am »
Совершенно верно! Если в советское время мы шли покупать обувь, то однозначно покупали сапоги кирзовые 43 размера... Всем всё было понятно... но не всегда удобно (плата за однозначность понимания.. видимо?).

Ну так то же самое и с goto. То, что кому-то удаётся его успешно использовать, не отменяет того факта, что в большинстве случаев применения в массовой разработке оно будет вести к запутыванию.
Вы не ставите простоту понимания, ясность структуры программы на первое место?
Во-первых, почему должно возникать "запутывание"? Что такое "массовая разработка"? Может быть речь о многократном использовании?
Во-вторых, я вообще не говорил о программах... А на ясность системы... наследование реализации и интерфейсы уровней системы (а не сущностей!) имеют только положительное влияние... Делают её и проще, и эффективнее, и удобнее.

Цитировать
Это ещё один, кстати, пример, откуда потом берётся жирность IDE. Потому что распутывать клубок структуры программы в подобных случаях без поддержки IDE очень трудно.
Да, иметь выбор всегда... несколько затратнее, чем не иметь оного... Но мы об удобстве или о "шашечках"?
Иметь столь запутанную структуру, которую нельзя понять простым изучением исходника и просто уложить в голову - Вы называете удобством?
Удобством я называю возможность использовать то, что наиболее подходит для данной ситуации. А неудобством... сапоги кирзовые 43 размера для всех ситуаций... Откуда берётся Ваш тезис о "запутанности структуры" для меня так и осталось загадкой.

Цитировать
Какая разница... сосуществуют ли объекты во время исполнения или нет?.. Две версии, под каждую "ось" всё равно придётся иметь... И классы будут разными...

Ещё хуже, если вам нужно иметь во время выполнения разные реализации X. Т.е. некоторые экземпляры Y должны иметь в своей базе одну реализацию X, некоторые - другую.

Пусть у Вас есть BaseButton, класс с реализацией. От него выстроено целое дерево наследования всяких разных кнопок. В стиле VCL. И внезапно нам нужна кроссплатформенность. У нас появляется две реализации BaseButton - под Винду и Линукс. Если мы так и оставим код реализации внутри класса BaseButton, то получим две параллельных версии одного класса, одного исходника. Проблему с управлением ими и проч.
Простите... тут я не понял... о каких "проблемах управления" идёт речь? О том, что ОС сообщает о том, что курсор "мышки" "наехал" на клавишу"... то, что пользователь нажал "клавишу"?.. То есть, проблема в том, что не был абстрагирован уровень взаимодействия с ОС?.. Ну, так о чём печаль-то?.. Надо просто поступать более обдуманно.

Большинству, конечно, не привыкать, но я так не хочу - потому что умею делать такие архитектуры, при которых каждый класс существует только в единственном варианте (только линейный порядок дорабатываемых версий).
Да, многие из нас родом из СССР... Я тоже так умею, но... не считаю, что это правильно.

Любая вариативность делается отдельными классами.
... посредством наследования реализации?..

Другой выход, как я и говорил, не оставлять код реализации внутри класса BaseButton, а сделать pointer to implementation. Интерфейс ButtonImpl, разные его реализации - и втыкать в BaseButton статическим полем указатель на реализацию.

Но я бы изначально не ввязался с этим Буттоном в трясину наследования.
Правильно... нечего баловать... сапоги кирзовые 43 размера... для всех... даже для тех у кого 38 размер... или 45...

Имел бы интерфейс AbstractButton и никому не видимую базовую реализацию BaseButton, создаваемую через фабрику.
И в любых расширенных кнопках просто имел бы поле base: AbstractButton, через которое агрегировал BaseButton.

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

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #31 : Январь 27, 2013, 07:11:10 am »
Где-то год назад в разговоре с Вами я приводил пример, как архитектура, в которой классы реализаций сокрыты (известны только интерфейсы и фабрики) позволяет решать "системные вопросы". Вам тогда ещё, насколько я помню, понравилось.
Мне и сейчас это нравится. Сокрытие реализации - весьма полезно. Интерфейсы специфицированы на определённом уровне системы. Всё правильно, давно отработано и удобно для использования и разработчиками и пользователями.

Повторю здесь, думаю, уместно:

Цитата: alexus
Строго говоря... элементы не должны взаимодействовать между собой... напрямую. Они должны делать только то, что им предписано... свыше. Сделали и отдали наверх, а кто там и как дальше работает, они не ведают. Если элемент (компонент/объект) А взаимодействует с элементом Б, то это взаимодействие должно быть определено, как минимум в элементе А, но, возможно, и в элементе Б, а это, в свою очередь, означает, что элемент А не может использоваться без элемента Б и, наоборот. Такая связь "цементирует" элементы и лишает систему гибкости (возможности перестраивать связи). "Слабые связи" в системе исчезают... а за ними и сама система становится монолитом, то есть, не-системой.

Конечно, это так. Но во многих случаях надсистема не занимается "ручной передачей" каждого события между компонентами.
Ручной?.. Она просто передаёт события/сообщения от отправителя к получателю.

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

При активном использовании в качестве интерфейсов абстрактных типов и при полном сокрытии их реализаций (т.е. одноуровневое наследование, с полным скрытием неабстрактного наследника), и использовании композиции объектов всё получается системно.
В качестве "труб" между ними оказываются указатели и операции абстрактных интерфейсов, доступные через эти указатели.
Тоже правильно.
А теперь добавьте вариабельность... от ситуации... и это добавит удобства/гибкости... при полном сохранении ясности. В чём проблема-то?..

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

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #32 : Январь 27, 2013, 07:36:38 am »
Во-первых, почему должно возникать "запутывание"?
...
Откуда берётся Ваш тезис о "запутанности структуры" для меня так и осталось загадкой.
Ну это-то как раз легко понять:

Закон Мерфи.
Если какая-нибудь неприятность может случиться, она случается.
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Почему наследование не может быть основой ОС?
« Ответ #33 : Январь 27, 2013, 08:46:52 am »
Для тех, кто до конца не понимает, почему наследование реализации - зло и почему его сравнивают даже с goto.
...
Вы это кому повествуете?
Цитата: ilovb
Автор говорил именно о наследовании реализации?

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #34 : Январь 27, 2013, 10:58:49 am »
Сокрытие реализации - весьма полезно.
Сокрытие реализации и наследование реализации исключают друг друга. В большинстве случаев.

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #35 : Январь 27, 2013, 11:09:18 am »
Сокрытие реализации - весьма полезно.
Сокрытие реализации и наследование реализации исключают друг друга. В большинстве случаев.
Ни в коей мере...

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #36 : Январь 27, 2013, 11:43:03 am »
Чтобы выполнить наследование реализации, к ней должен быть доступ. А чтобы иметь доступ, нужно как минимум отсутствие сокрытия.

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #37 : Январь 27, 2013, 11:59:32 am »
Чтобы выполнить наследование реализации, к ней должен быть доступ. А чтобы иметь доступ, нужно как минимум отсутствие сокрытия.
Для наследования доступ не нужен. Берём то, что есть и добавляем то, что считаем необходимым.

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #38 : Январь 27, 2013, 12:11:04 pm »
В таком случае, я под наследованием реализации в этой теме понимал другое: наследуемся и используем список методов родителя как библиотеку.

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #39 : Январь 27, 2013, 02:01:31 pm »
В таком случае, я под наследованием реализации в этой теме понимал другое: наследуемся и используем список методов родителя как библиотеку.
Насколько я понимаю в данном вопросе... есть "наследование" интерфейса (interface inheritance) и наследование реализации (implementation inheritance).
Наследование интерфейса... это вообще говоря... не наследование, а получение (присвоение) сигнатуры. Зачем это обозвали "наследованием"... трудно объяснить, путаницу внесли... только.
Наследование реализации может иметь несколько "уровней" защиты кода.

adva

  • Sr. Member
  • ****
  • Сообщений: 385
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #40 : Январь 27, 2013, 02:14:08 pm »
Наследование реализации может иметь несколько "уровней" защиты кода.
Если не сложно, приведите, пожалуйста, пример, чтобы было более понятно. То что хотел сказать Илья из его примера вроде бы понято, а Ваши высказывания без примера не воспринимаются

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #41 : Январь 27, 2013, 02:29:01 pm »
Наследование реализации может иметь несколько "уровней" защиты кода.
Если не сложно, приведите, пожалуйста, пример, чтобы было более понятно. То что хотел сказать Илья из его примера вроде бы понято, а Ваши высказывания без примера не воспринимаются
Нет проблем... см. слова public, protected, private (С++, Java, Delphi etc.)...

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #42 : Январь 27, 2013, 05:10:56 pm »
Нет проблем... см. слова public, protected, private (С++, Java, Delphi etc.)...

К наследованию реализации имеет отношение только protected. Когда я его (protected) вижу в коде - у меня заранее начинает болеть голова и хочется идти за очередной чашкой кофе. Предстоит очередное распутывание кода с прыжками (goto, ага) между разными кусками куда, завязанными между собой самыми причудливыми образами.

alexus

  • Гость
Re: Почему наследование не может быть основой ОС?
« Ответ #43 : Январь 27, 2013, 05:19:21 pm »
Нет проблем... см. слова public, protected, private (С++, Java, Delphi etc.)...

К наследованию реализации имеет отношение только protected. Когда я его (protected) вижу в коде - у меня заранее начинает болеть голова и хочется идти за очередной чашкой кофе. Предстоит очередное распутывание кода с прыжками (goto, ага) между разными кусками куда, завязанными между собой самыми причудливыми образами.
Наследование реализации не зависит от этих... эпитетов... Это уровни защиты кода/ограничения видимости, не более того...

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Почему наследование не может быть основой ОС?
« Ответ #44 : Январь 27, 2013, 06:10:54 pm »
Для тех, кто до конца не понимает, почему наследование реализации - зло и почему его сравнивают даже с goto.

Вот вам строка: obj.DoSomething. Если я знаю, что в системе нет наследования реализации, я понимаю, что именно будет выполненно. Процедура DoSomething того фактического типа, который имеет obj.
Ответьте на тот же вопрос, если система пронизана наследованием реализации. Попробуйте разобраться, как прыгает поток управления, даже при вызове метода одного объекта. Вызвали из своего метода свой же другой метод - управление упрыгало фиг знает в какого предка...
Если мы имеем нечто вроде "A* obj" (пусть у нас С++), где A это конкретный (не абстрактный) класс, то даже если он от кого-то там унаследовался (по реализации естественно), то узнать что именно случится если будет вызвано obj->DoSomething() довольно просто - в худшем случае придется обойти ациклический ориентированный граф.

А вот если "A" - это интерфейс, то все, алес. Узнать что именно произойдет при вызове obj->DoSomething() не представляется возможным - там может быть абсолютно что угодно. В общем случае единственным способом узнать это - использовать пошаговый отладчик. В точности то же самое, что и в случае goto (и то же что и при использовании процедурных типов).

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

Это ещё один, кстати, пример, откуда потом берётся жирность IDE. Потому что распутывать клубок структуры программы в подобных случаях без поддержки IDE очень трудно.
Ну да, ну да. А если у нас интерфейсы, то хоть через жирную IDE, хоть без оной, распутать клубок не возможно даже теоретически. Поэтому там жиные IDE и не нужны :-)

(на самом деле "жирные" IDE нужны для проектов реального размера, то есть с полмиллиона строк кода)

Второй пример: у вас есть наследование реализации от какого-то типа X. И вдруг вам нужно завести несколько реализаций X. Более простой случай - если реализации не сосуществуют во время выполнения. Например, под разные ОС. Вам придётся иметь две версии одного исходника, как-то их переключать, вместо того, чтобы просто иметь два отдельных класса - реализации базового абстрактного. При наследовании только от абстрактных классов получается придерживаться принципа - каждый вариант реализации существует в виде своего модуля, класса, и т.п. А не дремучая вариативность на уровне исходников.
Ничего не понял. Не вижу разницы. Хоть у меня интерфейс и его реализация, хоть два класса в иерархии наследования реализации, один фиг для операционной системы A у меня будет исходник Xa, для операционной системы B у меня будет Xb, и все. Выбор реализации для сборки ложится на плечи системы сборки. Тот кто отнаследовался от X, тому глубоко будет пофиг что там внизу на самом деле - Xa, или Xb.

Ещё хуже, если вам нужно иметь во время выполнения разные реализации X. Т.е. некоторые экземпляры Y должны иметь в своей базе одну реализацию X, некоторые - другую.
А кто-то предлагал наследование реализации как ЕДИНСТВЕННЫЙ механизм для декомпозиции задачи?

PS. Проблема наследования реализации, да и вообще наследования, не в том что ты описываешь, а в том, что это слишком высокоуровневый и весьма специфичный механизм. Как и любой подобный механизм, оно с блеском решает ряд задач, и с блеском же проваливает другую часть задачек. Это как "контент как интерфейс" в ББ - для узкого ряда задач оно отлично работает, а для других задач оно не применимо в принципе (хотя можно попробовать натянуть, получив в результате неюзабельную переусложненную какашку). Но это же не повод отказываться от подобного мезанизма вообще?
Y = λf.(λx.f (x x)) (λx.f (x x))