Sunteți pe pagina 1din 6

Programare orientată pe obiecte

Tema 1
Deadline: 11.11.2019, 23:59

Subiect
MiniGit - Sistem de control al versiunii codului.

Motivație
Ionel este student în anul 4 în ATM și se lamentează “că nu știe git”. Nu fi ca Ionel! Echipa POO-ATM
consideră că poți înțelege mai bine “git” dacă încerci să îl implementezi chiar tu.
Tema curentă încearcă acest lucru, provocându-vă să realizați propria versiune de “git”- “MiniGit”. Știm
însă că acest lucru nu este ușor, prin urmare vă venim în ajutor cu o serie de sugestii pentru implementare, la
care adăugăm, bineînțeles, și câteva cerințe, pentru a face provocarea “atractivă”.

The story
Git reprezintă un sistem de control al versiunii codului. Mai exact, când Ionel se apucă să adauge cod la
proiectul lui POO se întreabă dacă noul “feature” la care s-a gândit va funcționa așa cum se așteaptă. Pentru
a nu pierde versiunea actuală, care se întâmplă să fie funcțională, Ionel folosește ​git ca să creeze un ​commit​,
salvând astfel starea curentă a codului. Aceste ​commit​-uri alcătuiesc o structură de tip ​listă înlănțuită​. De
cele mai multe ori, sistemele de Git folosesc un ​repository local și un ​repository remote pentru a salva la
distanță proiectul lui Ionel, cu ajutorul comenzii ​push​. Astfel, Ionel poate lucra de pe altă mașină la
proiectul lui: un commit poate fi adus de pe remote cu ajutorul comenzii ​pull​. Noua funcționalitate atrage
alți contribuitori, care vor să lucreze la proiectul lui Ionel. Apare, deci noțiunea de ​branch​, iar lista
înlănțuită de commit-uri devine o structură arborescentă: mai multe commit-uri pot avea drept commit
precedent același commit. Problemele apar când echipa vrea să unească, prin comanda ​merge​, aceste
branch-uri, însă, cu puțină organizare, pot fi evitate ​conflictele​ de la o ramură la alta.

Sugestii de implementare
Pentru implementarea principalelor funcționalități oferite de “git”, vă propunem câteva sugestii. Acestea
sunt orientative, nu obligatorii :-) și vă încurajăm să veniți cu soluții diferite (și mai bune :-D). Sugestiile
le-am ordonat cronologic, pentru a vă crea o imagine de ansamblu mai bună a utilizării aplicației finale.
Așadar, să începem…
Ionel va putea folosi “MiniGit-ul” în directorul în care are fișierele/proiectul pe care dorește să le/îl
versioneze. Prin urmare, primul pas pe care Ionel va trebui să îl facă este să meargă în acel director și să
verifice existența fișierelor dorite a fi administrate de “MiniGit”.
Ca exemplu, noi am mers în directorul ​tema_poo,​ unde avem disponibile două fișiere: ​source1.cpp și
source1.h​.
Următorul pas pe care Ionel trebuie să îl facă este să lanseze “MiniGit” și să înceapă cu prima comandă,
MiniGit init​, care va instanția procesul de pregătire a directorului pentru versionare (vor fi create două
directoare, ​local și ​remote​, fiecare având un scop și conținut anume, detaliat în pașii următori). Efectul
comenzii se poate observa în imaginea de mai jos.

Ionel este pregătit să înceapă adăugarea fișierelor pe care dorește să le monitorizeze. Pentru a face acest
lucru, el va executa comanda ​MiniGit add <filename>​, prin care fișierul ales va fi marcat pentru includerea
în următorul commit.
În exemplul următor este prezentat rezultatul execuției comenzii ​MiniGit add source1.cpp​. Fișierul ​local.git
este creat și gestionat de un proces specific, prin care se realizează administrarea adăugării fișierelor pentru
nou commit și crearea acestuia.

Pentru adăugarea unui alt fișier, Ionel va executa aceeași comandă prezentată anterior. Exemplul următor
prezintă rezultatul execuției comenzii ​MiniGit add source1.h.​

În acest moment, Ionel a terminat de adăugat fișierele pe care vrea să le versioneze, astfel că este pregătit
pentru crearea primului său ​commit.​ Comanda folosită pentru această operațiune este ​MiniGit commit
<commit_name>​ și va putea fi folosită în acest format și pentru commit-uri viitoare.
Figura de mai jos prezintă rezultatul obținut în urma execuției comenzii ​MiniGit commit commit_1​.
Fiind sigur că fișierele sale sunt salvate, Ionel reia lucrul la tema de la POO și implementează funcționalități
noi, care duc la modificarea fișierelor din proiect. Înainte de a închide calculatorul, Ionel se decide să facă un
nou commit, pentru a fi sigur că nu își va pierde codul scris în ultimele ore. Astfel, el va relua pașii anteriori,
de adăugare a unui fișier pentru commit și va face un commit nou.
Rezultatele acestei secvențe de comenzi sunt redate în următoarele două imagini, astfel:
- Rezultatul execuției comenzii ​MiniGit add source1.cpp (în exemplul nostru, doar în fișierul
source1.cpp​ au fost introduse secțiuni noi de cod).

- Rezultatul execuției comenzii ​MiniGit commit commit_2.​


A doua zi, Ionel a auzit de la un coleg despre posibilitatea mutării commit-urilor într-o locație remote, având
astfel acces la o măsură suplimentară de protecție, în cazul ștergerii accidentale a fișierelor commit salvate
local. “MiniGit” simulează această funcționalitate prin intermediul directorului remote (cine știe...poate în
semestrul următor, la POO proiect, veți putea implementa această funcționalitate chiar pe o locație distinctă
din rețea ;-) ). Comanda prin care Ionel va copia commit-urile locale într-o locație remote este ​MiniGit push
origin.​
Rezultatul pe care noi l-am obținut este prezentat în figura următoare.

După o pauză de câteva zile, Ionel vrea să reia lucrul la tema POO, însă constată, cu stupoare, că ultimele
modificări făcute nu sunt bune, iar fișierele commit salvate local au fost șterse. Își aduce aminte însă că a
executat un ​push pe o locație remote, însă nu mai știe exact ce commit-uri are disponibile acolo. “MiniGit” îi
oferă posibilitatea de a afla commit-urile pe care le are salvate, prin intermediul comenzii ​MiniGit log
<remote_location>​, care îi va afișa denumirea tuturor fișierelor commit pe care le are salvate în locația
remote.
Fericit să vadă că are suficiente commit-uri salvate, Ionel vrea să refacă starea proiectului său dintr-un
anumit commit. Pentru acest lucru el execută comanda ​MiniGit pull <remote_location> <commit_name>​.
Această comandă îi va reface starea proiectului pornind de la commit-ul selectat. Ca exemplu, figura de mai
jos prezintă rezultatul execuției comenzii ​MiniGit pull D:\tema_poo\remote 0_1.commit​.
După o discuție cu profesorul coordonator, Ionel este pus într-o echipă cu un coleg pentru a continua
implementarea temei. Pentru a le ușura munca în echipă, “MiniGit” le pune la dispoziție posibilitatea creării
unor ​branch-uri,​ prin care pot realiza implementări pentru diferite module, urmând apoi să le unească într-o
singură versiune, după efectuarea a suficiente teste.
Modul în care branch-urile vor fi implementate este lăsat în seama voastră, fiind buni programatori și
prieteni ai lui Ionel. Ceea ce vă putem spune sunt comenzile necesare creării unui branch și mutarea
contextului proiectului pe acest nou branch.
● Comanda ​MiniGit branch <branch_name> creează un branch nou. Pentru a marca această
operațiune, vă sugerăm introducerea unei linii nou în header-ul fișierului ​local.git​, pentru a putea
monitoriza mai ușor fișierele adăugate pe fiecare branch.
● Comanda ​MiniGit checkout <branch_name> mută contextul curent de versionare a proiectului pe
branch-ul selectat. Prin urmare, orice modificare a unui fișier și adăugare pentru commit, vor fi
marcate pe acest branch și doar pe acesta.

Dacă veți considera că totul a fost simplu până în acest punct, vă propunem implementarea unei comenzi
suplimentare, anume ​MiniGit merge <branch_name_1> <branch_name_2>.​ Această comandă va uni două
branch-uri, ținând cont de fișierele modificate/introduse/șterse, pornind de la parametrul ​timestamp aferent
fiecărui fișier salvat într-un commit.

!”MiniGit” va avea, obligatoriu, un sistem de jurnalizare (log-are) a acțiunilor realizate de aplicație, cu


salvarea acestora într-un fișier text cu extensia .log.

Rezumat de cerințe și notare


Să se implementeze un utilitar din linia de comandă care să implementeze funcționalitățile descrise ale unui
sistem de gestiune a versiunilor:
MiniGit init
Inițializează fișierele și directoarele sistemului
MiniGit add <filename>
Pregătește fișierul pentru commit.
MiniGit commit <commit_name>
Salvează versiunea actuală sub formă de commit.
MiniGit push origin
Mută commit-urile de pe local pe remote.
-- a fost atinsă nota 6 --
MiniGit log <remote_location>
Afișează commit-urile salvate pe remote.
MiniGit pull <remote_location> <commit_name>
Aduce commit-ul ales de pe remote și generează fișierele din interiorul acestuia.
-- a fost atinsă nota 8 --
MiniGit branch <branch_name>
Creează un branch nou.
MiniGit checkout <branch_name>
Mută contextul versionării pe branch-ul selectat. Orice modificare aduse fișierelor monitorizate va fi
marcată doar pe acest branch, devenit branch-ul curent.
-- a fost atinsă nota 10 --
MiniGit merge <branch_name_1> <branch_name_2>
Realizează operația de “merge” între cele două branch-uri selectate.
-- a fost atinsă nota 12 --

Ce se urmărește?
- Aplicarea conceptelor prezentate în primele 5 laboratoare;
- Implementarea corectă a claselor și inițializarea adecvată a obiectelor;
- Identificarea necesității folosirii pattern-ului Singleton și implementarea corectă a acestuia;
- Gruparea eficientă a elementelor în cadrul claselor;
- Aplicarea principiului încapsulării;
- Aplicarea principiului polimorfismului prin funcții supraîncărcate;
- Modularizarea codului sursă - lucrați ca și cum altcineva ar urma să folosească sursele voastre;
- Utilizarea elementelor C++: parametrii impliciți, referințe, membrii și metode statice și constante,
etc.
- Crearea propriilor implementări a elementelor folosite adesea (de ex. vectori, liste, etc.). Este
permisă folosirea tipului de date ​string​;
- NU se recomandă utilizarea bibliotecii STL sau a altor framework-uri C++. Rolul temei este acela de
a vă familiariza cu modul de gândire în programarea orientată pe obiecte și nu de a deveni un simplu
beneficiar al implementărilor altora.
- În corectarea temei o importanță deosebită o are modelarea problemei propuse.