Russian Qt Forum
Ноябрь 23, 2024, 08:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: Dependency injection  (Прочитано 20555 раз)
once_again_abc
Гость
« Ответ #15 : Сентябрь 01, 2014, 06:47 »

...


Спасибо за ссылки и особенное спасибо за отличное объяснение DI и IoC!
Записан
Bepec
Гость
« Ответ #16 : Сентябрь 01, 2014, 08:39 »

Угу Улыбающийся Самое важное упущение - нет практического применения. Точнее я его не вижу, мб потом найдётся задачка Улыбающийся

В любом случае спасибо за объяснение.

PS но если сложное нельзя объяснить простыми словами - то либо неполное знание предмета, либо предмет не имеет четкой сформулированности и он больше как "теория".
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #17 : Сентябрь 01, 2014, 13:45 »

Вуаля. Мы сделали внедрение зависимости. За громким названием скрывается достаточно простой принцип. Мы "засовываем" один объект внутрь другого, внедряем его. Мы внедряем объект, от которого зависит BookStorage.

Получаем, классу BookStorage больше не нужно создавать Database самостоятельно, он просто им пользуется, и мы легко можем менять реализации Database. Надеюсь, разжевывать преимущества второго подхода над первым не нужно. Вот об этом и был тот пост. Он просто проиллюстрировал один из вариантов внедрения зависимости (внедрение зависимости через конструктор).

Где здесь анти-паттерн?

Анти-паттерн в том, что класс BookStorage в этом случае вообще становится не нужным.
ООП головного мозга такое ООП - плодите кучу бесполезной ботвы, к тому же вредной - усложнение конструкции за счет непомерного раздувания оо-архитектуры кучей ненужных и избыточных сущностей.

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

Вы взяли и вытащили кишки наружу. Теперь пользователям самим нужно геммороиться по созданию объекта БД, его и его настройке.
Но если так: тогда накой черт вообще нужен класс BookStorage?

Принцип действия этого анти-паттерна можно выразить словами: давайте нарушим инкапсуляции, и вытащим кишки класса наружу. И предложим пользователям самостоятельно поиметь геммор со всем этим.


зы:

Чем то мне это напоминает паттерн "стратегия".

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


Записан
once_again_abc
Гость
« Ответ #18 : Сентябрь 01, 2014, 14:04 »


Анти-паттерн в том, что класс BookStorage в этом случае вообще становится не нужным.
ООП головного мозга такое ООП - плодите кучу бесполезной ботвы, к тому же вредной - усложнение конструкции за счет непомерного раздувания оо-архитектуры кучей ненужных и избыточных сущностей.


такая иррациональная упертость сродни религиозному фанатизму.
Записан
Bepec
Гость
« Ответ #19 : Сентябрь 01, 2014, 14:19 »

Ну так поясните упёртым и непонимающим, в чем смысл? В чем плюс? В чем потенциал паттерна?

Пример: паттерн model-View позволяет разделить данные и их отображение. Польза? Польза. Можно отображать как хочешь и что хочешь, не меняя модель.

Кроме раздутия архитектуры, нарушении инкапсуляции ("вытаскивание кишков наружу", согласен), внедрения прослойки (опять таки внедрённой только ради внедрения) я ничего не вижу.

ООП обычное - класс "машина" с 4 слотами под класс "колёса" с унифицированным интерфейсом.
Получаем "Любая машина с любыми колёсами".

С DI - класс прослойка, который знает всё о классах машины, колёс, знает принципы их взаимодействия, класс машина с 4 слотами под класс "колёса" с унифицированным интерфейсом.
Получаем "Любая машина с любыми колёсами" и прослойкой. Смысл?

PS специально выделил цветом, что одинаково в обоих случаях.
« Последнее редактирование: Сентябрь 01, 2014, 14:20 от Bepec » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #20 : Сентябрь 01, 2014, 18:42 »

такая иррациональная упертость сродни религиозному фанатизму.

Как насчет заменить фразу "религиозный фанатизм" на фразу "здравый смысл" ?

Записан
vregess
Гость
« Ответ #21 : Сентябрь 01, 2014, 22:14 »

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

Что-то ты напридумывал. Судя по коду, инкапсулирована она была для получения доступа к ней же из BookStorage, чтобы записать туда book. Откуда ты взял все остальное не ясно.

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

Это не кишки, вот если бы я вытащил наружу сожедримое метода insert(), то да. Создание Database не относится к внутренностям класса BookStorage, это не его ответственность, о чем, кстати, говорит само название класса BookStorage - Storage. Где тут про базы данных? Вот по этому-то и вытаскивают Database, чтобы избавить BookStorage от не относящихся к нему операций (создание Database).

Принцип действия этого анти-паттерна можно выразить словами: давайте нарушим инкапсуляции, и вытащим кишки класса наружу. И предложим пользователям самостоятельно поиметь геммор со всем этим.
Инкапсуляция тут совсем не нарушается - данные остаются с методами, их обрабатывающими (метод insert), а вот создание связанных сущностей выносится во вне. Причем это делается с определенной целью, а не посто ради создания дополнительных сущностей. Это не ООП ради ООП.

Твоя главная ошибка здесь, что ты считаешь бд и ее создание неотъемлемой частью класса BookStorage. Это первая причина разногласий.
А на самом деле мы провели рефакторинг и оптимизировали класс BookStorage, оставив ему только функции, связанные с манипуляциями хранилищем.

А для оставшегося функционала (создание и внедрение в BookStorage) у нас есть несколько вариантов:
1. Отдаем на откуп пользователя - об этом ты писал. Заметь, до этого момента
нет ничего противозаконного, никаких анти-паттернов. Просто ты не видишь
преимуществ "отрефакторенного" BookStorage, или не хочешь видить, тк уверен, что
все это какой-то мифический анти-паттерн.
Тут мы сами создаем и  сами внедряем бд в BookStorage.
Некоторые преимущества см. в пункте 2.

2. Помещаем создание в фабрику или что-то похожее - теперь создает не пользователь,
а фабрика, но внедряет все еще пользователь. Тут создается "лишняя" сущность. Будем считать
это отрицательным моментом, но оно приносит ряд преимуществ: легче сопровождать
BookStorage, легче заменять одни части на другие, лугче расширять код,
повторное исользование компонентов становится легче.
Получается для тебя это куча бесполезной ботвы, да еще и вредной. Единственное, что
можно вытащить из твоей цитаты, так это "усложнение конструкции", да и то спорное.

3. Отдаем на откуп IoC-контейнера - создание и внедрение происходит автоматически.

4. Что-нибудь еще, выходящее за рамки поста.

класс BookStorage в этом случае вообще становится не нужным.
Это не так, потому что BookStorage продолжает выполнять свою функцию - сохраняет данные в хранилище.


резюме:
1. То, что мы вытащили, не является "кишками" BookStorage, просто этого там не должно быть (в данном случае).

2. Это совсем не бесполезное, и даже полезное (в данном случае), потому что уже само по себе приносит ряд улучшений.

3. Это не ООП ради ООП, все это для создания меньшей связанности между классами. Конечно отвязать все отовсюду это перебор, и уже будет раздуванием архитектуры, но совсем не в нашем случае.

4. Ты выдираешь фразы из контекста.
Вот мы мы вытащили создание бд из класса и поместили в еще один класс. Теперь у нас 2 класса.
Ты берешь эти 2 факта (вытащили что-то и добавили еще один класс) и на нах строишь свою логику, совсем не учитывая, зачем это было сделано.
Конечно, в таком случае, все эти дейтвия будут казаться странными.
Разберись, для чего это было сделано.

А я еще раз повторю, что это все в основном для уменьшения связанности компонентов. А потом поищи, зачем компоненты стремятся отвязать друг от друга.

Если ты пишешь hello-world, то DI/IoC для тебя будет излишним, и ты получишь свое "раздувание оо-архитектуры кучей ненужных и избыточных сущностей".
Хотя даже в маленьких проектах ты не желая того делаешь инверсию управления, выделяя интерфейс из класса (а это потому-что паттерны проектирования всего лишь систематизация общеупотребляемых практик).

Ну а еще есть не hello-world проекты, где это успешно можно применить.


в чем смысл? В чем плюс?
Еще раз, слабая связанность, избавление от ручного создания объектов.

внедрения прослойки (опять таки внедрённой только ради внедрения)
Прослойка внедряется для того, чтобы отвязать 2 сущности друго от друга и убрать из них лишнюю нагрузку в виде создания определенных объектов.


класс прослойка, который знает всё о классах машины, колёс, знает принципы их взаимодействия
Что за панический страх перед прослойками?
Я тебе по секрету скажу, что есть опять же паттерн фасад. И он специально нужен, чтобы знать обо всех, и он - прослойка.

Вот почему класс-прослойка у тебя вызывает вопросы, а прослойка между монитором и стулом не вызывает?
Почему такая избирательность.
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #22 : Сентябрь 01, 2014, 22:47 »


Что-то ты напридумывал. Судя по коду, инкапсулирована она была для получения доступа к ней же из BookStorage, чтобы записать туда book. Откуда ты взял все остальное не ясно.

Судя по коду - она была инкапсулирована. Это все что я знал судя по коду.
Другими словами, пока вы не нарушили инкапсуляцию и не вытащили кишки - я вообще не знал ни о какой БД.

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

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

А теперь ответьте мне на мой вопрос: Если вы вытащили кишки класса наружу, и свалили мне на голову свою БД, накой чорт мне тогда может быть нужен класс BookStorage?

BookStorage мне был нужен именно для того, что бы простую операцию сделать просто: ничего при этом не зная ни о каких бд с их особенностями.

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

Вы усложнили жизнь мне, и одновременно лишили смысла существование класса BookStorage.

----------

Понимаете, ваши стремные зависимости - это ни что иное, как детальки реализации механизма, которые вы вытащили на уровень пользователя.

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

Чем меньше нужно знать, что бы полноценно пользоваться - тем проще. А чем проще - тем лучше. Всегда.
В этом заключается суть контроля за сложностью проекта: нужно минимизировать количество знаний, нужных для того, что бы пользоваться механизмом.

А не вытаскивать сор из избы ---> говнокод наружу ---> детали реализации за пределы класса.

Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #23 : Сентябрь 01, 2014, 22:50 »

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

Любую проблему можно решить внедрением ещё одного слоя абстракции. Кроме проблемы избыточных слоёв абстракций.
« Последнее редактирование: Сентябрь 01, 2014, 23:00 от _Bers » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #24 : Сентябрь 01, 2014, 23:00 »

2_Bers. А если я хочу, что класс BookStorage в качестве бекенда мог использовал разные хранилища? Например, в MySql базу или xml файл, а может в json или обычный текстовый файл?
Для чего мне прятать создание базы внутри, я могу создавать бекенды и подсовывать их BookStorage. А BookStorage зная только интерфейс сможет сохранять информацию о книгах куда мне надо.
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #25 : Сентябрь 01, 2014, 23:13 »

2_Bers. А если я хочу, что класс BookStorage в качестве бекенда мог использовал разные хранилища? Например, в MySql базу или xml файл, а может в json или обычный текстовый файл?
Для чего мне прятать создание базы внутри, я могу создавать бекенды и подсовывать их BookStorage. А BookStorage зная только интерфейс сможет сохранять информацию о книгах куда мне надо.

Для того, что вы хотите bookstorage не нужен:

Код:
book b;
serialize::xml(b);
serialize::json(b);

« Последнее редактирование: Сентябрь 01, 2014, 23:18 от _Bers » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #26 : Сентябрь 01, 2014, 23:21 »

А вы шире на это посмотрите. Я воспользовался классами из обсуждения только для примера.
Бывает полезно создавать объект руками и отдавать на использование другому объекту. Возможностей по созданию и настройке больше.
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #27 : Сентябрь 01, 2014, 23:37 »

А вы шире на это посмотрите. Я воспользовался классами из обсуждения только для примера.
Бывает полезно создавать объект руками и отдавать на использование другому объекту. Возможностей по созданию и настройке больше.

Если глянуть шире - иногда это действительно имеет профит. Паттерн "стратегия" опять таки.
Но "стратегия" имеет четко обозначенную область применения, и не вызывает вопросов.

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

зы: надеюсь про "возможности по созданию и настройкам" - это вы не всерьёз.
« Последнее редактирование: Сентябрь 01, 2014, 23:43 от _Bers » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #28 : Сентябрь 01, 2014, 23:50 »

Почему не всерьёз - всерьёз.
Если мы спрячим объект базы внутри BookStorage, то не создать, не настроить этот объект мы не сможем.

Кстати, в чем вы видите разницу между стратегиями и этим DI?
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #29 : Сентябрь 02, 2014, 00:12 »

Почему не всерьёз - всерьёз.
Если мы спрячим объект базы внутри BookStorage, то не создать, не настроить этот объект мы не сможем.

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


Пример:
Взять обычный std::vector.

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

Но многих ли вы знаете из тех, кто хоть раз применял "тонкие настройки" - замену стандартного аллокатора на свой, кастомный?

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


Итого:
практика показывает, что:

1. Простой в эксплуатации механизм пользуется спросом.
2. Сложный в эксплуатации механизм не пользуется спросом.


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

Кстати, в чем вы видите разницу между стратегиями и этим DI?

Область применения стратегии: необходимость изменить поведение объекта в рантайме.

Например, мы конструируем модель мира - полигон, где живут животные.

Волки зимой должны сбиваться в стаю, а летом - охотиться в одиночку.

Это не просто один и тот же класс животного.
Это - один и тот же экземпляр животного.
И в зависимости от некоторых условий, происходящих в рантайме, экземпляр должен менять собственное поведение.

---

Что касается DI - я так и не понял, что это такое, и зачем оно нужно.
Все, что я о нем знаю сейчас - что это анти-паттерн, который только все усложняет.
Потому что все то, что можно сделать с помощью DI, можно сделать и без DI, только проще.
« Последнее редактирование: Сентябрь 02, 2014, 00:21 от _Bers » Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.058 секунд. Запросов: 23.