Baze de date embedded – exercitiu practic (pentru programatori mid-level)
Last Updated: Oct 10 2018 14:21, Started by
jegmihai
, Sep 07 2018 22:27
·
0

#73
Posted 20 September 2018 - 11:39

Am revenit cu un update, am adăugat noul Storage Plugin. Am avut în vedere următoarele lucruri:
Vezi si ce ti-a zis dani: "shutdown" devine destructor. Baza de date trebuie instantiata in db plugin, si conexiunea inchisa in destructorul lui db plugin. Clasele pe care le ai sunt in general ok (mai e nevoie de lucru, dar directia e buna). Cea mai mare problema e ca nu ai o piramida, un arbore, in arhitectura, ci doar clase care atarna in pom, si pomul in aer. Imagineaza-ti o piramida construita din straturi (layers). La varful piramidei se afla aplicatia, care e doar una (ma rog, mici varfuri, pentru fiecare entry point - dar momentan ai doar un main.cpp). Application manageriaza layerele de sub ea, adica plugins, fiecare plugin manageriaza resursele de sub el, adica resursele (conexiune la baza de date, repositories, dialoguri, etc). Conexiunea la baza de date manageriaza lucrurile specifice unei baze de date, dialogurile manageriaza input boxes, s.a.m.d. => o structura arborescenta. Nu vrei sa ai puncte de acces ad-hoc: daca ai nevoie de ceva de la db, in ui fiind, trebuie sa treci prin db plugin mai intai. Punctul de contact dintr-un plugin intr-altul e mereu printr-un obiect IPlugin. Layerele de deasupra sunt responsabile pentru copii lor. |
#74
Posted 20 September 2018 - 15:15

Dacă shutDown() va deveni destructor voi fi nevoit să mă conformez cu Rule Of Five. Totuși, mă gândesc să dezactivez copy + move constructors, respectiv assignment operators.
Dpdv arhitectural presupun că te referi la așa ceva: https://upload.wikim...Version.svg.png Sau chiar la ceva mai complex. |
#75
Posted 20 September 2018 - 15:35

Sau așa?
[ https://dzone.com/storage/temp/4277164-layered-architecture-overview.png - Pentru incarcare in pagina (embed) Click aici ] |
#76
Posted 20 September 2018 - 16:00

Aia este arhitectura fluxului de date, si da, asa sunt mutate datele de colo colo in aplicatia ta.
Eu vorbeam despre arhitectura structurala a codului. Problema cu "arhitectura" e ca ai atatea arhitecturi cati programatori, fiecare da cate un nume la cate ceva, si fiecare pune accentul pe unele aspecte mai mult sau mai putin. In principiu, mai toate respecta aceleasi principii fundamentale, pe care le aplicam si noi aici (si principii au tot fost numite deja pe acest topic). Exemple de denumiri: https://nathanjohnst...e-architecture/ https://jeffreypaler...tecture-part-1/ https://medium.freec...re-990c014448d2 DDD introduce ceva idei care pot fi combinate cu cele de mai sus: https://en.wikipedia...n-driven_design Ce faci aici deocamdata e mai mult "onion architecture", dar poti sa o numesti si "hexagonal", si deja folosesti un termen folosit de obicei in cercurile DDD (repository). E un melanj. Numele nu conteaza pana la urma urmei, adopti idei si concepte si le implementezi in functie de nevoi. Poti sa mulezi ce faci aici pe oricare dintre ele oricum, sau chiar doar anumite componente poti sa le faci dupa anumite strategii - de exemplu chiar DDD recomanda sa nu faci "DDD in toata aplicatia", ci doar unde merita. E irelevant, really. Aici vrem doar ca tu sa ai o fundatie foarte limitata dar destul de robusta incat cercetarile si cartile pe care le vei citi sa pot fi integrate usor in acest "framework of mind" pe care il construiesti acum. Adica: sa citesti acele articole si carti, si sa "vezi codul in fata ochilor", doar citind ideile abstracte ale arhitectilor respectivi. Dupa ce iti iei zborul, iti vei dezvolta propriul corp de idei. Addendum: pe scurt, momentan ai directia dependintelor ca in onion, dar separarea curata (prin plugins) din hexagonal, si o idee din DDD (repository), dar vom mai adauga cel putin inca una din DDD: value objects. Edited by OriginalCopy, 20 September 2018 - 15:56. |
#77
Posted 20 September 2018 - 20:08

#78
Posted 20 September 2018 - 20:23

FirstName, LastName, PhoneNumber, ContactId, ar fi cateva exemple de value objects.
Introduse peste tot pe unde variabilele se numesc first_name, etc. Avantaj: iti protejeaza domeniul de date corupte. In constructorul value objects arunci o exceptie daca datele sunt invalide. Deoarece toate componentele accepta doar value objects (faci semnatura metodelor sa dicteze asta), protejezi toate componentele de coruperi simple, sintactice. Nu te protejeaza de date corupte semantic, de exemplu un nr de telefon detinut de doua contacte. Alt avantaj: e mai usor sa cauti. Una e sa cauti dupa "string", alta dupa "FirstName". Si inca unul: expresivitatea domain model (mentionat intr-o postare anterioara si care e avantajul). |
#79
Posted 20 September 2018 - 20:58

Value objects le voi face immutable. Este redundant să le pasez prin const&?
Edited by jegmihai, 20 September 2018 - 20:59. |
#80
Posted 20 September 2018 - 21:12

Cel mai probabil compilatorul poate face niste optimizari. Nu stiu sigur, nu am mai programat de ceva vreme in C++.
dani.user e maestru la d-astea. Personal as folosi const& oricum, pentru expresivitatea codului. |
#81
Posted 20 September 2018 - 21:48

#82
Posted 20 September 2018 - 22:19

Ce înțelegi prin invalide? LastName este invalid dacă conține și 2-3 cifre(pe lângă litere)? Value objects sunt parte din domain model, deci in ele implementezi regulile de business relevante. Si regulile sintactice tot reguli de business sunt. Aici mostra de proiect la care lucreaza un coforumist: https://github.com/w...tree/master/src Clase ca GameStatus, MapCoordinate si Mark sunt value objects. |
|
#83
Posted 20 September 2018 - 22:30

Offtopic, m-am uitat peste GameStatus și mă duce cu gândul la State.
Tehnic vorbind, acea clasă reprezintă un state al jocului, însă ați ales sa o denumiți astfel datorită faptului că face parte din domain model?
De exemplu, da. La fel si un sir gol sau constituit din caractere neprintabile. Pattern matching se pliază aici? |
#85
Posted 21 September 2018 - 13:40

Am revenit cu un update în acest sens.
De asemenea, am adăugat un video în care evidențiez partea cu id-urile. Așa funcționează el momentan, fără să-i fi adăugat Repository-ul ca storage. https://streamable.com/t539t |
#86
Posted 21 September 2018 - 14:23

UX lasa de dorit, dar nu m-as apleca asupra lui acum.
Vezi ca ai litera Q (QString) in value objects. Efectiv nu ai voie cu #include <q...> in directorul src/phonebook/ - e foarte simplu. Si nu arunci exceptii in constructori. E foarte important, altfel cel mai important avantaj al VO s-a dus pe apa sambetei: VO iti protejeaza domeniul de valori invalide. Decat sa iti impingi QString-ul cu forta in domain model, mai bine implementezi operator std::string pentru value objects si lucrezi doar cu value objects. Orice ai alege, asta nu e ok: Contact(QString const& lastName, QString const& firstName, QString const& phoneNumber) noexcept; |
#87
Posted 21 September 2018 - 15:08

Efectiv nu ai voie cu #include <q...> in directorul src/phonebook/ - e foarte simplu.
Si nu arunci exceptii in constructori.
In constructorul value objects arunci o exceptie daca datele sunt invalide. |
|
#88
Posted 21 September 2018 - 15:11

Exceptie in constructor: https://github.com/w...rc/Mark.php#L28
Datorita exceptiei, nu poti construi VOs invalide. Si datorita faptului ca celelalte modele accepta exclusiv VO, nu poti infecta niciun alt model cu date invalide (sintactic). |
#89
Posted 21 September 2018 - 15:17

Excepția o arunc din metoda validate() care este apelată în constructor.
https://github.com/I...astName.cpp#L10 |
#90
Posted 21 September 2018 - 15:25

Cel putin o alta clasa in care m-am uitat nu arunci exceptie.
|
Anunturi
Bun venit pe Forumul Softpedia!
▶ 0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users