Inversion of Control

Juro

Re:Inversion of Control
« Odpověď #15 kdy: 25. 01. 2016, 23:16:04 »
... místo toho, abych volal nějaké API typu Notificator::getInstance()->showNotification(new Notification("NAZDAR")), tak pošlu skrz jasně definovaný kanál nějakou událost např. NotificationReques...

Prva vec, nad ktoru sa treba vzdy zamysliet je, ci sa to neda nahradit niecim ako notify("NAZDAR"). Viem, ze islo o priklad a davam to tiez ako priklad. Kod treba pisat co najjednoduchsie a nie co najzlozitejsie. Ked nepotrebujem v celej aplikacii IoC, tak nebudem robit v celej aplikacii IoC.


Kit

Re:Inversion of Control
« Odpověď #16 kdy: 25. 01. 2016, 23:40:10 »
... místo toho, abych volal nějaké API typu Notificator::getInstance()->showNotification(new Notification("NAZDAR")), tak pošlu skrz jasně definovaný kanál nějakou událost např. NotificationReques...

Prva vec, nad ktoru sa treba vzdy zamysliet je, ci sa to neda nahradit niecim ako notify("NAZDAR"). Viem, ze islo o priklad a davam to tiez ako priklad. Kod treba pisat co najjednoduchsie a nie co najzlozitejsie. Ked nepotrebujem v celej aplikacii IoC, tak nebudem robit v celej aplikacii IoC.

Také si to myslím a z daného příkladu bych to udělal asi takto:
Kód: [Vybrat]
notificator = new Notification(Notificator::getInstance());
// ...
notificator->show("NAZDAR");

DI je na prvním řádku, kde je uvedeno, kam bude objekt notificator posílat zprávy. Takových objektů je možné vyrobit víc, další může být např. objekt errorNotificator, který bude zprávy posílat jinam než ten první. Se dvěma notifikátory už se dá vyřádit docela dobře a dokonce i metoda show() může být mnohonásobně přetížena, aby se dalo notifikovat prakticky cokoli.

lopata

Re:Inversion of Control
« Odpověď #17 kdy: 25. 01. 2016, 23:56:44 »
... místo toho, abych volal nějaké API typu Notificator::getInstance()->showNotification(new Notification("NAZDAR")), tak pošlu skrz jasně definovaný kanál nějakou událost např. NotificationReques...

Prva vec, nad ktoru sa treba vzdy zamysliet je, ci sa to neda nahradit niecim ako notify("NAZDAR"). Viem, ze islo o priklad a davam to tiez ako priklad. Kod treba pisat co najjednoduchsie a nie co najzlozitejsie. Ked nepotrebujem v celej aplikacii IoC, tak nebudem robit v celej aplikacii IoC.

Také si to myslím a z daného příkladu bych to udělal asi takto:
Kód: [Vybrat]
notificator = new Notification(Notificator::getInstance());
// ...
notificator->show("NAZDAR");

DI je na prvním řádku, kde je uvedeno, kam bude objekt notificator posílat zprávy. Takových objektů je možné vyrobit víc, další může být např. objekt errorNotificator, který bude zprávy posílat jinam než ten první. Se dvěma notifikátory už se dá vyřádit docela dobře a dokonce i metoda show() může být mnohonásobně přetížena, aby se dalo notifikovat prakticky cokoli.

Ale to je jedno, klidně to může být třeba jenom notify("Nazdar"). To co jsem uváděl je příklad nějaké klasické implementace bez toho mého sporného IoC, o kterém by se dalo polemizovat, jestli to teda je IoC nebo ne. Ta pointa není v tom, jestli si někdo udělá nějakou helper metodu notify, aby všude nemusel psát těch xy znaků. Ta pointa je v tom, že se používá nějaké třída Notificator, která má nějakou implementaci, třeba zobrazovaní někam do rohu okna apod..
Ale já nechci použávat nějakou konkrétní implementaci. Ja chci zobrazit zprávu, to je všechno. Jak se zobrazí, kde, jak velká apod., to je jedno. Takže já místo abych používal nějakou konkrétní implementaci Notificator, tak pošlu zprávu ShowNotificationRequest a nechám nějaký plugin nebo jakoukoliv jinou část systému, aby se postarala o zpracování této žádosti.

EventBroker::sendEvent(new ShowNotificationRequest(new Notification("Nazdar")))



k

Re:Inversion of Control
« Odpověď #18 kdy: 26. 01. 2016, 00:07:58 »
Všechno může být součástí definice té zprávy neboť definice zprávy = C++ třída.

Pod pojmem nezávislost si představuji že především nemusím shánět nějaké .h s definicí čehokoliv :)

Chci třeba odesílat email, mám nějaké rozhraní IEmailService, tak si požádám o implementaci zasláním toho požadavku a výsledkem bude získaná reference na implementaci IEmailService. Kdybych používal nějaké factory třídy, tak bych je zase musel explicitně někam dosadit. Takhle se odněkud jen přihlásím k odběru eventů CreateServiceRequest a pokud takový event přijde.

Je to to, že nechcete vytvářet instanci takhle
my_mail_instance = new MailSender()
ale chcete někam vyslat zprávu central_brain_of_mankind.CreateRequest(...), aby vám v odpovědi ResponseRequest přišla instance ?

To můžete rovnou napsat dynamic_cast<IEmailService>(central_brain_of_mankind.GetInstance("EmailService)) a ušetříte spoustu psaní :-)

k

Re:Inversion of Control
« Odpověď #19 kdy: 26. 01. 2016, 00:11:25 »
EventBroker::sendEvent(new ShowNotificationRequest(new Notification("Nazdar")))

dynamic_cast<INotificationService>(central_brain_of_mankind.GetInstance("NotificationService)).Show("Nazdar");


lopata

Re:Inversion of Control
« Odpověď #20 kdy: 26. 01. 2016, 00:16:08 »

Chci třeba odesílat email, mám nějaké rozhraní IEmailService, tak si požádám o implementaci zasláním toho požadavku a výsledkem bude získaná reference na implementaci IEmailService. Kdybych používal nějaké factory třídy, tak bych je zase musel explicitně někam dosadit. Takhle se odněkud jen přihlásím k odběru eventů CreateServiceRequest a pokud takový event přijde.

Je to to, že nechcete vytvářet instanci takhle
my_mail_instance = new MailSender()
ale chcete někam vyslat zprávu central_brain_of_mankind.CreateRequest(...), aby vám v odpovědi ResponseRequest přišla instance ?

To můžete rovnou napsat dynamic_cast<IEmailService>(central_brain_of_mankind.GetInstance("EmailService)) a ušetříte spoustu psaní :-)

Jo přesně tak, konečně to někdo pochopil. Když požadavek bude chtít nějakou odpověď, tak pro ni bude místo už v tom požadavku, takže by ten požadavek měl třeba datový člen EmailService* resolvedService nebo tak něco.

Ta varianta s tím dynamic castem je druhá možnost, že tam bude někde něco jako ServiceRepository nebo tak něco. Akorát ty eventy mají výhodu v tom, že na ně může teoreticky reagovat víc částí, můžu logovat veškerou aktivitu aplikace, můžu event potlačit, prostě by to bylo flexibilnější.
Psaní by se ani moc nemuselo ušetřit. 

k

Re:Inversion of Control
« Odpověď #21 kdy: 26. 01. 2016, 00:31:51 »
Teoreticky může na zprávu reagovat víc částí, prakticky budete mít v aplikaci jednu DLLku s EmailService :-)
Tudíž se můžete navrátit ke klasice v EmailService.dll jedna exportovaná C funkce CreateEmailServiceInstance a ta vrací pointer na IEmailService.
Popřípadě k CoCreateInstance.

Re:Inversion of Control
« Odpověď #22 kdy: 26. 01. 2016, 00:40:56 »
Jedná se o docela složitou GUI aplikaci v C++.
Další případ by bylo např. otevření souboru. Uživatel pokliká na nějaký soubor a místo explicitního volání nějaké metody typu EditorUtility::openFile("file")
by se vyslala událost RequestOpenFile a např. nějaký plugin by se postaral o vyřízení.

Výhodu vidím velkou právě např. v tom, že komponenty budou na sobě nezávislé [...]

Tak mě to napadlo, třeba se to někde už používá? 
Ano, přesně takhle to funguje v Erlangu.

Ivan Nový

Re:Inversion of Control
« Odpověď #23 kdy: 26. 01. 2016, 01:43:26 »
Trochu mícháte dvě věci, design patterns a application patterns, viz zde https://msdn.microsoft.com/en-us/library/ee413983.aspx, nebo zajímavý vzor "pumpy a filtry", viz zde http://www.enterpriseintegrationpatterns.com/patterns/messaging/PipesAndFilters.html. A další tamtéž.

Kit

Re:Inversion of Control
« Odpověď #24 kdy: 26. 01. 2016, 02:23:00 »
Trochu mícháte dvě věci, design patterns a application patterns, viz zde https://msdn.microsoft.com/en-us/library/ee413983.aspx,

Bylo by dobré nemíchat patterny s Microsoftem. To opravdu nejde dohromady.