Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Despre compania de aministrare Sq...

Durere taietura deget dupa 2 luni

Dalți gravare lemn

Didgeridoo
 Motorola Edge 50 Ultra

Gaura perete apartament cu evitar...

Orientare antena prime focus

Problema conectare mail yahoo
 comisioane asociatie proprietari

Primul sistem de televiziune cu p...

Internetul este neutilizabil fara...

Eroare cloud burn icopy face id
 DermaRoller ce este ?

Articole limba Germana

Cum se imparte legal o mostenire ...

Avem sanse sa avem energie electr...
 

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

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

#55
jegmihai

jegmihai

    Senior Member

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

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

Operatiile pe baza de date se fac cel mai bine prin repositories.
Prin repositories te referi la Repository Pattern?

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

Stii/nu ai uitat de "prefer composition over inheritance", nu?
Corect, nu am uitat.

View Postdani.user, on 18 septembrie 2018 - 18:23, said:

  • std::runtime_error ofera deja what(). N-are sens sa-l suprascrii fara sa aduci functionalitate suplimentara.
Corect, chiar nu știu de ce făceam asta.

View Postdani.user, on 18 septembrie 2018 - 18:23, said:

  • Specificarea return type-ului la final, ca aici auto createModel() noexcept->void;, mi se pare oribila. Are sens doar cand ai decltype si trebuie neaparat sa pui la final.
Personal prefer acest stil (cu return type-ul la final) deoarece denumirile metodelor sunt mai lizibile. Cum în cazul metodelor care returneaza un VeryLongDataTypeName, stilul are sens, am decis să fiu constant și în cazul celorlalte metode care returnează tipuri primitive.

View Postdani.user, on 18 septembrie 2018 - 18:23, said:

  • Observ multa logica dublata doar pentru a putea pasa cand std::string, cand QString.
Nu este cea mai clean soluție, știu. Cum ai îmbunătăți acest aspect?

View Postdani.user, on 18 septembrie 2018 - 18:23, said:

De cand cu std::string_view nu prea mai exista motive de a transmite std::string drept parametru.
Se pare că nu m-am documentat suficient de bine. Am intenționat să pasez std::string_view în metodele statice din QueriesManager, însă trăiam cu senzația că nu poți obține const char* - ul din el.

#56
OriginalCopy

OriginalCopy

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

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

View Postjegmihai, on 18 septembrie 2018 - 19:57, said:

Prin repositories te referi la Repository Pattern?
Da.

#57
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,231
  • Înscris: 24.02.2007

View Postjegmihai, on 18 septembrie 2018 - 19:57, said:

Personal prefer acest stil (cu return type-ul la final) deoarece denumirile metodelor sunt mai lizibile. Cum ĂŽn cazul metodelor care returneaza un VeryLongDataTypeName, stilul are sens, am decis să fiu constant și ĂŽn cazul celorlalte metode care returnează tipuri primitive.

Exista si solutii mai simple: lasi pe un rand VeryLongDataTypeName si incepi unul nou cu numele metodei.

Edited by dani.user, 18 September 2018 - 20:47.


#58
OriginalCopy

OriginalCopy

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

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

View Postdani.user, on 18 septembrie 2018 - 18:23, said:

Cateva observatii, pe partea specifica C++:
Cred ca acest topic merita pinned. As adauga la titlu "[...] pentru programatori mid-level"

View Postjegmihai, on 18 septembrie 2018 - 19:57, said:

Corect, nu am uitat.
Sper ca intelegi ca ce inveti de aici nu poate fi gasit in carti sau cursuri. Toti incearca sa iti vanda ceva, dar nimeni nu iti da o idee concreta despre cum sa faci asa incat codul sa nu fie legat ombilical de nimic. Ghidul <tehnologie aici> (ex: Qt) vrea sa faci lucrurile "the Qt way", cartile despre DDD vor sa faci lucrurile "the DDD way", vendorii de cloud vor sa faci lucrurile "the microservices way" s.a.m.d.

Arhitectura pe care ti-o dau e bazata pe POCO si nu am gasit o situatie in care nu e buna, poate fi suprapusa peste orice combinatie de tehnologii sau arhitecturi. E sinteza mea personala a foarte multor ani de proiecte de succes care ruleaza milioane / an, carti, articole si conferinte. Presupun ca exista proiecte facute curat de altii intr-un mod similar, dar eu nu am intalnit asa ceva pana acum in industrie. Unii POs sunt reticenti atunci cand incerci sa le "vinzi" ideea unei arhitecturi curate, deoarece au impresia ca ar costa mai mult. Eu iti arat cum poti face lucruri cu mijloace simple, pastrand codul curat, modular, si cu probabilitate de buguri mai mica.

Poti promite ca nu vei sterge niciodata acel proiect si ca nu il vei redenumi (URL-ul ramane acelasi)? Ar fi extrem de util pentru cei care vin dupa tine pe aici.

Follow me sau PM pentru linkedin.

#59
jegmihai

jegmihai

    Senior Member

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

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

Da.
OK, o să încerc să revin astăzi.

Pentru început, așa ar fi OK?

template <typename T, typename QueryModel>
class IRepository
{
	virtual ~IRepository() = default;

	virtual void add(T const& item) = 0;

	virtual void remove(int const id) = 0;

	virtual void update(int const id) = 0;

	virtual QueryModel search(T const& item) = 0;

	virtual QueryModel listAll() = 0;
};


View Postdani.user, on 18 septembrie 2018 - 18:23, said:

De cand cu std::string_view nu prea mai exista motive de a transmite std::string drept parametru.
Inclusiv în excepțiile custom?

View PostOriginalCopy, on 19 septembrie 2018 - 09:54, said:

Toti incearca sa iti vanda ceva, dar nimeni nu iti da o idee concreta despre cum sa faci asa incat codul sa nu fie legat ombilical de nimic. Ghidul <tehnologie aici> (ex: Qt) vrea sa faci lucrurile "the Qt way",
Într-adevăr, am observat acest lucru, cel puțin din documentațiile lor.

Înțeleg la ce te referi și trebuie să îți mulțumesc pentru aceste sugestii.

View PostOriginalCopy, on 19 septembrie 2018 - 09:54, said:

Poti promite ca nu vei sterge niciodata acel proiect si ca nu il vei redenumi (URL-ul ramane acelasi)?
Da, oricum nu văd ce motiv aș avea să-l șterg/mut.

View PostOriginalCopy, on 19 septembrie 2018 - 09:54, said:

Follow me sau PM pentru linkedin.
Îți voi trimite PM pentru LinkedIn.

#60
OriginalCopy

OriginalCopy

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

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

View Postjegmihai, on 19 septembrie 2018 - 10:52, said:

Pentru început, așa ar fi OK?
Da. Eu nu as face cu acel id numeric, ci as pasa tot T, dar presupun ca e ok, trebuie doar sa tii minte obiectele. Dar e o chestiune de gusturi pana la urma urmei. Mai mult conteaza sa ai o separare clara intre responsabilitati si contracte solide de comunicare intre componente.

#61
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Am introdus clasa Contact

#pragma once
#include <QString>
class Contact
{
public:
constexpr Contact(
	 QString const& lastName, QString const& firstName, QString const& phoneNumber);
constexpr auto lastName() const noexcept -> QString const&;
constexpr auto firstName() const noexcept -> QString const&;
constexpr auto phoneNumber() const noexcept -> QString const&;

private:
QString _lastName;
QString _firstName;
QString _phoneNumber;
};
inline constexpr Contact::Contact(
QString const& lastName, QString const& firstName, QString const& phoneNumber)
: _lastName(lastName)
, _firstName(firstName)
, _phoneNumber(phoneNumber)
{
}
inline constexpr auto Contact::lastName() const noexcept -> QString const &
{
return _lastName;
}
inline constexpr auto Contact::firstName() const noexcept -> QString const &
{
return _firstName;
}
inline constexpr auto Contact::phoneNumber() const noexcept -> QString const &
{
return _phoneNumber;
}


și ContactsSQLiteRepository

class ContactsSQLiteRepository : public IRepository<Contact, QSqlQueryModel*>
{
public:
ContactsSQLiteRepository();
void add(Contact const& item) override;
void remove(int const id) override;
void update(Contact const& newProperties, int const id) override;
QSqlQueryModel* search(Contact const& item) override;
QSqlQueryModel* listAll() override;
private:
QSqlDatabase _database;
QSqlQueryModel* _model;
};


Deocamdată este OK?

#62
OriginalCopy

OriginalCopy

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

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

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

Deocamdată este OK?
Nu. Clasa expune QSqlQueryModel. Nu vad utilitatea, pe langa problema cu leaky abstractions.

Returneaza obiecte Contact.

Folosirea lui Qt e un detaliu de implementare al plugin-ului, nu are ce sa caute la exterior.

Domain model-ul e numitorul comun al tuturor, pluginurile trebuie sa comunice in termenii din domain model.

#63
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Înțeleg, însă UiPlugin, în stadiul actual, tot va avea cumva nevoie de un Model.

Presupun că excludem din start o relație de friendship între cele 2 plugins.

Edited by jegmihai, 19 September 2018 - 16:22.


#64
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,231
  • Înscris: 24.02.2007
Folosind doar API-ul C al sqlite, alaturi de biblioteca standard C++ te poate ajuta sa scrii cod mai idiomatic, cu resource management adecvat (fara pointeri membrii).

Edited by dani.user, 19 September 2018 - 19:25.


#65
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Da, dar API-ul C nu poate suplini QueryModel-ul de care are nevoie View-ul.

De fapt, cred că QSqlQueryModel este singurul membru pe care am fost obligat să-l aloc pe heap din tot proiectul. Unde va fi posibil voi folosi unique_ptr.

Edited by jegmihai, 19 September 2018 - 20:48.


#66
dani.user

dani.user

    Guru Member

  • Grup: Senior Members
  • Posts: 30,231
  • Înscris: 24.02.2007
Daca acel querymodel e o necesitate doar pentru view, sa-si creeze viewul unul, ca detaliu intern de implementare.

#67
OriginalCopy

OriginalCopy

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

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

View Postjegmihai, on 19 septembrie 2018 - 16:18, said:

Înțeleg, însă UiPlugin, în stadiul actual, tot va avea cumva nevoie de un Model.
Bineinteles ca are nevoie de un model. Si doar ce l-ai creat, se numeste Contact.

Ce crezi ca este Contact, daca nu un model (as in model-view-controller)?

A, ca nu e stampila Qt pe el, da, nu e. E un model de model, fara bagaje suplimentare.

#68
jegmihai

jegmihai

    Senior Member

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

View Postdani.user, on 19 septembrie 2018 - 20:44, said:

Daca acel querymodel e o necesitate doar pentru view, sa-si creeze viewul unul, ca detaliu intern de implementare.
Nu sună rău, însă nu știu dacă este cea mai bună soluție dpdv arhitectural. Poate ne lămurește OriginalCopy în legătură cu acest aspect.

View PostOriginalCopy, on 19 septembrie 2018 - 20:51, said:

Si doar ce l-ai creat, se numeste Contact.
Există o problemă legată de Contact. Baza de date atribuie fiecărei înregistrări câte un id, însă Contact nu știe de acel id.

std::vector<Contact> ContactsSQLiteRepository::search(Contact const& item)
{
QSqlQuery query = QueriesManager::createSearchPersonQuery(item.lastName(), item.firstName());
if (!query.exec())
	 throw CouldNotSearchForTheContactException(query.lastError().text().toStdString());
else
{
	 std::vector<Contact> contacts;
	 QString lastName;
	 QString firstName;
	 QString phoneNumber;
	 while (query.next())
	 {
		 lastName = query.value("lastname").toString();
		 firstName = query.value("firstname").toString();
		 phoneNumber = query.value("phonenumber").toString();
		 Contact contact(lastName, firstName, phoneNumber);
		 contacts.push_back(contact);
	 }
	 return contacts;
}
return std::vector<Contact>();
}


În momentul în care voi lega Model-ul de View, cel din urmă nu va afișa și id-ul.

Am făcut update Repository-ului de contacte.

class ContactsSQLiteRepository : public IRepository<Contact>
{
public:
ContactsSQLiteRepository();
void add(Contact const& item) override;
void remove(int const id) override;
void update(Contact const& newProperties, int const id) override;
std::vector<Contact> search(Contact const& item) override;
std::vector<Contact> listAll() override;
private:
QSqlDatabase _database;
QSqlQueryModel* _model;
};



#69
OriginalCopy

OriginalCopy

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

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

View Postjegmihai, on 19 septembrie 2018 - 22:19, said:

Nu sună rău, însă nu știu dacă este cea mai bună soluție dpdv arhitectural. Poate ne lămurește OriginalCopy în legătură cu acest aspect.


Există o problemă legată de Contact. Baza de date atribuie fiecărei înregistrări câte un id, însă Contact nu știe de acel id.

Deci, dincolo de mecanismul de salvare (db sau nu), un id nu este o caracteristica intrinseca unui model-copil, ci a unui model-parinte: te ajuta sa identifici copilul in interiorul parintelui; il intrebi pe parinte: "care e copilul cu id-ul 42?", si parintele iti spune.


Nu inteleg ce problema descrii de fapt. Dar avant in vedere paragraful anterior, poti descrie problema cu id-ul? Asta daca nu iti raspunde deja la intrebare...


PS: copil = Contact, parinte = PhoneBook.

Edited by OriginalCopy, 19 September 2018 - 22:59.


#70
jegmihai

jegmihai

    Senior Member

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

View PostOriginalCopy, on 19 septembrie 2018 - 22:59, said:

Nu inteleg ce problema descrii de fapt. Dar avant in vedere paragraful anterior, poti descrie problema cu id-ul?
Procedurile de Update și Delete au nevoie de id.

De aici deducem că user-ul trebuie să știe de dinainte ce se află în spatele acelui id, iar acest lucru îl putea afla prin intermediul View-ului.

#71
OriginalCopy

OriginalCopy

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

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

View Postjegmihai, on 20 septembrie 2018 - 08:56, said:


Procedurile de Update și Delete au nevoie de id.

De aici deducem că user-ul trebuie să știe de dinainte ce se află în spatele acelui id, iar acest lucru îl putea afla prin intermediul View-ului.

A, cred că știu de unde vine neînțelegerea.

Nu ai înțeles ce am scris anterior cum că eu nu aș pasa id pentru identificare, ci Contact cu totul.

Iar db plugin ar ține minte intern o mapare între adresele obiectelor Contact și id-urile lor.

Asta ar fi fără id in semnătură.

Cu id în semnătură, filozofia ta ar fi că id-ul e o caracteristică a lui phonebook, iar metode ca search ar returna phonebook (care are un map în interior cu acele id-uri).

Eu unul prefer metoda asta deoarece se potrivește mai bine cu domain model: un phonebook are contacts în el (identificate prin id-uri). Bașca că nu ne mai batem capul cu pointeri (sau un alt mecanism pe care ar trebui să îl inventăm) - path of least resistance.

#72
jegmihai

jegmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 11,536
  • Înscris: 03.09.2013
Am revenit cu un update, am adăugat noul Storage Plugin.

Am avut în vedere următoarele lucruri:
  • ContactsSQLiteRepository să nu aibă metode publice care i-ar putea corupe state-ul. Prin urmare, am decis ca toate operațiile de inițializare să fie făcute în constructorul default.
  • StoragePlugin să expună doar o interfață abstractă și nu o clasă concretă.
Pe de altă parte, din cauza/datorită acestui approach, metodele specifice IPlugin, respectiv init() și run(), au devenit cam...nefolositoare.

Anunturi

Chirurgia spinală minim invazivă Chirurgia spinală minim invazivă

Chirurgia spinală minim invazivă oferă pacienților oportunitatea unui tratament eficient, permițându-le o recuperare ultra rapidă și nu în ultimul rând minimizând leziunile induse chirurgical.

Echipa noastră utilizează un spectru larg de tehnici minim invazive, din care enumerăm câteva: endoscopia cu variantele ei (transnazală, transtoracică, transmusculară, etc), microscopul operator, abordurile trans tubulare și nu în ultimul rând infiltrațiile la toate nivelurile coloanei vertebrale.

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