Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.50/26: Рейтинг темы: голосов - 26, средняя оценка - 4.50
53 / 28 / 13
Регистрация: 01.03.2013
Сообщений: 330

IoC container вместо Singletone

27.02.2023, 08:47. Показов 6220. Ответов 79
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.
В инете много инфы на эту тему, но она довольно не структурирована и сложно понять нужно ли вообще в это вникать на плюсах.
В общем есть приложение на Qt. В данном приложении много объектов-одиночек. Хотелось бы избавиться от них.
На первых парах не нашел какого-то встроенного инструмента в Qt. Есть мысли написать свой велосипед, но все же хотелось бы использовать проверенное решение.
Из того, что я понял контейнер зависимостей это некий класс, имеющий соответствующие методы - геттеры / сеттеры, полем которого выступает словарь {key, val}, где key это строка идентификатор, val - указатель на созданный объект. Но это какое-то слишком простое представление. Там еще фабрики каким то боком).
Рад буду любой ссылке либо на статью с подробным описанием решения моей проблемы, либо проекту на гитхабе (желательно максимально простому, не хотелось бы бездумно использовать какой-нибудь громоздкий инструмент на начальном этапе)
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
27.02.2023, 08:47
Ответы с готовыми решениями:

Класс Singletone
Здравствуйте! Продолжаю готовиться к экзамену по С++. На последнем уроке вкратце рассказали про класс Singleton, но я расслабился и...

Singletone и множество потоков
Всем доброго утра! В приложение есть множество потоков обращающихся к классу одиночки. Правильно ли я понимаю, что сам класс будет...

Белый экран при входе в админку - Class 'FOF30\\Container\\Container' not found
Добрый вечер! Помогите, пожалуйста, исправить проблемку. С джумлой раньше дел практически никаких не имел, поэтому прошу помощи у знающих...

79
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
01.03.2023, 13:02
Студворк — интернет-сервис помощи студентам
Ну и по зависимостям.

Мой изначальный пример с синглтоном содержал такие зависимости.


В моём примере с DI зависимостей стало меньше.


В вашем примере DI на основе шаблонов сохраняется лишняя зависимость от синглтона.


Это не означает, что он не имеет право на существование. Это означает, что вы можете лучше.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
01.03.2023, 13:29
Цитата Сообщение от eva2326 Посмотреть сообщение
Если ваш код использует неккий логгер, то вы в любом случае будете таскать с собой зависимости от него.
Не обязательно.
Я могу предоставлять контракт -- интерфейс или, если вам больше нравится, шаблонный параметр -- который будет использоваться в моих сущностях и не таскать за своим кодом конкретные реализации.
В моём коде может вообще не быть упоминаний зависимостей.
0
 Аватар для eva2326
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
01.03.2023, 13:48
Цитата Сообщение от lemegeton Посмотреть сообщение
Поздравляю, вы изобрели простенький DI.
Параметр шаблона не имеет к DI никакого отношения.
На шаблонах можно так завернуть, что изготавливать наследников от каких то интерфейсов вообще не понадобится.

Цитата Сообщение от lemegeton Посмотреть сообщение
Лишняя зависимость от класса Singleton только осталась.
Почему это она лишняя?

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

Цитата Сообщение от lemegeton Посмотреть сообщение
Значит недостаточно крупные.
Нет, не значит.
Избавьте меня от вот таких вот голословных понтов.

Цитата Сообщение от lemegeton Посмотреть сообщение
Вы ИЗМЕНИЛИ мой код
Разумеется.
У вас была неккая одна единственная реализация.
И тут вы захотели организовать поддержку ещё одной реализации.
Однако ваш оригиналный код не поддерживает подобную возможность.

Разумеется, мне пришлось изменить ваш код.
И теперь у вас на руках имеется более продвинутая версия.

Это тоже синглетон, но при этом его работу можно кастомизировать.
Этот пример наглядно демонстрирует, что использование синглетонов само по себе никак не ограничивает архитектуру в плане расширения.

Цитата Сообщение от lemegeton Посмотреть сообщение
Прикинь, да? Это и есть самое большое различие. Указание внешней зависимости.
Как мы это называем? Именно. Dependency Injection.
Это не принципиальное различие.
Прикинь, да?

Цитата Сообщение от lemegeton Посмотреть сообщение
Я явно показал, как избавиться в компоненте от зависимости от Singleton'а и конкретики реализации.
Я тоже явно показала как избавиться от зависимости от синглетона и от конкретики реализации.
Вот только зависимости - это не только наследники от некких базовых классов.
Зависимости - это ещё и сами базовые классы, и всё то множество инфраструктурных классов, которые необходимы для функционирования архитектуры.

И от этих зависимостей вы никуда не ушли.

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

Цитата Сообщение от lemegeton Посмотреть сообщение
Слово потерялось. Инфраструктурные что?
Зависимости.

Цитата Сообщение от lemegeton Посмотреть сообщение
Вы просто поменяли мой пример под себя.
Не под себя, а под вас.
Вы изначально привели пример модели, которая не умела расширяться.
Я её слегка подправила под ваши запросы, и теперь она умеет расширяться.

Так а в чем, говорите, проблема заключается?

Цитата Сообщение от lemegeton Посмотреть сообщение
Ну если вы локально поднимаете какое-то моковое окружение для юнит-тестов -- мои вам соболезнования.
Мне не нужны соболезнования.
Мне нужна конкретика: в чем проблема?

Добавлено через 8 минут
Цитата Сообщение от lemegeton Посмотреть сообщение
В вашем примере DI на основе шаблонов
Там только два элемента: Сервис и синглетон.
Причем, благодаря параметру шаблона синглетон не является зависимостью.

Цитата Сообщение от lemegeton Посмотреть сообщение
Это не означает, что он не имеет право на существование. Это означает, что вы можете лучше.
Вы тоже сможете лучше, если осознаете, что вариант с шаблоном (именно конкретный вариант, который я предложила выше) вообще не имеет зависимостей, и не вынуждает пользователей обязательно наследоваться от каких то интерфейсов.

Цитата Сообщение от lemegeton Посмотреть сообщение
Не обязательно.
Я могу предоставлять контракт -- интерфейс или, если вам больше нравится, шаблонный параметр
Нет, обязательно.
Интерфейс - он в сферическом ваккуме существует?
Это тоже код, который записан в файле, и который вам придется таскать повсюду со своим логгером.

А вот шаблонный параметр может вообще не предполагать наличия каких то интерфесов.
С этой точки зрения, разница принципиальная.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
01.03.2023, 14:00
Цитата Сообщение от eva2326 Посмотреть сообщение
Это ещё почему?
Потому что коду, который хочет использовать сущность и получает её через конструктор, наплевать откуда взялась сущность.
Он с этим синглтоном никак не связан. И у ТС не встал бы вопрос.
0
 Аватар для eva2326
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
01.03.2023, 14:05
Цитата Сообщение от lemegeton Посмотреть сообщение
И у ТС не встал бы вопрос.
ТС пришел к синглетонами именно потому, что у него встал.

Цитата Сообщение от Kenny7423 Посмотреть сообщение
Изначально у меня объекты, которые требуют повсеместного использования (например Logs, Queue), переходили из класса в класс по ссылке в конструкторе, потом я их переделал под singleton, потому что параметров конструктора в некоторых классах стало слишком много.
Цитата Сообщение от eva2326 Посмотреть сообщение
ТС этой темы специально ушел на сиглетоны, что бы избавить себя от неудобств.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
01.03.2023, 14:19
Цитата Сообщение от eva2326 Посмотреть сообщение
Параметр шаблона не имеет к DI никакого отношения.
Имеет. Вы передаете с его помощью зависимость.

Цитата Сообщение от eva2326 Посмотреть сообщение
Это не принципиальное различие.
Это принципиальное различие.
В данном конкретном примере я показал зависимости кода.
В вашем коде другие зависимости. И добавлен способ передачи зависимости.
Скорее это уже не синглтон, а сервис локатор.

Цитата Сообщение от eva2326 Посмотреть сообщение
Зависимости.
Да. Зависимости, связанные с организацией кода.

Цитата Сообщение от eva2326 Посмотреть сообщение
Вы изначально привели пример модели, которая не умела расширяться.
Дак я неслучайно же её именно в таком виде и привёл! И даже указал, что это -- проблема.

Цитата Сообщение от eva2326 Посмотреть сообщение
Вы изначально привели пример модели, которая не умела расширяться.
Я её слегка подправила под ваши запросы, и теперь она умеет расширяться.
Так а в чем, говорите, проблема заключается
Да. Вы верно привели проблему.
И естественно, что она перестаёт быть проблемой, если её переписать.
Что вы благополучно и показали.
Добавив указание зависимости, превратив синглтон в сервис локатор.

Цитата Сообщение от eva2326 Посмотреть сообщение
Зависимости - это ещё и сами базовые классы, и всё то множество инфраструктурных классов, которые необходимы для функционирования архитектуры.
И от этих зависимостей вы никуда не ушли.
Еще раз. Писать абсолютно несвязанный код мы пока не умеем и не факт, что надо.
Цель -- уменьшить количество связей.
В своём коде я представляю свой контракт, используя который можно менять конкретные реализации.
Это позволяет абстрагироваться от конкретных реализаций зависимостей.
Например, я не должен за своей библиотекой таскать класс/библиотеки логгера, мне достаточно иметь контракт, который можно удовлетворить. А уж каким образом -- не проблема моей библиотеки.

Цитата Сообщение от eva2326 Посмотреть сообщение
Там только два элемента: Сервис и синглетон.
Причем, благодаря параметру шаблона синглетон не является зависимостью.
Тэкс. Вы штота путаться начали.
"Синглетон" прямо написан в коде класса. Следовательно, является зависимостью. Класс нельзя будет откомпилировать без класса "синглетона".
Дальше больше -- шаблонный параметр инжектит вторую зависимость.
В результате финальный класс зависит от синглтона и от класса, указанного шаблонным параметром.
И синглтон в коде так же зависит от шаблонного параметра.

Цитата Сообщение от eva2326 Посмотреть сообщение
Нет, обязательно.
Интерфейс - он в сферическом ваккуме существует?
Он существует в моей библиотеке. И от него зависит моя библиотека.
И всё. Больше ни от чего моя библиотека не зависит.
Ни от какой реализации этого интерфейса/шаблонного параметра.
Мне не нужно таскать за собой никакую либу. Только контракт.
Моя либа собирается без сторонних библиотек.

Цитата Сообщение от eva2326 Посмотреть сообщение
А вот шаблонный параметр может вообще не предполагать наличия каких то интерфесов.
С этой точки зрения, разница принципиальная.
Тут без порно. Разница принципиальная.

Добавлено через 1 минуту
Цитата Сообщение от eva2326 Посмотреть сообщение
ТС пришел к синглетонами именно потому, что у него встал.
Именно.

Цитата Сообщение от eva2326 Посмотреть сообщение
ТС этой темы специально ушел на сиглетоны, что бы избавить себя от неудобств.
... и мы все дружно написали ему перестать передёргивать этот затвор, ибо это может быть аксиомой эскобара.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
01.03.2023, 14:24
Цитата Сообщение от eva2326 Посмотреть сообщение
ТС этой темы специально ушел на сиглетоны, что бы избавить себя от неудобств.
Он у шел на синглтоны патаму шта ушел на синглтоны.
Я не увидел резонной причины.
Кликните здесь для просмотра всего текста




Может я конечно мелко мыслю. Но раз у него повсеместно используется что то. Можно поручить какому то Шарику их хранить, и все будут у этого Шарика это использовать, нет ?
Откуда родились Синглтоны ? )
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
01.03.2023, 14:25
Цитата Сообщение от KSergey9 Посмотреть сообщение
Я вот читаю ветку и никак не могу понять: откуда вообще берётся противопоставление Singleton и IoC/DI ?
Это же какие-то абсолютно перпендикулярные вещи.
Добавление промежуточного уровня абстракции может решать любые решаемые задачи) У Александреску есть описание класса, который инкапсулируя ссылку на type_info создаёт сущность с семантикой значение, т.е. позволяет работать с собой по значению, обращаясь к, фактически, синглтону. Иной раз это удобно. Однако грустно, когда такие инструменты используются для удовлетворения нужд бедолаг вопиющих нечто вроде "Нимагу создать массив синглтонов!".
Когда слышишь такое, невольно думаешь: - "Молодец. Значит синглтон получился на славу. Наверное."
1
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
01.03.2023, 14:45
Цитата Сообщение от eva2326 Посмотреть сообщение
Интерфейс - он в сферическом ваккуме существует?
Это тоже код, который записан в файле, и который вам придется таскать повсюду со своим логгером.
Не с логгером. Интерфейсы/шаблоны зависимостей должны предоставляться классом, требующим зависимость. Инверсия зависимостей же.

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
 
// ---------------- awesome service impl
 
namespace Kenny7423 {
    
    class Log {
    public:
        virtual void info(std::string message) = 0;
    };
    
    class AwesomeService {
    public:
        AwesomeService(Log* aLog);
        
        void doAwesomeThings();
    private:
        Log* log;
    };
    
    AwesomeService::AwesomeService(Log* aLog) : log{aLog} {}
    
    void AwesomeService::doAwesomeThings()
    {
        log->info("Awesome!");
    }
}
 
// ---------------- log impl lib1
 
namespace lemegeton {
    
    class Log {
    public:
        virtual void info(std::string message);
    };
    
    void Log::info(std::string message)
    {
        std::cout << "lemegeton: " << message << std::endl;
    }
}
 
// ---------------- log impl lib2
 
namespace eva2326 {
    
    class Log {
    public:
        virtual void info(std::string message);
    };
    
    void Log::info(std::string message)
    {
        std::cout << "eva2326: " << message << std::endl;
    }
}
 
// ---------------- the app
 
class Log : public lemegeton::Log,
    public Kenny7423::Log
{
public:
    virtual void info(std::string message)
    {
        lemegeton::Log::info(message);
    }
};
 
/* or
class Log : public eva2326::Log,
    public Kenny7423::Log
{
public:
    virtual void info(std::string message)
    {
        eva2326::Log::info(message);
    }
};
*/
 
int main()
{
    Log* log = new Log();
    Kenny7423::AwesomeService* service = new Kenny7423::AwesomeService(log);
    service->doAwesomeThings();
}
1
 Аватар для eva2326
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
01.03.2023, 15:11
Цитата Сообщение от lemegeton Посмотреть сообщение
Имеет. Вы передаете с его помощью зависимость.
Это - не зависимость.

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

Вот пример зависимости:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// example.hpp
 
#include <iostream>
struct example
{
    friend std::ostream& operator<<(std::ostream& out, const example& obj)
    {
        return out << obj.age; 
    }
    size_t age;
};
 
// main.cpp
 
int main()
{
    std::cout << example{33} ;
}
example зависит от std::ostream.

А вот пример, как с помощью шаблона можно полностью устранить зависимость:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// example.hpp
 
#define OUT_TO_STREAM(classname)  \
    template<class ostream> friend \
    ostream& operator<<(ostream& out, const classname& obj)
 
struct example
{
    OUT_TO_STREAM(example)
    {
        return out << obj.age; 
    }
    
    size_t age;
};
 
// main.cpp
#include <iostream>
 
int main()
{
    std::cout << example{33} ;
}
Во втором случае, из-за того, что example не имеет зависимостей, то и файл example.hpp тоже не требует, что бы вместе с ним обязательно таскали ещё какие то файлы.

Цитата Сообщение от lemegeton Посмотреть сообщение
Дак я неслучайно же её именно в таком виде и привёл! И даже указал, что это -- проблема.
Получается, что проблема вовсе не в синглетонах, а в прокладке между стулом и монитором?

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

Проблема в чем?
В том, что изменились требования, и пришлось чуть чуть подправить код?

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

Цитата Сообщение от lemegeton Посмотреть сообщение
Еще раз.
Ещё раз, вы там выже жаловались, что вам вместе с моим логгером нужно будет таскать зависимости от этого логгера.
И вы это так написали, якобы DI позволит вам этого избежать.

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

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

Цитата Сообщение от lemegeton Посмотреть сообщение
"Синглетон" прямо написан в коде класса. Следовательно, является зависимостью.
В вашем случае ваш синглетон - это просто какая то непонятная прокладка.
Давайте её уберем, если она вас напрягает:

C++
1
2
3
4
5
6
struct MyAwesomeImagePostingService {
    template <class Connect>
    void doSomethingAwesome() {
        Connect::instance()->postImage();
    }
};
Но если она нужна для поддержки работы инфраструктуры, тогда это такой же элемент как например, интерфейс.
Вы же не называете интерфейсы зависимостями.
Почему тогда вы называете зависимостью деталь, которая наряду с интерфейсами выполняет инфраструктурную роль?

Цитата Сообщение от lemegeton Посмотреть сообщение
Класс нельзя будет откомпилировать без класса "синглетона".
По вашей логике тогда и интерфейсы тоже являются зависимостями.
Ведь без них класс нельзя будет откомплиировать.

Технически, зависимость от интерфейса - это тоже зависимость.
Однако, в контексте ооп, зависимостями обычно называют только наследников.
А вот интерфейсы и сопутствующие им инфраструктурные классы зависимостями не считают.


Цитата Сообщение от lemegeton Посмотреть сообщение
Он существует в моей библиотеке. И от него зависит моя библиотека.
И всё. Больше ни от чего моя библиотека не зависит.
Но она зависит.
И если я захочу периспользовать какие то ваши классы где-то ещё, то мне тоже придется таскать с собой их зависимости.
Ровно тоже самое, как и в случае с моим логгером.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
01.03.2023, 15:44
Цитата Сообщение от eva2326 Посмотреть сообщение
А теперь внезапно выясняется, что нет, не позволит.
Кем? )))
Цитата Сообщение от eva2326 Посмотреть сообщение
Давайте её уберем, если она вас напрягает:
А лучше сразу уберем зависимость от синглтона?
И скажем, что это одно и то же?
Ну нет же разницы никакой.

Цитата Сообщение от eva2326 Посмотреть сообщение
В вашем случае ваш синглетон - это просто какая то непонятная прокладка.
Давайте её уберем, если она вас напрягает:
Ох, молодёжь, вам бы всё переписать.

Цитата Сообщение от eva2326 Посмотреть сообщение
Проблема в чем?
В том, что изменились требования, и пришлось чуть чуть подправить код?
Возможно в маленьких проектах это не проблема.
В крупных проектах -- "поправить одну функцию", превнеся несовместимость, означает рекурсивно поправить так же ВСЕ места их использования.
Зарелизить все задетые библиотеки по дереву зависимостей.
Зарелизить все задетые приложения по дереву зависимостей.

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

Цитата Сообщение от eva2326 Посмотреть сообщение
Зависимость - это некоторая деталь, без которой у вас код даже не скомпилируется.
Интересная трактовка.

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

Цитата Сообщение от eva2326 Посмотреть сообщение
И если я захочу периспользовать какие то ваши классы где-то ещё, то мне тоже придется таскать с собой их зависимости.
Ровно тоже самое, как и в случае с моим логгером.
Да. Придется. Поэтому у моих либ этих самых зависимостей по-минимуму. Где только возможно используется IoC/DI, убирающий зависимость от конкретной реализации.
Нет, не то же самое. В версии с IoC/DI вы сможете подменить логгер на любой другой. В варианте, который вы предложили, придется сначала переделать под DI.
Моя библиотека избавлена от необходимости таскать с собой в связке ещё какой-то код.

Добавлено через 4 минуты
Цитата Сообщение от eva2326 Посмотреть сообщение
Но она зависит.
Нет. Непосредственно моя библиотека не зависит. Её можно собирать отдельно.
А вот там, где вы захотите её применить, вам придется либо воспользоваться подготовленными мною реализациями, либо написать свою.

Добавлено через 4 минуты
Цитата Сообщение от eva2326 Посмотреть сообщение
Давайте её уберем, если она вас напрягает:
Дыа. Если решать проблему, она, внезапно, исчезает.
Magic!
0
 Аватар для eva2326
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
01.03.2023, 16:32
Цитата Сообщение от lemegeton Посмотреть сообщение
Кем?
Не кем, а чем. Интерфейсами.
Интерфейсы все равно таскать придется.

Цитата Сообщение от lemegeton Посмотреть сообщение
А лучше сразу уберем зависимость от синглтона?
И скажем, что это одно и то же?
Ну нет же разницы никакой.
Не получится. instance как бы намекает.

Цитата Сообщение от lemegeton Посмотреть сообщение
Поэтому мы сразу думаем о том, как уменьшать связанность кода и весьма осторожно подходим к выбору паттернов проектирования.
Так если вы сразу думаете о том, как уменьшить связанность, тогда почему вы сразу не подумали о том, как сделать синглетон расширяемым?

Получается, что проблема, которую вы обрисовали, связанна не с синглетонами, а с вашими кривыми руками.

Цитата Сообщение от lemegeton Посмотреть сообщение
Представьте себе сервис-локатор, который не вернул нужный сервис, это зависимость или нет?
В такой формулировке вообще не понятно, при чем тут зависимость.

Цитата Сообщение от lemegeton Посмотреть сообщение
код, который использует внешнюю динамическую библиотеку, это зависимость или нет?
Только и только в том случае, если не может без неё обойтись.
Цитата Сообщение от lemegeton Посмотреть сообщение
код, который использует данные в файле, это зависимость или нет?
Только и только в том случае, если не может без них обойтись.

Цитата Сообщение от lemegeton Посмотреть сообщение
Нет, не то же самое. В версии с IoC/DI вы сможете подменить логгер на любой другой. В варианте, который вы предложили, придется сначала переделать под DI.
Это бред.
В моём варианте тоже можно подменить логгер на любой другой.
И ничего переделывать для этого не нужно.


Цитата Сообщение от lemegeton Посмотреть сообщение
Нет. Непосредственно моя библиотека не зависит. Её можно собирать отдельно.
А вот там, где вы захотите её применить, вам придется либо воспользоваться подготовленными мною реализациями, либо написать свою.
Видимо вы не поняли.
Я беру какой то класс, готовлю какую то реализацию, на базе вашей библиотеки.
Использую в этом классе.

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

Это абсолютно тоже самое, как и с моим логгером.

Вот взять вот эти строчки:
Цитата Сообщение от korvin_ Посмотреть сообщение
Kenny7423::AwesomeService* service = new Kenny7423::AwesomeService(log);
    service->doAwesomeThings();

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

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

Добавлено через 54 секунды
Цитата Сообщение от lemegeton Посмотреть сообщение
Он существует в моей библиотеке. И от него зависит моя библиотека.
Цитата Сообщение от lemegeton Посмотреть сообщение
Нет. Непосредственно моя библиотека не зависит.
У вас биполярочка?
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
01.03.2023, 16:48
Цитата Сообщение от eva2326 Посмотреть сообщение
Так если вы сразу думаете о том, как уменьшить связанность, тогда почему вы сразу не подумали о том, как сделать синглетон расширяемым?
Тпру, Зорька.

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

Уводить дискуссию в сторону от начального вопроса -- некрасиво.

Цитата Сообщение от eva2326 Посмотреть сообщение
Получается, что проблема, которую вы обрисовали, связанна не с синглетонами, а с вашими кривыми руками.
Любая проблема связана в первую очередь с вашими кривыми руками.
Не уводите дискуссию в сторону.


Цитата Сообщение от eva2326 Посмотреть сообщение
Ситуация абсолютно точно такая же, как и в случае с моим логгером.
Приведите пример. (с)(тм)

Цитата Сообщение от eva2326 Посмотреть сообщение
а классу подсунуть заглушку
Да. Так и есть. И то, что вы можете её передать в класс - это и есть depedency injection.

Цитата Сообщение от eva2326 Посмотреть сообщение
которую даже не обязательно наследовать от интерфейса
Совершенно согласен. Не обязательно. Можно шаблонным параметром, можно макросом, можно хоть на другом языке программирования.
Я предпочитаю интерфейсом из-за явности контракта. Пока вы не в моей команде, я вас не заставляю. )))

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

Цитата Сообщение от eva2326 Посмотреть сообщение
У вас биполярочка?
Притворятся, непонимающим ради оскорблений -- это несколько за гранью.
Пожалуйста, прекратите эту практику.
0
184 / 72 / 35
Регистрация: 09.05.2022
Сообщений: 388
01.03.2023, 17:36
Привет! Кажется, ты ищешь способ управления зависимостями объектов для своего проекта на C++ в Qt. Эта техника называется Dependency Injection (DI) и она может значительно упростить создание и управление объектами в сложных приложениях.

Есть несколько DI-фреймворков и библиотек для C++, которые ты можешь использовать в Qt. Например:

Boost.DI - это легкая библиотека только для заголовков, которая предоставляет простой интерфейс для определения и инъекции зависимостей с помощью инъекции конструктора, инъекции сеттера или инъекции свойства. Она хорошо работает с Qt, и ты можешь найти пример использования Boost.DI с Qt на сайте библиотеки.
QDI - это DI-фреймворк, специально разработанный для Qt-приложений. Он использует макрос Q_OBJECT для определения зависимостей и предоставляет простой API для регистрации и разрешения зависимостей. QDI также поддерживает автоматическое внедрение зависимостей и может использоваться как с C++, так и с QML.
Poco:ependencyInjector - это фреймворк для C++11 и выше, который поддерживает инъекцию конструкторов и инъекцию сеттеров и может использоваться в приложениях Qt.
Inversify-cpp - это мощный и гибкий DI-фреймворк для C++11 и выше, который предоставляет простой API для определения и инъекции зависимостей с помощью инъекции конструктора, инъекции сеттера или инъекции свойства. Он также поддерживает автоматическое внедрение зависимостей и может использоваться как с C++, так и с TypeScript.
Вот несколько ресурсов, которые могут помочь:

Dependency Injection in C++ - это статья с хорошим введением в DI в C++, которая включает примеры с использованием Boost.DI и Poco:ependencyInjector.
Modern C++ Dependency Injection - это статья с обзором DI в современном C++, включая пример с использованием Inversify-cpp.
Инъекция зависимостей в Qt
0
118 / 86 / 35
Регистрация: 07.11.2022
Сообщений: 355
01.03.2023, 17:48
karlhildekruger, что за набор слов?
ChatGPT ?
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4576 / 2775 / 491
Регистрация: 28.04.2012
Сообщений: 8,782
01.03.2023, 18:18
Цитата Сообщение от eva2326 Посмотреть сообщение
Допустим, я хочу переиспользовать AwesomeService, а мне вообще не нужно никакое логгирование.
Но мне все равно придется таскать с собой интерфейс логгера.
Конечно, ведь это часть контракта класса AwesomeService.

Цитата Сообщение от eva2326 Посмотреть сообщение
И вешать на него какую то заглушку.
Ну да. Stub или mock. А иначе нужно будет таскать вместе с AwesomeService библиотеку логирования.

Либо ты всегда можешь использовать
Цитата Сообщение от lemegeton Посмотреть сообщение
Паттерны типа декоратор/прокси к вашим услугам.
и всё в таком духе.

Цитата Сообщение от eva2326 Посмотреть сообщение
Если он не нужен, то можно выбросить всю библиотеку логгирования, а классу подсунуть заглушку
Ровно так и делается в юнит-тестах.

Цитата Сообщение от eva2326 Посмотреть сообщение
которую даже не обязательно наследовать от интерфейса
Обязательность явного наследования интерфейса — языковая особенность. Можно и неявный шаблон использовать, но в таком случае он перестаёт быть публичным контрактом класса AwesomeService и для его (класса AwesomeService) модульного тестирования придётся лезть в его реализацию и смотреть где он какие методы логгера использует, т.к. из его публичной сигнатуры это будет не выявить.

Вот две сигнатуры:

C++
1
2
3
4
5
6
7
template<class Log>
class AwesomeService {
public:
    AwesomeService(Log* log);
    ~AwesomeService();
    virtual void doAwesomeThings();
};
C++
1
2
3
4
5
6
7
8
9
10
11
class Log {
public:
    virtual void info(std::string message) = 0;
};
 
class AwesomeService {
public:
    AwesomeService(Log* log);
    ~AwesomeService();
    virtual void doAwesomeThings();
};
Как из первой понять, что такое Log? Во второй всё понятно.
1
 Аватар для eva2326
1685 / 513 / 107
Регистрация: 17.05.2015
Сообщений: 1,524
02.03.2023, 00:16
Цитата Сообщение от lemegeton Посмотреть сообщение
Изначально вы попросили меня пример, где синглтон создаёт проблему.
Изначально вы утверждали, что якобы синглетоны создают проблемы.
Я попросила пример, где синглетон создает проблемы.

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

Цитата Сообщение от lemegeton Посмотреть сообщение
Уводить дискуссию в сторону от начального вопроса -- некрасиво.
Некрасиво перекладывать ответственность на паттерн синглетон вину за свои кривые руки.

Цитата Сообщение от lemegeton Посмотреть сообщение
Любая проблема связана в первую очередь с вашими кривыми руками.
Не уводите дискуссию в сторону.
Что это за инфантильная попытка свалить на меня все проблемы мира?
Так например, ваши проблемы ко мне вообще никакого отношения не имеют.

Это вы уводите дисскуссию в сторону.
Я просила привести пример проблемы синглетона.
А не проблемы ваших кривых рук.

Цитата Сообщение от lemegeton Посмотреть сообщение
Приведите пример. (с)(тм)
Вот здесь:

C++
1
2
3
4
5
6
7
class MyAwesomeService {
public:
    void doAwesomeStuff() {
        // do awesome stuff
        ::mylog::emergency.log("Done!");  
    }
};
::mylog::emergency - это имя объекта.

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

Цитата Сообщение от lemegeton Посмотреть сообщение
Таскать необязательно.
Нет, вы именно что будете таскать.
Вы там выше жаловались, что синглетоны вынуждают вас таскать запчасти.
Вот с DI вам тоже придется таскать запчасти.

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

Цитата Сообщение от lemegeton Посмотреть сообщение
Пожалуйста, прекратите эту практику.
Как только вы прекратите противоречить самому себе, я перестану спрашивать, нет ли у вас биполярочки.

Цитата Сообщение от lemegeton Посмотреть сообщение
функционал
см #34

Добавлено через 9 минут
Цитата Сообщение от korvin_ Посмотреть сообщение
Конечно, ведь это часть контракта класса AwesomeService.
Странно, что человек выше этого не понимает.
По его мнению, только синглетоны вынуждают таскать запчасти.

Цитата Сообщение от korvin_ Посмотреть сообщение
Обязательность явного наследования интерфейса — языковая особенность.
Не в с++

Цитата Сообщение от korvin_ Посмотреть сообщение
Как из первой понять, что такое Log?
По названию.
Вот карандаш означает карандаш.
Ботинок означает ботинок.
А Log означает Log

Цитата Сообщение от korvin_ Посмотреть сообщение
Во второй всё понятно.
Да и в первой тоже понятно.

Добавлено через 3 минуты
Цитата Сообщение от korvin_ Посмотреть сообщение
для его (класса AwesomeService) модульного тестирования придётся лезть в его реализацию и смотреть где он какие методы логгера использует
Зачем?

Цитата Сообщение от korvin_ Посмотреть сообщение
т.к. из его публичной сигнатуры это будет не выявить.
Ну и что?
Это что - повод лазить в реализацию?

Тестируют же паблик, а не приват.
Пока тесты зеленые, что там внутри - вообще не интересно.

Добавлено через 30 минут
Цитата Сообщение от korvin_ Посмотреть сообщение
Обязательность явного наследования интерфейса — языковая особенность.
И вот кстати, в с++ можно сделать так, что бы были и интерфейсы, и наследование, но при этом, что бы они порождались автоматически, без необходимости явным образом прописывать их вручную.


Например, Петя сделал такую систему сообщений: у него, что бы создать тип пользовательского сообщения, нужно обязательно вручную написать код наследования:

C++
1
2
3
4
5
6
7
8
struct UserMessage: EventSystem::IMessage { ... };
...
 
int main()
{
    UserMessage msg{ param };
    EventSystem::Send(msg);
}
Тут сразу два неудобства:
1. Типы юзерских сообщений зависят от библиотечного класса IMessage, что прибивает их гвоздями к Петиной библиотеке.
2. Просто неудобно на каждый чих создавать новый класс.

Поэтому Вася посмотрел на всё, плюнул и сделал вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
int main()
{
  struct UserMessage { ... }; // Не нужно больше ни от чего наследоваться
  ...
 
  UserMessage msg{ param };
 
  EventSystem::Send(msg); // Можно сразу любые объекты посылать
  EventSystem::Send("hello");
  EventSystem::Send(1,2,3);   
}
На самом деле ничего кардинально не изменилось.
Хитрый Вася просто взял Петину библиотеку, и немножечко подправил шаблон функции Send
Внутри этого шаблона автоматичеки создается шаблоно-наследник от IMessage, путем инстанцирования типами аргументов, с которыми была вызвана функция.
Поэтому клиентам больше не нужно вручную писать код наследования, а можно сразу запускать Send для объектов любых типов.

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

Какая же это зависимость, если юзерские сообщения никак не зависят от Петиной библиотеки, а Петина библиотека никак не зависит от юзерских сообщений?
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
02.03.2023, 00:52
Цитата Сообщение от eva2326 Посмотреть сообщение
EventSystem::IMessage

Ну так, наверное интерфейсы не воздух подпирают.
И они описывают некий функционал который должен определить наследник.
Что это за фантазии ?

Добавлено через 4 минуты
Цитата Сообщение от eva2326 Посмотреть сообщение
Внутри этого шаблона автоматичеки создается шаблоно-наследник от IMessage, путем инстанцирования типами аргументов, с которыми была вызвана функция.
Но мысль механизма понятна.
А при чем тут синглтоны ?
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
02.03.2023, 08:18
Цитата Сообщение от IGPIGP Посмотреть сообщение
Добавление промежуточного уровня абстракции может решать любые решаемые задачи)
Кроме проблемы слишком большого числа абстракций.
Что мы, собственно, и наблюдаем.
0
 Аватар для lemegeton
4903 / 2696 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
02.03.2023, 09:04
Цитата Сообщение от eva2326 Посмотреть сообщение
Изначально вы утверждали, что якобы синглетоны создают проблемы.
Я попросила пример, где синглетон создает проблемы.
Я вам продемонстрировал и синглтон и проблемы с его использованием.
Судя по вашим ответам, вы проблемы поняли, показали, как их исправить, а дальнейшей софистикой занимаетесь лишь из любви к искусству.

Цитата Сообщение от eva2326 Посмотреть сообщение
Что это за инфантильная попытка свалить на меня все проблемы мира?
Цитата Сообщение от eva2326 Посмотреть сообщение
Некрасиво перекладывать ответственность на паттерн синглетон вину за свои кривые руки.
Цитата Сообщение от eva2326 Посмотреть сообщение
Как только вы прекратите противоречить самому себе, я перестану спрашивать, нет ли у вас биполярочки.
Переходы на личности не являются аргументами.
Как и демонстрация высокомерия и агрессии.
Продолжение кормления троллей не считаю конструктивным.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.03.2023, 09:04

Singletone для Class library
приветствую всех, Каждый раз в каждом class где я работаю с class library я создаю объект. Говорят это не есть хорошо. ...

Паттерн singletone и unit of work
Изучаю паттерн unit of work.Чета я не сильно понял чем он отличается от singletone.И тот и тот создают только одну копию обьекта.Только...

IoC контейнер
Добрый день! Подскажите пожалуйста, как использовать IoC контейнер, например Ninject Использую EF. Создал Контекст: public class...

Spring ioc
Всем привет. Немного запутался по поводу ioc-контейнера. Что стоит отдавать ему под управление? К примеру сейчас столкнулся с такой...

DI/IoC из коробки
Вышел NET 4.7.2 , а вместе с ним приятные плюшки для форм: ASP.NET Поддержка внедрения зависимостей в веб-формах Внедрение...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru