Нужно ли нам наследование реализаций? :)
От: Tom Россия http://www.RSDN.ru
Дата: 18.02.13 17:54
Оценка: 9 (3)
Испугались?


Всем привет!
На самом деле хочется ещё раз поднять тему наследования реализаций.
После погружения в Dependency Injection практику программирования стало ясно, что наследование создает очень сильную связь между наследником и базовым классом.
Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.
И даже если уж так нужно именно наследование реализации (допущу что в редких случаях оно может понадобится) то какие обходные пути есть.
Первое что приходит в голову — использовать включение. Конечно оно повлечет некоторый "синтаксический оверхэд" , но всё же этот вариант присуствует.
Особенно он будет хорошо смотреться в некоторых языках в которых код можно генерировать налету (не будем называть такие языки вслух )
Какие есть ещё варианты реализации наследования реализации без использования собственно самого наследования.
И в целом какие будут мысли:

PS:
Интересно не задумывался ли кто о написании языка который был бы изначально дружелюбным к Dependency Injection-у.
Т.е. в котором не было бы операции инстанциирования конкретного класса а только получение инстанса каким либо образом по его интерфейсу.

PPS:
Проще обсуждение вести в контексте языка C# & .NET в целом.
Народная мудрось
всем все никому ничего(с).
Re: Нужно ли нам наследование реализаций? :)
От: Abyx Россия  
Дата: 18.02.13 18:02
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Проще обсуждение вести в контексте языка C# & .NET в целом.


при CRTP (статическом полиморфизме) происходит наследование реализаций.
в C# такого наверное нету.
In Zen We Trust
Re: Нужно ли нам наследование реализаций? :)
От: dimgel Россия https://github.com/dimgel
Дата: 18.02.13 18:15
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Интересно не задумывался ли кто о написании языка который был бы изначально дружелюбным к Dependency Injection-у.

Tom>Т.е. в котором не было бы операции инстанциирования конкретного класса а только получение инстанса каким либо образом по его интерфейсу.

Вместо одного класса писать пару интерфейс+класс? Увольте.

А язык дружелюбный есть, ага. Прямо в книге Одерски подход описан, и сказано, что это типа замена DI. Впрочем, это не совсем DI, это не-очень-доброе старое ручное связывание, но по сравнению, скажем, с "классическим" (до аннотаций) Spring-ом, где все эти же связи прописывались в XML (громоздко до тошноты и легко напортачить), здесь у нас static type checking. И суммарно система стала проще (IoC-контейнер не нужен, AOP не нужен, долгое сканировование классов в поисках аннотаций при запуске не нужно).

// Классы с зависимостями.
class A { def s = "world" }
class B(a: A) { def s = "hello " + a.s }
class C(a: A, b: B) { def main() { println(b.s + ", goodbye " + a.s) }}

object MyApp extends App {
    // Выполняем связывание (если простыня длинная, или несколько длинных и похожих 
    // в разных точках входа, её можно произвольно декомпозировать средствами языка).
    val a = new A
    val c = new C(a, new B(a))

    // Запускаем приложение.
    c.main()
}
Re: Нужно ли нам наследование реализаций? :)
От: dimgel Россия https://github.com/dimgel
Дата: 18.02.13 18:24
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.

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

А по теме имею сказать следующее: люблю я всякие data-driven алгоритмы клепать. Но иногда случается такое, что по мере усложнения задачи растёт сложность управляющих метаданных, и в итоге единственный разумный выход — превратить иерархию пассивных структур в иерархию стратегий, т.е. вынести часть логики из алгоритма в метаданные. И вот тут просто с целью убирания задвоений кода часть этого кода частенько перемещается в protected final методы базового класса. Оно короче и понятнее выходит, чем если поднимать на щит "нет наследованию!" и плодить всякие хелперы сбоку-припёку, да ещё и с более широкой областью видимости.

Ну и "каркасом" тоже иногда балуюсь, хотя гораздо реже.
Re[2]: Нужно ли нам наследование реализаций? :)
От: dimgel Россия https://github.com/dimgel
Дата: 18.02.13 18:40
Оценка:
Здравствуйте, dimgel, Вы писали:

D>Оно короче и понятнее выходит, чем если поднимать на щит "нет наследованию!" и плодить всякие хелперы сбоку-припёку, да ещё и с более широкой областью видимости.


Особенно если стратегии stateful (в этом случае время их жизни ограничено потрохами алгоритма) — передавать состояние хелперам запаришься.
Re: Нужно ли нам наследование реализаций? :)
От: AlexRK  
Дата: 18.02.13 18:48
Оценка: +1 :)
Здравствуйте, Tom, Вы писали:

Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.


Не нужно.

Tom>Первое что приходит в голову — использовать включение. Конечно оно повлечет некоторый "синтаксический оверхэд" , но всё же этот вариант присуствует.


Ну да, агрегация. Да и оверхеда большого не должно быть, ИМХО.
Re: Нужно ли нам наследование реализаций? :)
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 19.02.13 00:23
Оценка: +1
Здравствуйте, Tom, Вы писали:

Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.


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

Tom>Первое что приходит в голову — использовать включение. Конечно оно повлечет некоторый "синтаксический оверхэд" , но всё же этот вариант присуствует.


У агрегации с автоматической делегацией реализации контракта есть свои тараканы.
... << RSDN@Home 1.2.0 alpha 5 rev. 23 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: Нужно ли нам наследование реализаций? :)
От: Tom Россия http://www.RSDN.ru
Дата: 19.02.13 05:14
Оценка:
Tom>>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.
AVK>Нужна возможность подключения реализаций существующих контрактов. Соответственно, ответ очень простой — если есть лучшая альтернатива, то наследование реализации не нужно.
Мне нравится слово подключение.

Tom>>Первое что приходит в голову — использовать включение. Конечно оно повлечет некоторый "синтаксический оверхэд" , но всё же этот вариант присуствует.


AVK>У агрегации с автоматической делегацией реализации контракта есть свои тараканы.

Какие?
Народная мудрось
всем все никому ничего(с).
Re: Нужно ли нам наследование реализаций? :)
От: C.A.B LinkedIn
Дата: 19.02.13 07:11
Оценка:
Здравствуйте, Tom, Вы писали:
Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.
Не то чтобы нужно, а скорей часто удобно. Из вариантов реализации наследования, лично мне нравятся Scala-traits.

Tom>PS:

Tom>Интересно не задумывался ли кто о написании языка который был бы изначально дружелюбным к Dependency Injection-у.
Tom>Т.е. в котором не было бы операции инстанциирования конкретного класса а только получение инстанса каким либо образом по его интерфейсу.
Я задумываюсь
Автор: C.A.B
Дата: 12.02.13
.
Между тем,что я думаю,тем,что я хочу сказать,тем,что я,как мне кажется,говорю,и тем,что вы хотите услышать,тем,что как вам кажется,вы слышите,тем,что вы понимаете,стоит десять вариантов возникновения непонимания.Но всё-таки давайте попробуем...(Э.Уэллс)
Re[3]: Нужно ли нам наследование реализаций? :)
От: michael_isu Беларусь  
Дата: 19.02.13 12:20
Оценка: -1
Здравствуйте, dimgel, Вы писали:

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


D>>Оно короче и понятнее выходит, чем если поднимать на щит "нет наследованию!" и плодить всякие хелперы сбоку-припёку, да ещё и с более широкой областью видимости.


D>Особенно если стратегии stateful (в этом случае время их жизни ограничено потрохами алгоритма) — передавать состояние хелперам запаришься.


Откройте для себя еxtensions methods.
Re[4]: Нужно ли нам наследование реализаций? :)
От: dimgel Россия https://github.com/dimgel
Дата: 19.02.13 12:24
Оценка:
Здравствуйте, michael_isu, Вы писали:

_>Откройте для себя еxtensions methods.


1. Я не на шарпе.
2. Они не делают логику проще, а наоборот запутывают связность.
3. Незачем плодить странные костыли там, где работает нормальное ООП-наследование.
Re[5]: Нужно ли нам наследование реализаций? :)
От: michael_isu Беларусь  
Дата: 19.02.13 12:30
Оценка: -1
Здравствуйте, dimgel, Вы писали:

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


_>>Откройте для себя еxtensions methods.


D>1. Я не на шарпе.

Какая досада.

D>2. Они не делают логику проще, а наоборот запутывают связность.

Автора не читали, но обсуждаем? Понятно.

D>3. Незачем плодить странные костыли там, где работает нормальное ООП-наследование.

Работает до поры до времени.
Re: Нужно ли нам наследование реализаций? :)
От: michael_isu Беларусь  
Дата: 19.02.13 12:31
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.


Слишком абстрактный вопрос задаете. Лучше пример Иначе опять 30 страниц флуда ни о чем будет.
Re[2]: Нужно ли нам наследование реализаций? :)
От: Tom Россия http://www.RSDN.ru
Дата: 19.02.13 12:56
Оценка:
Здравствуйте, michael_isu, Вы писали:

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


Tom>>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.


_>Слишком абстрактный вопрос задаете. Лучше пример Иначе опять 30 страниц флуда ни о чем будет.


Да пример очень простой:


class DerivedClass : BaseClass
{
// Bl bla bla
}



Что делать если при тестировании кода мне надо подменить базовый класс?
Делать нечего, надо вешаться ибо в данном случае его не подменить, а вот если было бы так:


class DerivedClass
{
  public DerivedClass(IBaseClass baseClassImplementation)
  {
      _baseClassImplementation = baseClassImplementation;
  }
}


В данном случае зависимость не жёсткая и передать мы можем что угодно, в качестве "базового" класса.
Другое дело что если вдруг нам надо действительно расширить или поменять функционал базового класса то придётся кучу методов просто "прокидывать".
Народная мудрось
всем все никому ничего(с).
Re: Нужно ли нам наследование реализаций? :)
От: artelk  
Дата: 19.02.13 13:02
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.

+1
Единственный известный мне случай, когда оно имеет смысл — Template Method. Хотя и его можно легко "вывернуть" в Стратегию.
Re[3]: Нужно ли нам наследование реализаций? :)
От: dimgel Россия https://github.com/dimgel
Дата: 19.02.13 13:06
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Что делать если при тестировании кода мне надо подменить базовый класс?


Правильно поставленный вопрос уже содержит половину ответа, гы. В данном случае — ответ целиком.
Re[3]: Нужно ли нам наследование реализаций? :)
От: michael_isu Беларусь  
Дата: 19.02.13 13:22
Оценка: +1
Здравствуйте, Tom, Вы писали:

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


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


Tom>>>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.


_>>Слишком абстрактный вопрос задаете. Лучше пример Иначе опять 30 страниц флуда ни о чем будет.


Tom>Да пример очень простой:


Пример в смысле из жизни, реальный.

Tom>Другое дело что если вдруг нам надо действительно расширить или поменять функционал базового класса то придётся кучу методов просто "прокидывать".


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

Базовые классы иногда нужны, но должны быть очень веские причины и большие полномочия для их создания и изменения. Но в большинстве случаев туда пишут все кто хотят, не понимая последствий.
Re[4]: Нужно ли нам наследование реализаций? :)
От: Tom Россия http://www.RSDN.ru
Дата: 19.02.13 13:56
Оценка:
Tom>>Да пример очень простой:
_>Пример в смысле из жизни, реальный.
Куда реальнее, самый реальный пример из реального проекта.

Tom>>Другое дело что если вдруг нам надо действительно расширить или поменять функционал базового класса то придётся кучу методов просто "прокидывать".


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

Под базовым имелось ввиду просто класс от которого кто то наследуется.
Народная мудрось
всем все никому ничего(с).
Re: Нужно ли нам наследование реализаций? :)
От: dimgel Россия https://github.com/dimgel
Дата: 19.02.13 13:58
Оценка:
А вообще, боян. Только позавчера давал ссылку на старое обсуждение: http://www.rsdn.ru/forum/philosophy/2384478
Автор: McSeem2
Дата: 27.02.07
Re: Нужно ли нам наследование реализаций? :)
От: Философ Ад http://vk.com/id10256428
Дата: 24.02.13 03:51
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>стало ясно, что наследование создает очень сильную связь между наследником и базовым классом.


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

В таких случаях как IUnkonwn понятно, где могут быть реализованы методы AddRef() и Release()
после отмены наследования реализации именно потому, что внутри иерархии они не зовутся, но если метод базового класса планируется вызвать чуть ли не во всей иерархии, то куда его помещать — загадка, но есть и более запутанные случаи:
1)
abstract class Base {protected void BaseMethod(){}; protected abstract void Do();}
abstract class A : Base { protected void MethodA() { BaseMethod() };}
class B : A { protected void MethodB() { MethodA() }; override void Do {MethodB();} }
2)
class Control {protected virtual void WndProc(); protected virtual void DefWndProc(); }
class ScrollableControl :Control {protected override void WndProc() { base.WndProc(); } }
class ContainerControl :ScrollableControl {protected override void WndProc() { base.WndProc(); } }
class Form :ContainerControl {protected override void WndProc() { base.WndProc(); } }
class MyForm :Form {protected override void WndProc() { base.WndProc(); DefWndProc()} }

во что превратятся подобные иерархии после отмены наследования реализации?

Tom>Соответственно встает вопрос, а нужно ли наследование (реализации) вообще.


Нет не нужно.
Ровно настолько же, насколько не нужно и ООП — без него вполне можно жить.
Однако в ряде случаев оно может упростить жизнь.
Всё сказанное выше — личное мнение, если не указано обратное.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.