Topic outline

  • Programarea Orientata pe Obiecte

    Programarea Orientata pe Obiecte (POO) – sau OOP – Object Oriented Programming – este o paradigma de programare care foloseste concepte abstracte (sub forma de clase si obiecte) pentru a crea modele bazate pe elemente din lumea reala. 

    Folosirea POO permite realizarea de sisteme informatice de dimensiuni mărite, cu timpi de dezvoltare, testare și mentenanță reduși față de paradigmele anterioare. Totuși, pentru a crea un sistem funcțional este necesară înțelegerea corectă a conceptelor care stau în spatele POO. Cu aceste concepte se ocupă cursul și laboratoarele de POO.

    La orele de POO ne vom focusa pe crearea lumei reale si interactiunei sale, ca objective sunt setate : 

    • Obligatoriu
    1. Studiul limbajului de programare JAVA
    2. Principiile OOP
    3. Principiile SOLID
    4. Pregatirea pentu a trece cu success un interviu

    • Suplimentar
    1. Studiul la GIT
    2. Lucru cu bazele de date
    3. Interactiunea Backend - Frontend
    4. HTTP
    5. CRUD

    Ore contact direct:

    • ore de curs: 45 ore
    • lucrări de laborator: 30 ore


  • Studiul limbajului de programare JAVA

    Programarea Orientată pe Obiecte se poate aplică în orice limbaj care permite acest lucru. Cele mai cunoscute asemenea limbaje astăzi sunt C++, Java, C#, chiar și PHP. În acest semestru vom ilustra conceptele de POO folosind limbajul Java.

    Java a pornit că o platformă de programare pentru sisteme embedded. Țelurile principale ale proiectului erau:

    • independența de sistem
    • utilizarea POO.

    Astăzi, Java este folosită mai mult că o platformă pentru Internet și a atins o utilizare impresionantă.

    Java este un mediu (platformă) de programare care constă în:

    • un limbaj de programare (Java) care descrie programatorului ce instrucțiuni sunt valide și ce face fiecare
    • un compilator (javac.exe (Windows) / javac (Linux)) care transformă fișierul sursă într-un limbaj intermediar numit bytecode
    • mașină virtualăJava Virtual Machine (JVM), care permite transformarea codului intermediar în instrucțiuni executabile pe procesorul curent.
    • bibliotecă puternică ce răspunde foarte bine nevoilor apărute în practică (class library)

    La cadrul cursului vom studia:

    1. Scurt istoric despre JAVA
    2. JDK, JRE, JVM
    3. Garbage collection
    4. Variable
    5. Operator
    6. Comment
    7. Condition
    8. Method
    9. Array
    10. Loop
    11. Casting
    12. Class
    13. Constructor


    Toate topicurile care le vom discuta vor avea si exemple care le vom discuta in cadrul lectiilor. Pentru aceasta vom utiliza proiectul dat https://github.com/vadimeladii/internship.

    Mai multe resurse:



    • Principiile OOP

      OOP sau Object Oriented Programming care este o paradigma des intalnita in programare. Foarte multe limbaje de programare populare suporta OOP. Printre ele as aminti Java, C++, C#, Python, PHP, JavaScript, Ruby, Perl, Objective-C, sau Swift. Aceste limbaje care suporta OOP au la baza cateva concepte precum Clasele care sunt niste templaturi si Obiectele care sunt instante ale acestor clase. De exemplu putem sa avem o Clasa numita Persoana si pe baza ei sa creem mai multe Obiecte care vor fi practic niste persoane, adica Obiectul Radu, Mihai sau Cristina.

      OOP se bazeaza pe 4 mari principii. Daca intelegem aceste principii ne va fi usor sa intelegem si aceasta paradigma si modul in care putem implementa viitoarele proiecte. Hai sa le luam pe rand.

      1. Abstractizarea este procesul prin care “ascundem” anumite functionalitati pe care nu e nevoie sa le stii. De exemplu, atunci cand lucrezi intr-o echipa de programatori ai putea primi un task in care e nevoie sa creezi functionalitatea de salvare in baza de date. Ceilalti colegi vor folosi functionalitatea ta de foarte multe ori cand vor salva lucruri in baza de date. Ei bine, ei nu trebuie sa stie exact cum salvezi tu acele date, cum ai scris codul si ce se intampla mai exact in functionalitatea ta. Ei pur si simplu vor folosi functionalitatea ta trimitand datele in baza de date cu un efort minim. In acest mod, codul aplicatiei devine oarecum modular, adica format din bucatele de sine statatoare care fac anumite lucruri bine definite.
      2. Incapsulare este procesul prin care tinem datele si functiile separate de exterior. Daca luam tot exemplul precendent in care tu faci functionalitatea de adaugare in baza de date, e posibil ca acolo sa ai niste variabile in care sa tii username-ul si parola de conectare la baza de date. Ei bine, nu ai vrea ca o alta functionalitatea sa poata modifica variabila username sau din gresala ea sa fie suprascrisa de un username folosit in zona de creare useri. Prin incapsulare creem o capsula care delimiteaza interiorul de exterior.
      3. Mostenirea sau Inheritance da voie unor clase sa preia proprietati din alte clase. Un exemplu bun pentru a explica mostenirea este cazul unei aplicatii prin care vindem masini. Aceste masini au in general aceleasi proprietati cu unele mici diferente. Toate vor avea un anumit tip de combustibil, capacitate cilindrica a motorului sau pret. Diferenta vine atunci cand ne intereseaza numarul de locuri in cazul unui autoturism si masa maxima de transport in cazul unui camion. In codul nostru, vom avea nevoie de 2 clase si anume Car si Truck care au destul de multe proprietati in comun. Ca sa nu duplicam proprietatile acestea putea sa creem o clasa principala numita Vehicle care va avea proprietatile comune si apoi clasele Car si Truck care vor mostenii Vehicle si vor avea in plus proprietatile specifice.
      4. Polimorfism este procesul prin care putem sa creem mai multe copii ale aceleiasi metode care poate sa primeasca inputuri diferite. Ca exemplu practic putem sa luam aici din nou un site de vanzari auto. Am stabilit mai inainte ca avem nevoie de o clasa Vehicle si in ea vrem sa creem o metoda care sa ne aduca toate informatiile unei masini pe baza numarul de inmatriculare. In acelasi timp vrem sa putem face acest lucru si pe baza seriei de sasiu. Ei bine aceste 2 date sunt diferite ca format si lungime asa ca avem nevoie de 2 metode, cu acelasi nume care primesc inputuri diferite dar afiseaza acelasi lucru.

      • Principiile SOLID

        Principiile de design software reprezintă un set de recomandări care ne ajută în a evita conceperea greșită a programului. Există trei elemente care trebuie evitate atunci când se concepe arhitectura unui produs:

        • rigiditate - dacă un sistem este închis, este greu de schimbat
        • imobilitate - reutilizarea unui modul este imposibilă atunci când există o interdependență între acesta și restul modulelor
        • fragilitate - o schimbare poate aduce prăbușirea întregului sistem

        De aceea atunci când se concepe/implementează un produs acesta trebuie să respecte cele 5 principii 

        Single responsability 

        • Orice modul sau clasă trebuie să încapsuleze o singură funcționalitate. 
        • O clasă sau funcție, nu ar trebui să rezolve sau sa trateze mai mult decât un singur scop deoarece aceasta ar introduce cuplarea între cele două funcționalități. 

        Open Close 

        • Acest principiu exprimă faptul că o clasă sau o funcție, trebuie să fie deschisă pentru extensie dar închisă pentru modificare.
        • De exemplu, dacă avem o bibliotecă ce conține un set de clase ce trebuie extinse ar fi mai corect dacă am avea inițial un set de clase abstracte. Astfel în loc să modificăm clasele concrete din cadrul bibliotecii, putem extinde clasele abstracte. 
        • Conform prof. Bertrand Meyer acest principiu se rezumă la 2 reguli: 

        1. Un modul se declara open dacă acesta se poate extinde. De exemplu, se pot adăuga membrii noi unei clase, prin moștenire. 
        2. Un modul se declară close dacă poate fi utilizat de alte module. Aceasta înseamnă că a fost clar definit, iar informația esențială este declarată private. 

        Liskov substitution 

        • Acest principiu spune că, într-un program dacă S este subtip al lui T, atunci obiectele de tip T pot fi înlocuite cu obiecte de tip S, fără modificarea funcționalităților esențiale. 
        • Acest principiu impune unele condiții în scrierea metodelor: 
        • Contravarianța argumentelor metodelor unui subtip. Aceasta înseamnă impunerea unei relații inverse de ordine între părinte și copil 
        • Covarianța tipurilor pe care le returnează un subtip 
        • Subtipurile nu aruncă excepții. Excepția de la regulă este atunci când acele excepții sunt subtipuri ale celor aruncate de metodele tipului părinte 
        • Altfel spus noile clase extinse din părinte trebuie să fie capabile înlocuiască clasa de bază în toate funcțiile sale fără a fi nevoie să aducem modificări nicăieri. 

        Interface segregation 

        • Acest principiu expune ideea că niciun client nu are voie să fie forțat să depindă de metodele pe care nu le folosește 
        • Aceasta se realizează prin ”spargerea” interfețelor în module mai mici pe care clasele au opțiunea de a le implementa sau nu. 
        • Acest mod va ajuta și la ideea de decuplarea funcționalităților atunci când se dorește re-factorizarea produsului. 

        Dependency inversion 

        • Acest principiu se referă la o anumită formă de a decupla module software. 
        • Modulele de nivel înalt nu trebuie să depindă de modulele de nivel jos. 
        • Ambele module trebuie să depindă de abstractizări. 
        • Abstractizările nu trebuie să depindă de detalii ci detaliile trebuie să depindă de abstract.

        • Studiul la GIT

          In aceasta topic vom vorbi despre cum iti poti salva si accesa codul in orice moment.

          Git sau GitHub este din ce in ce mai utilizat si cerut de toti angajatorii, fiind un software care te ajuta la versionarea codului tau. De exemplu, daca vrei sa construiesti pe baza a ceea ce ai lucrat pana acum sau sa aduci si alte persoane care sa contribuie la munca ta, nu poti tine codul pe calculatorul tau pentru ca va deveni dificil ca si altii sa acceseze si sa lucreze cu ceea ce tu ai facut pana la momentul respectiv.

          Creatorul Linux, pe numele lui Linus Torvalds, este cel care s-a gandit la o metoda de versionare a codului, in momentul in care a considerat ca este nevoie ca mai multi programatori sa lucreze la versiunea sa de Linux.

          Prin folosirea Git, altii vor putea adauga si-si pune amprenta pe codul deja creat de tine. Iti prezint in video cateva exemple practice si iti prezint in detaliu posibiltatile ce Git ti le ofera. De asemena, voi vorbi despre Repository si cat de util acesta iti poate fi.

          Multi programatori folosesc GitHub pentru a-si stoca ceea ce au codat si a-si crea un portofoliu pe care angajatorii il pot oricand vizualiza. Este extrem de important sa ai cont pe GitHub daca iti doresti o cariera in IT. Sa nu mai vorbesc ca poti colabora cu alti programatori ce vor aduce imbunatatiri codului tau. Pe langa GitHub, te mai poti folosi de GitLab si Atlantis, care fac exact aceleasi lucruri dar au doar cateva mici diferente de design.


          Mai multe resurse :

          • Lucru cu bazele de date

            Introducere în Bazele de Date

            Bazele de date sunt colecții organizate de date care sunt ușor accesibile, gestionate și actualizate. Ele sunt esențiale pentru gestionarea eficientă a informațiilor în diverse aplicații software.

            Tipuri de Baze de Date

                1. Baze de Date Relaționale (RDBMS): Folosesc tabele pentru a reprezenta datele și relațiile dintre ele. Exemple: MySQL, PostgreSQL, Oracle Database.
                2. Baze de Date NoSQL: Folosesc structuri de date diverse (documente, grafuri, coloane, chei-valori) pentru a gestiona date nestructurate sau semi-structurate. Exemple:            MongoDB, Cassandra, Redis.
                3. Baze de Date Orientate pe Obiecte (OODBMS): Integrează concepte de programare orientată pe obiecte cu capabilitățile unui sistem de gestionare a bazelor de date.              Exemple: db4o, ObjectDB.

            Limbaje de Interogare

                1. SQL (Structured Query Language): Limbaj standard pentru gestionarea și manipularea bazelor de date relaționale.
                 Comenzi de bază:
                     - SELECT: Extrage date dintr-o bază de date.
                    - INSERT: Adaugă noi înregistrări într-o tabelă.
                    - UPDATE: Actualizează date existente într-o tabelă.
                    - DELETE: Șterge date dintr-o tabelă.
                Exemplu:
                    ```sql
                    SELECT * FROM studenti WHERE an = 2;
                    INSERT INTO studenti (nume, prenume, an) VALUES ('Popescu', 'Ion', 2);
                    ```

                2. MongoDB Query Language (MQL): Un limbaj specific pentru interogarea bazelor de date MongoDB.
                Exemplu:
                    ```javascript
                    db.studenti.find({ an: 2 });
                    db.studenti.insert({ nume: "Popescu", prenume: "Ion", an: 2 });
                    ```

            Normalizarea Bazelor de Date

            Normalizarea este procesul de organizare a datelor într-o bază de date pentru a reduce redundanța și a îmbunătăți integritatea datelor. Include mai multe forme normale (1NF, 2NF, 3NF, BCNF, etc.).

            Indexare

            Indexarea este o tehnică folosită pentru a îmbunătăți viteza de accesare a datelor dintr-o bază de date. Un index este similar cu un indice dintr-o carte și permite găsirea rapidă a înregistrărilor într-o tabelă.

            Constrângeri și Integritate

            Constrângerile sunt reguli aplicate pe coloanele tabelelor pentru a asigura corectitudinea și integritatea datelor. Exemple:
                - PRIMARY KEY: Unic identificator pentru fiecare rând dintr-o tabelă.
                - FOREIGN KEY: Asigură relația dintre două tabele.
                - UNIQUE: Asigură unicitatea valorilor într-o coloană.

            Backup și Recuperare

            Este esențial să aveți strategii de backup și recuperare pentru a proteja datele împotriva pierderii. Acestea includ backup-uri periodice și testarea procedurilor de restaurare.

            Exemple de Proiecte Practice

                1. Sistem de Gestiune a Bibliotecii: Crearea unei baze de date pentru gestionarea cărților, utilizatorilor și împrumuturilor.
                2. Sistem de Management al Studenților: O bază de date care să gestioneze informațiile despre studenți, cursuri, note și profesori.
                3. Sistem de E-Commerce: Implementarea unei baze de date pentru gestionarea produselor, comenzilor, clienților și plăților.

            Resurse Suplimentare

            Cărți:
                - "Database System Concepts" de Abraham Silberschatz, Henry F. Korth, S. Sudarshan
                - "SQL for Dummies" de Allen G. Taylor

            Cursuri Online:
                - Coursera: Databases and SQL for Data Science (https://www.coursera.org/learn/sql-data-science)
                - Udemy: The Complete SQL Bootcamp (https://www.udemy.com/course/the-complete-sql-bootcamp/)

            • Interactiunea Backend - Frontend

              Interacțiunea Backend-Frontend

              Introducere în Interacțiunea Backend-Frontend

              Interacțiunea între backend și frontend este crucială pentru dezvoltarea aplicațiilor web. Backend-ul gestionează datele și logica aplicației, în timp ce frontend-ul se ocupă de interfața cu utilizatorul.

              Componentele Backend-ului

              • Server: Găzduiește aplicația web.
                • Exemple: Apache, Nginx.
              • Aplicația: Logica aplicației, scrisă în limbaje precum Node.js, Python, Java.
              • Baza de Date: Stochează datele aplicației.
                • Exemple: MySQL, PostgreSQL, MongoDB.

              Componentele Frontend-ului

              • HTML: Structura paginilor web.
              • CSS: Stilizarea paginilor web.
              • JavaScript: Interactivitatea paginilor web.
              • Framework-uri Frontend:
                • Exemple: React, Angular, Vue.js.

              Cum Interacționează Backend-ul cu Frontend-ul

              1. Cererile HTTP: Frontend-ul trimite cereri HTTP (GET, POST) către backend pentru a obține sau trimite date.
                fetch('https://api.exemplu.com/data')
                  .then(response => response.json())
                  .then(data => console.log(data));
              2. API-uri: Backend-ul expune API-uri pe care frontend-ul le folosește.
                GET /api/studenti
                POST /api/studenti
              3. Autentificare: Backend-ul gestionează autentificarea utilizatorilor.
                const token = localStorage.getItem('token');
                fetch('https://api.exemplu.com/protected', {
                  headers: {
                    'Authorization': `Bearer ${token}`
                  }
                });
              4. WebSockets: Permite comunicarea în timp real între client și server.
                const socket = io('https://api.exemplu.com');
                socket.on('message', data => {
                  console.log(data);
                });

              Exemple de Proiecte Practice

              • Aplicație To-Do List: Frontend-ul permite adăugarea și gestionarea sarcinilor, iar backend-ul stochează sarcinile.
              • Aplicație de Social Media: Frontend-ul afișează postări și comentarii, iar backend-ul gestionează datele utilizatorilor.
              • Aplicație de E-Commerce: Frontend-ul afișează produsele și coșul de cumpărături, iar backend-ul gestionează stocurile și comenzile.

              Resurse Suplimentare

              • HTTP

                HTTP

                Ce este HTTP?

                HTTP (HyperText Transfer Protocol) este un protocol de comunicație utilizat pentru transferul de date pe web. Este fundamentul oricărei schimbări de date între client (browser) și server.

                Cum Funcționează HTTP?

                HTTP funcționează pe baza unui model cerere-răspuns:

                • Un client (de obicei un browser) trimite o cerere HTTP către un server.
                • Serverul procesează cererea și trimite un răspuns HTTP înapoi la client.

                Metode HTTP

                HTTP definește mai multe metode de cerere diferite care indică acțiunea pe care clientul dorește să o efectueze. Cele mai comune metode sunt:

                • GET: Solicită resurse de la server fără a modifica datele.
                • POST: Trimite date către server pentru a crea sau actualiza resurse.
                • PUT: Actualizează sau creează o resursă specificată.
                • DELETE: Șterge resursa specificată.

                Coduri de Răspuns HTTP

                Când un server răspunde la o cerere HTTP, acesta trimite un cod de stare HTTP care indică rezultatul cererii:

                • 200 OK: Cererea a fost realizată cu succes.
                • 404 Not Found: Resursa solicitată nu a fost găsită pe server.
                • 500 Internal Server Error: Serverul a întâmpinat o eroare internă.

                Header-ele HTTP

                Header-ele HTTP furnizează informații suplimentare despre cerere sau răspuns. Exemple de header-e includ:

                • Content-Type: Specifică tipul de media al resursei.
                • Authorization: Furnizează credențiale pentru autentificare.
                • Cache-Control: Controlul cache-ului pentru cerere/răspuns.

                HTTPS

                HTTPS (HyperText Transfer Protocol Secure) este versiunea securizată a HTTP. Utilizează criptarea TLS/SSL pentru a proteja datele transferate între client și server.

                Exemplu Simplu de Cerere HTTP

                GET /index.html HTTP/1.1
                Host: www.exemplu.com

                Resurse Suplimentare