Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-ca-cd:laboratoare:programare-avansata-java [2026/01/11 23:05]
florian_luis.micu [Assertions vs Excepții]
poo-ca-cd:laboratoare:programare-avansata-java [2026/01/12 01:22] (current)
florian_luis.micu [[Optional] Software Development Methodologies]
Line 7: Line 7:
 =====Obiective===== =====Obiective=====
  
-=====Serializare și Deserializare=====+Scopul acestui laborator este introducerea studenților în concepte mai avansate care permit crearea framework-urilor și a aplicațiilor enterprise. 
 + 
 +Aspectele urmărite sunt: 
 +  * înțelegerea conceptelor de testare. 
 +  * utilizarea corectă a mecanismului de reflection. 
 +  * exersarea serializărilor și deserealizărilor. 
 +  * implementarea și utilizarea corectă a adnotărilor. 
 +  * exersarea folosirii aserților. 
 +  * familiarizarea cu dependențe populare cum ar fi JUnit, Mockito, Jackson. 
 + 
 +Aspectele **bonus** urmărite sunt: 
 +  * înțelegerea mecanismelor de logging. 
 +  * aprofundarea metodologiilor de dezvoltare software. 
 +  * Diferența dintre getClass() și instanceof. 
 +  * Organizarea memoriei pentru moștenire în Java. 
 + 
 +<note warning>​ 
 +  * În acest laborator există mai multe secțiuni marcate **[Optional]**. Aceste secțiuni cuprind informații **bonus** care vă pot fi prezentate în **timpul laboratorului** sau pe care le puteți aprofunda **în afara** acestuia, ele nefiind necesare pentru laboratoarele viitoare sau pentru teme. 
 +  * De asemenea, veți întâlni câteva secțiuni marcate **[Nice to know]**. Vă recomandăm ca acestea să aibă **prioritate** în parcurgerea secțiunilor de tip **[Optional]**,​ deoarece vă pot oferi informații bonus care să fie și foarte probabil utile pentru **teme** sau **laboratoare viitoare**. 
 +</​note>​ 
 + 
 +=====🔄 Serializare și Deserializare=====
  
 ====Ce este serializarea?​==== ====Ce este serializarea?​====
Line 174: Line 195:
 ===De ce este Jackson preferat în aplicațiile moderne?=== ===De ce este Jackson preferat în aplicațiile moderne?===
  
-De ce este Jackson preferat în aplicațiile moderne? 
   * JSON este lizibil și ușor de debugat,   * JSON este lizibil și ușor de debugat,
   * este interoperabil cu alte limbaje,   * este interoperabil cu alte limbaje,
Line 339: Line 359:
 </​code>​ </​code>​
  
-=====Adnotări în Java=====+=====🏷️ ​Adnotări în Java=====
  
 ====Ce sunt adnotările?​==== ====Ce sunt adnotările?​====
Line 594: Line 614:
  
  
-=====Reflection în Java=====+=====🪞 Reflection în Java=====
  
 ====Ce este Reflection?​==== ====Ce este Reflection?​====
Line 783: Line 803:
  
  
-=====Assertions=====+=====🔍 Assertions=====
  
 ====Ce sunt assertions?​==== ====Ce sunt assertions?​====
Line 844: Line 864:
  
  
-=====Unit Testing=====+=====🔬 Unit Testing=====
  
 ====Ce este Unit Testing?​==== ====Ce este Unit Testing?​====
Line 992: Line 1012:
 </​note>​ </​note>​
  
 +=====🧪 Integration Testing & Mocking=====
 +
 +====Ce este Integration Testing?​====
 +
 +**Integration testing** verifică dacă **mai multe componente ale aplicației funcționează corect împreună**,​ nu doar în izolare.
 +
 +Spre deosebire de unit testing:
 +  * nu testăm o metodă izolată
 +  * testăm colaborarea dintre clase, module sau layere
 +
 +Exemple:
 +  * service + repository
 +  * controller + service
 +  * service + client HTTP
 +
 +====Unit Tests vs Integration Tests====
 +
 +^ Unit Testing ​       ^ Integration Testing ​       ^
 +| testează o unitate ​ | testează colaborarea ​      |
 +| izolat ​             | dependențe reale           |
 +| foarte rapid        | mai lent                   |
 +| fără infrastructură | poate necesita DB / config |
 +
 +<note important>​ Integration testing **nu înseamnă** „testăm tot sistemul”. </​note>​
 +
 +====Niveluri de integrare====
 +
 +În practică există mai multe grade:
 +  * integrare **parțială** (mock pentru unele dependențe)
 +  * integrare **reală** (DB real, filesystem, config)
 +
 +Laboratoarele se concentrează de obicei pe **integrare parțială**,​ pentru control și viteză.
 +
 +====De ce avem nevoie de Mocking?​====
 +
 +Mocking permite **simularea comportamentului unei dependențe**,​ fără a o executa efectiv.
 +
 +Folosim mocking când:
 +  * dependența este lentă
 +  * dependența este externă
 +  * vrem să controlăm exact comportamentul
 +
 +====Mockito – framework de mocking====
 +
 +**Mockito** este standardul de facto în Java pentru mocking.
 +
 +Cu Mockito putem:
 +  * crea obiecte mock
 +  * defini comportamentul lor
 +  * verifica interacțiunile
 +
 +====Exemplu simplu de mocking====
 +
 +<code java>
 +UserRepository repo = mock(UserRepository.class);​
 +
 +when(repo.findById(1L))
 +    .thenReturn(new User("​Ana"​));​
 +</​code>​
 +
 +Ce se întâmplă:​
 +  * ''​repo''​ NU este implementare reală
 +  * metoda ''​findById''​ este simulată
 +  * nu există DB implicat
 +
 +====Integrare parțială cu Mockito====
 +
 +<code java>
 +class UserServiceTest {
 +
 +    UserRepository repo = mock(UserRepository.class);​
 +    UserService service = new UserService(repo);​
 +
 +    @Test
 +    void returnsUserName() {
 +        when(repo.findById(1L))
 +            .thenReturn(new User("​Ana"​));​
 +
 +        String name = service.getUserName(1L);​
 +
 +        assertEquals("​Ana",​ name);
 +    }
 +}
 +</​code>​
 +
 +Aici testăm:
 +  * logica din ''​UserService''​
 +  * integrarea cu repository-ul (simulat)
 +
 +====Verificarea interacțiunilor====
 +
 +Mockito permite verificarea apelurilor:
 +<code java>
 +verify(repo).findById(1L);​
 +</​code>​
 +
 +Acest lucru este util când:
 +  * ordinea apelurilor contează
 +  * vrem să verificăm efecte indirecte
 +
 +====Observații importante====
 +
 +  * Nu se face mock pentru **clasa testată**
 +  * Se fac mock doar pentru **dependințe**
 +  * Mock-urile nu trebuie suprafolosite
 +  * Testele cu prea multe mock-uri devin fragile
 +
 +====[Nice to know] Folosirea lui var în teste====
 +
 +În Java, ''​var''​ permite **inferarea tipului la compilare**,​ reducând zgomotul sintactic, fără a pierde siguranța tipurilor.
 +
 +
 +<note important>​ ''​var''​ **nu este tip dinamic**. Tipul este determinat **o singură dată**, la compilare. </​note>​
 +
 +===Exemplu cu Mockito + var===
 +
 +Fără ''​var'':​
 +<code java>
 +UserRepository repository = mock(UserRepository.class);​
 +UserService service = new UserService(repository);​
 +</​code>​
 +
 +Cu var:
 +<code java>
 +var repository = mock(UserRepository.class);​
 +var service = new UserService(repository);​
 +</​code>​
 +
 +Codul este:
 +  * mai scurt
 +  * la fel de sigur
 +  * mai lizibil în contextul testelor
 +
 +<note important>​
 +Deși ''​var''​ poate fi util în scrierea rapidă a codului, trebuie să avem grijă să nu îl folosim în următoarele situații:
 +  * câmpuri
 +  * parametri
 +  * API public
 +  * când tipul nu e clar din context
 +</​note>​
 +
 +=====[Nice to know] 🪵 Logging în Java =====
 +
 +==== Ce este logging-ul? ====
 +
 +Logging-ul reprezintă mecanismul prin care o aplicație înregistrează informații despre:
 +  * execuția codului
 +  * evenimente importante
 +  * erori sau situații neașteptate
 +
 +Spre deosebire de ''​System.out.println'',​ logging-ul:
 +  * poate fi configurat (nivel, format, destinație)
 +  * poate fi dezactivat fără a modifica codul
 +  * este standard în aplicații profesionale
 +
 +====De ce NU folosim System.out.println?​====
 +
 +Instrucțiunea ''​System.out.println'':​
 +  * nu are niveluri (info, warning, error)
 +  * nu poate fi filtrat pe baza nivelelor
 +  * nu este potrivit pentru producție
 +
 +====Logging standard în Java (java.util.logging)====
 +
 +Java oferă un mecanism de logging în JDK, fără biblioteci externe ''​java.util.logging''​.
 +
 +Exemplu minimal:
 +<code java>
 +import java.util.logging.Logger;​
 +
 +public class Example {
 +    private static final Logger logger =
 +        Logger.getLogger(Example.class.getName());​
 +
 +    void run() {
 +        logger.info("​Application started"​);​
 +    }
 +}
 +</​code>​
 +
 +Niveluri de logging (cele mai uzuale)
 +
 +  * ''​SEVERE''​ / ''​ERROR''​ – erori critice
 +  * ''​WARNING''​ – situații problematice
 +  * ''​INFO''​ – informații generale
 +  * ''​FINE''​ / ''​DEBUG''​ – detalii de execuție
 +
 +<note important>​ Logging-ul NU trebuie să schimbe comportamentul aplicației,​ **doar să-l observe**. </​note>​
 +
 +====Logging folosind Log4j====
 +
 +Pe lângă mecanismul de logging din JDK (java.util.logging),​ în practică este foarte des întâlnită biblioteca Apache Log4j.
 +
 +Log4j este:
 +  * o bibliotecă externă de logging (nu face parte din JDK)
 +  * mai flexibilă și mai configurabilă decât logging-ul standard din Java
 +  * folosită frecvent în aplicații enterprise și framework-uri
 +
 +Un exemplu de inițializare:​
 +<code java>
 +import org.apache.logging.log4j.LogManager;​
 +import org.apache.logging.log4j.Logger;​
 +
 +public class Example {
 +    private static final Logger logger =
 +        LogManager.getLogger(Example.class);​
 +
 +    void run() {
 +        logger.info("​Application started"​);​
 +    }
 +}
 +</​code>​
 +
 +<note warning> Log4j a fost implicat în vulnerabilitatea **Log4Shell (2021)**, una dintre cele mai grave din istoria Java. Acest lucru NU înseamnă că logging-ul este periculos, ci că **bibliotecile trebuie actualizate și verificate pentru vulnerabilități**. În prezent, există utilitare care fac acest lucru automat cum ar fi [[https://​snyk.io/​|Snyk]]</​note>​
 +
 +<note tip>
 +  * ''​java.util.logging''​ → suficient pentru laborator și aplicații simple
 +  * Log4j → standard de facto în aplicații mari
 +  * ''​System.out.println''​ → nu este logging
 +</​note>​
 +
 +=====[Optional] 🗺️ Software Development Methodologies=====
 +
 +În urma paradigmei OOP, au fost concepute mai multe metodologii care pot augmenta performanța sau anumite abilități ale unui proiect conform necesităților.
 +
 +De exemplu, **Data Oriented Design** (DOD) este o paradigmă care ajută programarea folosind obiecte prin folosirea **cache-ului**. Practic, clasele sunt refactorizate astfel încât să țină cont de mărimea cache-ului din procesor pentru a scădea drastic timpii de acces. Această paradigmă începe să fie destul de folosită în mediile în care viteza este importantă,​ cum ar fi programarea jocurilor video, drept urmare chiar și engine-ul Unity a fost rescris astfel încât să folosească DOD (găsiți articolul [[https://​unity.com/​dots|aici]].
 +
 +<note tip>
 +Vă recomandăm să parcurgeți secvențe din acest videoclip de la [[https://​www.youtube.com/​watch?​v=yy8jQgmhbAU|CppCon]].
 +</​note>​
 +
 +O altă metodologie utilă este **Test Driven Development** (TDD) în care accentul este pus pe dezvoltarea testelor înainte de a dezvolta codul propriu-zis. Practic, după etapa de ideație, putem trece la crearea testelor care vor defini comportamentul corect al programului nostru, apoi vom dezvolta codul necesar pentru a putea trece cu succes peste testele scrise de noi. Puteți citi mai multe despre această abordare [[https://​agilealliance.org/​glossary/​tdd/​|aici]].
 +
 +De asemenea, o altă metodologie folosită este **Domain Driven Design** (DDD) care este o abordare de proiectare software în care structura aplicației este ghidată de domeniul de business, iar logica esențială este modelată prin concepte clare (entități,​ valori, agregate) definite împreună cu experți din domeniu, folosind un limbaj comun (ubiquitous language) pentru a menține codul aliniat cu realitatea problemei. Această abordare este detaliată în articolul scris de Redis [[https://​redis.io/​glossary/​domain-driven-design-ddd/​|aici]].
 +=====Exerciții=====
 +
 +<note tip>
 +Pentru exercițiile de mai jos va trebui să vă creați propriile proiecte Maven. Vă recomandăm să luați dependențele necesare de pe [[https://​mvnrepository.com/​repos/​central|Maven Repository]],​ concret JUnit și Mockito.
 +
 +De asemenea, vă recomandăm să parcurgeți documentația Mockito și JUnit sau să folosiți ghiduri de pe site-uri de specialitate cum ar fi [[https://​www.baeldung.com/​mockito-series|Baeldung Mockito series]].
 +</​note>​
 +
 +<note important>​
 +Acest laborator nu va fi încărcat pe Devmind Code, deoarece va fi verificat manual de către laborantul vostru.
 +</​note>​
 +====Task 1 – Unit Testing cu coverage ≥ 80% (6p)====
 +
 +Se dă următoarea clasă de producție, care modelează un serviciu simplu de procesare a comenzilor. Codul conține:
 +  * ramificații (if)
 +  * excepții
 +  * assertions
 +  * logică dependentă de input
 +
 +<code java>
 +public class OrderService {
 +
 +    public double calculateTotal(double price, int quantity) {
 +        assert price >= 0 : "Price must be non-negative";​
 +        assert quantity > 0 : "​Quantity must be positive";​
 +
 +        return price * quantity;
 +    }
 +
 +    public double applyDiscount(double total, double discountPercent) {
 +        if (discountPercent < 0 || discountPercent > 50) {
 +            throw new IllegalArgumentException("​Invalid discount"​);​
 +        }
 +
 +        return total - (total * discountPercent / 100);
 +    }
 +
 +    public String categorizeOrder(double total) {
 +        if (total < 100) {
 +            return "​SMALL";​
 +        } else if (total < 500) {
 +            return "​MEDIUM";​
 +        } else {
 +            return "​LARGE";​
 +        }
 +    }
 +
 +    public boolean isFreeShipping(double total) {
 +        return total >= 200;
 +    }
 +}
 +</​code>​
 +
 +Scrieți teste unitare folosind JUnit 5 astfel încât:
 +  * coverage-ul clasei să fie ≥ 80%
 +  * toate ramurile importante să fie testate
 +  * testele să fie clare, independente și deterministe
 +
 +<note tip>
 +În industrie, testarea este importantă,​ iar o metrică consacrată în acest sens este ca 80% din cod să fie acoperit de teste. Pentru a verifica cât cod este acoperit de testele voastre puteți folosi [[https://​www.jetbrains.com/​help/​idea/​code-coverage.html|ghidul oficial IntelliJ]] sau să întrebați laborantul.
 +</​note>​
 +
 +<note important>​
 +Pentru a testa cât mai mult cod, trebuie să generați teste valide și invalide pentru codul dat, astfel încât să testați toate ramurile logice.
 +</​note>​
 +
 +====Task 2 - Integration Test + Mocking (4p)====
 +
 +Se dau următoarele clase:
 +<code java User.java>​
 +public class User {
 +    private final String name;
 +
 +    public User(String name) {
 +        this.name = name;
 +    }
 +
 +    public String getName() {
 +        return name;
 +    }
 +}
 +</​code>​
 +
 +<code java UserRepository.java>​
 +public interface UserRepository {
 +    User findById(long id);
 +}
 +</​code>​
 +
 +<code java UserService.java>​
 +public class UserService {
 +
 +    private final UserRepository repository;
 +
 +    public UserService(UserRepository repository) {
 +        this.repository = repository;
 +    }
 +
 +    public String getUserName(long id) {
 +        User user = repository.findById(id);​
 +        return user.getName();​
 +    }
 +}
 +</​code>​
  
 +  - Scrieți un test pentru UserService folosind Mockito.
 +  - Mock-uiți UserRepository astfel încât:
 +    * pentru id = 1, să returneze un User("​Ana"​)
 +  - Verificați că metoda getUserName(1) returnează "​Ana"​.
 +  ​
 +Puteți folosi ''​var''​ pentru:
 +  * repository
 +  * service
 +  * rezultatul final
  
 +<note tip>​Denumirea și scopul claselor de mai sus respectă un standard folosit de framework-ul Spring.</​note>​
  
 +===== Resurse și link-uri utile =====
 +  * [[https://​site.mockito.org/​ | Mockito]] ​
 +  * [[https://​www.atlassian.com/​continuous-delivery/​software-testing/​types-of-software-testing | Different types of software testing]]
 +  * [[https://​www.baeldung.com/​java-logging-intro | Introduction to Java logging - Baeldung]]
 +  * [[https://​softwareengineering.stackexchange.com/​questions/​123956/​why-should-i-use-reflection | Why should I use reflection and when? - StackOverflow]]
  
  
poo-ca-cd/laboratoare/programare-avansata-java.1768165541.txt.gz · Last modified: 2026/01/11 23:05 by florian_luis.micu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0