Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Cum accesez site-ul CNAS ?

Algoritm simplu de calculare al u...

Bitdefender Total Security ș...

casa verde 2024
 Intrerupator cu N - doza doar cu ...

Incalzire casa fara gaz/lemne

Incalzire in pardoseala etapizata

Suprataxa card energie?!
 Cum era nivelul de trai cam din a...

probleme cu ochelarii

Impozite pe proprietati de anul v...

teava rezistenta panou apa calda
 Acces in Curte din Drum National

Sub mobila de bucatarie si sub fr...

Rezultat RMN

Numar circuite IPAT si prindere t...
 

Baze de date embedded – exercitiu practic (pentru programatori mid-level)

* * * - - 2 votes
  • Please log in to reply
183 replies to this topic

#19
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
QSqlQueryModel ar fi un obiect specific plugin-ului de UI?

#20
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013

View PostOriginalCopy, on 13 septembrie 2018 - 14:38, said:

Plugin e ceva foarte abstract, folosit doar la initializarea și deinitializarea întregii aplicații.

Într-o interfață Plugin ai o metodă de genul getDependencies, și  altele gen init(), run() și shutdown().
Am început sa scriu pe partea de plugins. Înainte de a merge mai departe, aș vrea să mă asigur că mă aflu pe calea cea bună.

#21
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006

View Postjegmihai, on 13 septembrie 2018 - 17:19, said:

QSqlQueryModel ar fi un obiect specific plugin-ului de UI?
Numele nu imi spune exact ce e. Poate da, poate nu. Dar in ultima instanta, cererile catre baza de date se fac de catre Repository, care se afla in storage plugin.

View Postjegmihai, on 13 septembrie 2018 - 18:09, said:

Am început sa scriu pe partea de plugins. Înainte de a merge mai departe, aș vrea să mă asigur că mă aflu pe calea cea bună.

Da, e bine. Metoda init sau cum ai numit-o trebuie totusi sa accepte ca parametru acelasi tip de date ca cel returnat de getDependencies. Nu stiu de ce returnezi vector<Dependency> si nu vector<Plugin> totusi.

#22
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006
src/ui_files/ se muta in desktop plugin, pentru ca apartine acelui plugin.

#23
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013

View PostOriginalCopy, on 13 septembrie 2018 - 18:20, said:

NumeMetoda init sau cum ai numit-o trebuie totusi sa accepte ca parametru acelasi tip de date ca cel returnat de getDependencies.
Te referi la metoda initiatePlugins() din clasa PhoneBook?

Altfel nu înțeleg de ce un Plugin ar trebui să poată inițializa pe altul (dacă te referi la metoda init() din IPlugin).

#24
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006
Acum inteleg de ce ai clasa Dependency (am uitat ca suntem in C++), dar ce am zis ramane ca si principiu valabil:

Un plugin nu il initializeaza pe altul. Fiecare plugin isi declara dependintele. Si in metoda init(), fiecare plugin trebuie sa primeasca ca parametru celelalte plugin-uri de care a zis ca depinde.

Eu ca plugin, zic ca am nevoie de ceva, si apoi tu ca caller imi dai ce am zis eu ca am nevoie.

Cine e "tu ca caller"? Pai Application, o clasa responsabila de initializarea in ordinea corecta a tuturor pluginurilor (chiar si prin interpusi). Aceeasi clasa Application care are metoda execute() sau cum vrei tu s-o numesti, pe care o apelezi in main(). Application nu e nici ea dependenta de niciun vendor.

Imagineaza-ti ca eu, plugin de UI, am nevoie sa cer ceva de la read model. Read model e in interiorul lui storage plugin. Deci am nevoie de o instanta a acelui storage plugin, de la care pot cere read model, si face ceva cu el in UI.

Si tot asa.

#25
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013

View PostOriginalCopy, on 13 septembrie 2018 - 14:38, said:

Cât despre repository, folosește std::string.
Done, am făcut overload metodelor deja existente.

Am mai făcut un update pentru partea de plugins.

View PostOriginalCopy, on 13 septembrie 2018 - 19:06, said:

Si in metoda init(), fiecare plugin trebuie sa primeasca ca parametru celelalte plugin-uri de care a zis ca depinde.
Aceasta fiind o modalitate de asigurare că celelalte plugins există și nimic mai mult?

În implementarea actuală simt că am cheat-uit acest lucru.

#26
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006

View Postjegmihai, on 13 septembrie 2018 - 22:50, said:

Aceasta fiind o modalitate de asigurare că celelalte plugins există și nimic mai mult?

În implementarea actuală simt că am cheat-uit acest lucru.
E vital. Nu poate functiona altfel.

Daca eu, plugin de UI, am nevoie de read model, si nu reusesc sa pun mana pe un read model, atunci nu pot functiona cum trebuie.

#27
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013

View PostOriginalCopy, on 13 septembrie 2018 - 23:03, said:

E vital. Nu poate functiona altfel.
Până să ajung să încerc să implementez, totul era foarte abstract.

View PostOriginalCopy, on 13 septembrie 2018 - 23:03, said:

Daca eu, plugin de UI, am nevoie de read model, si nu reusesc sa pun mana pe un read model, atunci nu pot functiona cum trebuie.
Am ajuns în acest punct.

View PostOriginalCopy, on 13 septembrie 2018 - 19:06, said:

Imagineaza-ti ca eu, plugin de UI, am nevoie sa cer ceva de la read model. Read model e in interiorul lui storage plugin. Deci am nevoie de o instanta a acelui storage plugin, de la care pot cere read model, si face ceva cu el in UI.
În acest caz, problema ar fi următoarea: singurul loc în care cele 2 plugins ar putea interacționa este clasa PhoneBook, însă clasa PhoneBook nu știe nimic altceva despre ele decât că sunt niște IPlugin-uri cu metodele aferente interfeței.

#28
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006

View Postjegmihai, on 14 septembrie 2018 - 13:49, said:

În acest caz, problema ar fi următoarea: singurul loc în care cele 2 plugins ar putea interacționa este clasa PhoneBook, însă clasa PhoneBook nu știe nimic altceva despre ele decât că sunt niște IPlugin-uri cu metodele aferente interfeței.
Poti castui obiectele. In getDependencies() spui ce vrei, in init() te astepti sa primesti ce ai cerut. Daca nu primesti, eroare (exceptie, return false, logging, etc)

#29
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006
Fa un sistem mai abstract. Asa nu e abstract, e cod duplicat: https://github.com/I...k/phonebook.cpp

Lucreaza doar cu IPlugin in PhoneBook (presupun ca asta e clasa pe care eu am numit-o mai sus "Application").

Domeniul de business (tot codul din src/phonebook/) nu are voie sa depinda de un plugin sau altul. Asta ar viola definitia de plugin.

Domeniul are voie sa stie doar de notiunea de "plugin", deci sa aiba o singura metoda: addPlugin(). Domeniul nu stie si nu ii pasa ce face fiecare plugin.

Pluginurile pot depinde intre ele, si pot depinde de business model, niciodata invers (=definitia lui "plugin").

In momentul in care o clasa e mentionata intr-o compilation unit, spunem ca acea compilation unit depinde de acea clasa.

"Plugin" e doar ceea ce respecta directia clara de dependinte, asa cum am descris-o mai sus.

Altfel nu se numeste plugin, ci tightly coupled component.

Edited by OriginalCopy, 14 September 2018 - 15:50.


#30
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Ar fi firesc ca un anumit plugin să poată fi inițializat fără vreo dependință?

InMemorySQLiteStoragePlugin nu pare să depindă de nimeni.

#31
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006

View Postjegmihai, on 14 septembrie 2018 - 16:47, said:

Ar fi firesc ca un anumit plugin să poată fi inițializat fără vreo dependință?

InMemorySQLiteStoragePlugin nu pare să depindă de nimeni.

Bineînțeles.

Doar food for thought: ar putea depinde de un plugin de logging. Sau unul de caching.

Acestea sunt "cross-cutting concerns"  întâlnite în mod comun în aplicații, cum le-am menționat aici: https://forum.softpe.../#entry23060478

Și nu e musai să le faci ca pluginuri, există și metoda prin AOP, sau multe alte variații, în funcție de alte detalii. Menționez doar așa ca fapt divers, ca să conectez diferite postări ale mele, poate le citești sau le-ai citit, și vrei să le integrezi undeva în sistemul tău propriu de gândire.

Unele pluginuri chiar e strict necesar să nu aibă nicio dependență. Vrei într-un final să ai un graf aciclic. Dacă ai unul ciclic, atunci e extrem, extrem de probabil să fi făcut o greșeală în arhitectură.

#32
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Am făcut un update pe GitHub. Aplicația funcționează, însă nu sunt sigur dacă totul este așa cum ar trebui.

Am și o nelămurire. Aici ai spus așa:

View PostOriginalCopy, on 13 septembrie 2018 - 19:06, said:

Pai Application, o clasa responsabila de initializarea in ordinea corecta a tuturor pluginurilor (chiar si prin interpusi).

Apoi ai spus așa:

View PostOriginalCopy, on 14 septembrie 2018 - 15:22, said:

Domeniul are voie sa stie doar de notiunea de "plugin", deci sa aiba o singura metoda: addPlugin(). Domeniul nu stie si nu ii pasa ce face fiecare plugin.


#33
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006
"initializarea" adica apelarea metodelor init() in ordinea corecta ***. Nu "instantierea". Instantierea fiecarui plugin o vei face cel mai probabil in main.cpp.

*** pentru a indeplini aceasta misiune, trebuie sa apelezi getDependencies() mai intai pentru fiecare plugin, si o clasa Graph ("interpusul" mentionat in alta postare) cu care faci sortarea topologica.


Acest intreg sistem de pluginuri mai elaborat e poate prea complicat pentru aplicatia de fata. Poti avea doar init(), pe care il apelezi direct in main pentru fiecare plugin, in ordinea corecta. Depinde de ce urmaresti. Daca vrei doar sa GTD, dar totusi o separare curata, atunci sterge getDependencies() si asambleaza-ti aplicatia direct in main, manual, fara Graph si toate cele.

Daca vrei sa iti faci o infrastructura de cod reutilizabila si in aplicatii mai complexe, poti face de la inceput aceasta intreaga poveste cu getDependencies(). Sau faci totul in main() deocamdata, si dupa ce aplicatia e "gata", introduci si sistemul de plugins mai sistematic cu getDependencies() (e destul de simplu, o data ce ai oricum codul separat frumos).

Greseala pe care o vad momentan e ca getDependencies() returneaza vector<Plugin*>: un plugin nu poate returna pointeri la alte pluginuri. vector<Dependency> era corect. init() insa primeste un vector de pluginuri (cu pluginurile specificate de getDependencies).

Nu stiu exact unde in modul de gandire a fost greseala ta, dar asta e manifestarea greselii de gandire in cod pe care o vad.

Deci, ai doua optiuni mari si late:

1. instantierea si initializarea in main(), totul manual
2. instantierea in main(), addPlugin() pentru fiecare, si return application.run() in main(). pluginul UI va fi executat ultimul datorita sortarii topologice, si va bloca main thread. initializarea se face de catre Application (=PhoneBook) cu ajutorul interpusului Graph.

Edited by OriginalCopy, 14 September 2018 - 18:23.


#34
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Pentru început voi merge pe approach-ul numărul 1. Îmi rezerv puțin timp pentru a mă documenta cu privire la topological sorting.

Referitor la următoarea remarcă:

Quote

Lines 28-29 should be just one: return uiPlugin.run();

Astfel aș fi nevoit să modific interfața și să oblig orice plugin să returneze o valoare în urma metodei run().

Pentru UiPlugin acest lucru este total în regulă, însă, spre exemplu, storage plugin nu are nevoie să returneze o valoare. Dacă s-ar întampla ceva ce nu trebuie, el ar arunca o excepție.

#35
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Am revenit cu un update pe GitHub, având însă problema menționată mai sus.

View Postjegmihai, on 15 septembrie 2018 - 19:03, said:

Astfel aș fi nevoit să modific interfața și să oblig orice plugin să returneze o valoare în urma metodei run().


#36
OriginalCopy

OriginalCopy

    I'm harmful, fear me please! :))

  • Grup: Senior Members
  • Posts: 27,268
  • Înscris: 10.08.2006

View Postjegmihai, on 15 septembrie 2018 - 19:03, said:

Dacă s-ar întampla ceva ce nu trebuie, el ar arunca o excepție.
Eu nu as lasa exceptiile sa treaca dincolo de granita pluginurilor. Un plugin pentru mine e o bariera stricta de separare: ii dai niste lucruri prin constructor, o initializezi, si iti returneaza bool.

Complexitatea unui plugin e mare, iar in componentele mari, complexe, vei avea cel mai probabil si clase de exceptii dedicate. De exemplu NoDisplayException - aruncat de UI daca aplicatia e rulata pe un server (care nu are display). Vrei ca aceasta exceptie sa ajunga in apelant? Asadar, apelantul (core domain) trebuie sa stie de modul de comunicare cu userul? Sau cu alte cuvinte: sa cuplezi domeniul de un plugin? Pai asta ar viola principiul mentionat anterior: definitia unui plugin = depinde de alte pluginuri si de core domain; definitia core domain = nu depinde de nimic. Ai viola directia dependintelor.

Pe langa asta, o eroare e cel mai bine tratata exact in locul in care ea are loc. De ce? Pentru ca in acel loc ai contextul cel mai larg, ai cele mai multe informatii despre ce s-a intamplat si de ce, ai toate variabilele ***. Motivul pentru care uneori nu tratezi local eroarea e ca ai clase de erori care pot fi tratate similar. Acele erori au loc in diferite parti ale codului.

*** daca nu ai acces la toate variabilele, direct sau indirect, e pentru ca ai un "neg" in arhitectura, nu ai injectat consistent toate dependintele de care ai nevoie.

Una dintre principiile usoare in arhitectura e sa ai straturi (layered architecture). Aplicatia privita din avion e cu un core domain, in care inserezi niste pluginuri. Din avion, arhitectura fiecarui plugin nu conteaza, e un detaliu de implementare, insa in interiorul pluginului ai iar alte straturi.

Un alt motiv pentru care nu tratezi local eroarea e deoarece poti generaliza eroarea si prin generalizare, o poti trata (catch block) intr-un layer de mai de sus in arhitectura.

Acum, cat de sus permiti exceptiilor sa "bubble up" pana cand le prinzi si tratezi (try catch)?

Dupa parerea mea, ultimul transon de aparare impotriva unei exceptii e in plugin (chiar in metoda run). Asa, poti izola mult mai punctual o eroare.

De ce vad asa lucrurile? Una dintre motivatiile de a separa in pluginuri e ca poti imparti responsabilitati intr-o echipa: un programator e responsabil de pluginul X, altul de pluginul Y, s.a.m.d. (cu overlap si alte chestii, irelevante in aceasta discutie). In momentul in care in log vezi ca o eroare a aparut in pluginul de UI, ii pui in brate ticketul din bug tracker persoanei cu cea mai multa experienta in acea zona fara foarte mult efort: nu trebuie sa stai sa inspectezi eroarea, sa incerci sa o reproduci timp de 1-2 zile, doar ca sa iti dai seama cine trebuie sa o rezolve.

Astfel cresti eficienta echipei. Vrei sa cresti numarul de evenimente "persoana potrivita la problema potrivita".

Anunturi

Chirurgia endoscopică a hipofizei Chirurgia endoscopică a hipofizei

"Standardul de aur" în chirurgia hipofizară îl reprezintă endoscopia transnazală transsfenoidală.

Echipa NeuroHope este antrenată în unul din cele mai mari centre de chirurgie a hipofizei din Europa, Spitalul Foch din Paris, centrul în care a fost introdus pentru prima dată endoscopul în chirurgia transnazală a hipofizei, de către neurochirurgul francez Guiot. Pe lângă tumorile cu origine hipofizară, prin tehnicile endoscopice transnazale pot fi abordate numeroase alte patologii neurochirurgicale.

www.neurohope.ro

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Forumul Softpedia foloseste "cookies" pentru a imbunatati experienta utilizatorilor Accept
Pentru detalii si optiuni legate de cookies si datele personale, consultati Politica de utilizare cookies si Politica de confidentialitate