From e4b4f9bfe1a4e9091686e2c13e253e7a1d32f473 Mon Sep 17 00:00:00 2001 From: Livio Francisconi <90481242+Livio74@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:12:23 +0100 Subject: [PATCH 1/9] fix: utilizzo di .gitattribute per utilizzare sempre newline unix like , possibile soluzione per issue #179 (#181) --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..07764a78 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text eol=lf \ No newline at end of file From 9da6182ee794e63ebb40ed14f325aad13b229e51 Mon Sep 17 00:00:00 2001 From: Michael Di Prisco Date: Sat, 23 Dec 2023 13:42:43 +0100 Subject: [PATCH 2/9] Proposta prima bozza capitolo testing (#145) Co-authored-by: Emilio Junior Francischetti <67055839+frnmjn@users.noreply.github.com> Co-authored-by: Nicola Erario Co-authored-by: Simone Gizzi Co-authored-by: Corrado Petrelli Co-authored-by: Angelo Cassano Co-authored-by: Simone Gentili Co-authored-by: sistella <56387955+sistella@users.noreply.github.com> Co-authored-by: Livio Francisconi <90481242+Livio74@users.noreply.github.com> --- docs/it/testing.md | 172 +++++++++++++++++++++++++++++++++++ docs/it/testing/piramide.png | Bin 0 -> 4532 bytes 2 files changed, 172 insertions(+) create mode 100644 docs/it/testing.md create mode 100644 docs/it/testing/piramide.png diff --git a/docs/it/testing.md b/docs/it/testing.md new file mode 100644 index 00000000..1642c501 --- /dev/null +++ b/docs/it/testing.md @@ -0,0 +1,172 @@ +# Testing + +Il testing è una parte fondamentale di ogni progetto software. In questo capitolo vedremo come testare il nostro codice in modo efficace. + +## Piramide del testing + +Esistono diversi tipi di test, ognuno con un suo scopo ben preciso. + +Si fa spesso riferimento alla piramide del testing, che rappresenta la proporzione tra di essi: +Piramide del testing + +Nel resto del capitolo li vedremo nel dettaglio. + +### Unit test + +Il test unitario è un processo di sviluppo software in cui le parti testabili più piccole di un'applicazione, denominate unità, vengono esaminate individualmente per verificarne il corretto funzionamento. Chi sviluppa, o chi si occupa del controllo qualità del software, completa i test unitari durante il processo di sviluppo. Per unità solitamente si intende una funzione o una piccola serie di funzioni i cui comportamenti sono strettamente legati. + +Il punto principale è la presenza di un contesto isolato con un obiettivo. + +L'unità che ci si appresta a testare non dovrebbe avere _dipendenze_, ossia richiamare codice di altre unità. Quando ciò accade, il codice richiamato (la dipendenza) dovrebbe essere _messa sotto mock_, cioè essere sostituito, nel contesto dello unit test, da una funzione che ne fa le veci. Questa funzione, denominata appunto **mock**, ci permette di simulare tutti i comportamenti che potrebbe avere la dipendenza senza dipendere direttamente da essa. + +Parliamo anche del concetto di _coverage_: Solitamente gli unit test permettono di raggiungere alti livelli di code coverage proprio per via della loro granularità. Per Coverage si intende infatti la percentuale di righe di codice testate sul totale. + +Solitamente i problemi rilevabili negli unit test sono più facili da correggere perché riguardano piccole porzioni di codice e molti test sono riutilizzabili anche in altri progetti se si usa codice condiviso. + +D'altro canto, se i test sono scritti male o non forniscono una buona coverage, danno falsa sicurezza e non prevengono i bug, e il (tanto) tempo impiegato a scriverli risulta inutile. + +### Integration test + +Il test di integrazione è una tecnica di test del software che ha come obiettivo quello di testare più componenti o moduli di un sistema software insieme. Ha lo scopo di verificare che i diversi componenti, quando combinati, funzionino correttamente e producano i risultati attesi. + +Concetti principali: + +- **Scope**: Anche qui parliamo di contesto e obiettivi specifici. +- **Stubs**: Sostituti di moduli e dipendenze necessari al funzionamento dei test. +- **Spettro più ampio**: A differenza dello unit test che verifica un modulo / una funzione / un contesto specifico e ridotto, l’integration testing integra più moduli e ne testa le interdipendenze e la comunicazione. + +Tipologie di test: + +- **Big-bang**: Si creano decine, centinaia, migliaia di test in base alla dimensione della codebase. Si testa tutto, tutto assieme. Solitamente il tutto viene fatto in un singolo integration test, o in pochissimi. Funziona per codebase ridotte. +- **Top-down testing**: Approccio incrementale, si parte dai moduli ad altissimo livello (Controller nel caso di un MVC) e si scende al livello più basso (Se si utilizzano i fat model si arriva anche fino a lì). Funziona per codebase grosse, iniziare è più complesso ma ha più impatto, pian piano diventa sempre più facile perché i livelli superiori sono già stati testati. +- **Bottom-up testing**: Approccio incrementale al contrario. Si parte da sotto e si va in alto. Anche qui parliamo di grosse codebase, iniziare è più facile ma ha meno impatto, proseguendo anche qui diventa sempre più facile perché l’impalcatura sotto funziona. +- **Sandwich** o **Hybrid Testing**: Combinazione dei due approcci sopra basati su un planning di priorità. + +Quando si lavora in team, più o meno grandi, non sempre ci si può assicurare che quanto sviluppato da una parte del team comunichi correttamente con quanto sviluppato da un’altra parte del team: gli Integration test sono fondamentali in questi contesti. Inoltre, se è facile individuare e correggere il comportamento di una specifica funzione (tramite unit test o tramite semplice attenzione quando si sviluppa), più difficile è notare eventuali differenze nel modo in cui i componenti di un’applicazione interagiscono tra di loro. I test di integrazione sono OTTIMI per garantire questa sicurezza. +Infine, l’integrazione tra componenti non è solo da intendersi come "corretta comunicazione e scambio di informazioni tra le parti" ma anche "corretta gestione degli errori". In definitiva, se due o più componenti funzionano assieme e i test sono stati scritti correttamente, abbiamo quasi l'assoluta certezza del loro funzionamento combinato. + +D'altro canto è complesso realizzare dei test di integrazione e mantenerli nel tempo per via dell’evoluzione naturale del software su cui si lavora. + +Rispetto agli unit test, infatti, è più complicato trovare gli errori essendo più ad ampio spettro. + +Molto complesso individuare tutte le integrazioni che ha senso testare. La coverage al 100% è infatti inverosimile in progetti grossi. +Spesso realizzare questi test è più complesso perché bisogna prima avere idea della codebase sottostante, a prescindere che si lavori in TDD (Test Driven Development - vedi paragrafo successivo) o meno. + +### End-to-end test + +Il test end-to-end (E2E) è una metodologia di test del software che si concentra sul test dell'intero sistema software dall'inizio alla fine, simulando scenari del mondo reale e interazioni dell'utente. Ha lo scopo di garantire che il sistema funzioni correttamente nel suo insieme e soddisfi i requisiti aziendali desiderati. A differenza degli altri tipi di test, fin ora trattati, qui il test interagisce con l'applicativo **solo** attraverso le interfacce più esterne (Browser o Api). + +E qui sta il punto. I requisiti sono essenzialmente aziendali e non tecnici. + +Nei test E2E, l'intera applicazione o sistema viene testato in un modo che imiti il modo in cui verrebbe utilizzato dagli utenti finali. Implica la simulazione delle interazioni dell'utente, l'inserimento dei dati e la convalida degli output previsti su più componenti, moduli e livelli del sistema. + +Anche qui parliamo di contesto e obiettivi, ma chiaramente non sono più “specifici” di per sé perché, ad esempio, testare “specificatamente” un flusso di pagamento coinvolge centinaia di parti. Inoltre, vista la complessità rilevata nel realizzare questi test, solitamente si usano strumenti che perlomeno automatizzino alcune parti del processo, come un live recording via estensione del browser. + +A differenza degli altri tipi di test, qui possiamo verificare se l’esigenza non funzionale, e quindi di business, sia rispecchiata nel comportamento della piattaforma. + +Infine, a differenza degli altri tipi di test trattati, qui vediamo all’atto pratico come i dati agiscono a 360 gradi. + +Ricreando scenari realistici, abbiamo modo di avere una sicurezza “definitiva” (tra molte virgolette) del comportamento della piattaforma. + +D'altro canto, è difficile prevedere e analizzare quante farne e cosa testare. Inoltre il test è più lungo da scrivere perché mentre per un integration test basta cambiare un flag per ottenere un flusso diverso, un test e2e deve probabilmente essere riscritto perché ha flussi differenti per giungere alla stessa conclusione. + +## Tipologie di test + +Esistono diverse tipologie di test, ognuna con un suo scopo ben preciso. Vediamole brevemente: + +- **Functional testing**: Il test funzionale è un tipo di test in cui il target sono le specifiche funzionali. Il sistema viene infatti testato rispetto ai requisiti funzionali, garantendo che questi siano adeguatamente soddisfatti dall'applicazione. +- **Performance testing**: Il test di performance è un tipo di test in cui il target è la performance del sistema. Il sistema viene infatti testato rispetto ai requisiti di performance, garantendo che questi siano adeguatamente soddisfatti dall'applicazione. +- **Usability testing**: Il test di usabilità è un tipo di test in cui il target è l'usabilità del sistema. Il sistema viene infatti testato rispetto ai requisiti di usabilità, garantendo che questi siano adeguatamente soddisfatti dall'applicazione. +- **Security testing**: Il test di sicurezza è un tipo di test in cui il target è la sicurezza del sistema. Il sistema viene infatti testato rispetto ai requisiti di sicurezza, garantendo che questi siano adeguatamente soddisfatti dall'applicazione. +- **Regression testing**: Il test di regressione è un tipo di test in cui il target è la regressione del sistema. Il sistema viene infatti testato rispetto ai requisiti di regressione, garantendo che questi siano adeguatamente soddisfatti dall'applicazione. + +Esistono molte altre tipologie di test, come _compatibility testing_, _acceptance testing_, _exploratory testing_, _golden testing_, _contract testing_, ma queste sono le più comuni. + +## Tecniche di test + +Esistono tre tecniche di test, ognuna con un suo scopo ben preciso. Vediamole brevemente: + +- **Black-box testing**: Il test _black-box_ è una tecnica di test in cui il tester non ha conoscenza dell'implementazione del sistema. +- **White-box testing**: Il test _white-box_ è una tecnica di test in cui il tester ha conoscenza dell'implementazione del sistema. +- **Grey-box testing**: Il test _grey-box_ è una tecnica di test in cui il tester ha conoscenza parziale dell'implementazione del sistema. + +Di solito queste tre tecniche vengono utilizzate per individuare eventuali falle nel sistema. Solitamente il _Black-box testing_ è la tecnica più utilizzata, in quanto permette di individuare falle che non sono state individuate durante lo sviluppo e non richiede una conoscenza pregressa del sistema. + +## Metodologie di testing + +### Manual testing + +Il manual testing è una metodologia in cui i test vengono eseguiti manualmente dalla figura del tester. Questo approccio ha diversi svantaggi e solitamente viene utilizzato solo per testare le funzionalità più critiche del sistema quando non è possibile automatizzare i test. Questa metodologia viene chiamata anche _explorative testing_, tramite la quale si prova a rompere l'applicazione creando scenari difficilmente automatizzabili e scrivendo di conseguenza i test. + +### Automated testing + +L'automated testing è una metodologia in cui i test vengono eseguiti automaticamente da un software. Questo approccio ha diversi vantaggi: **Ripetibilità**, **Riduzione dei costi**, **Riduzione dei tempi di sviluppo**. + +### Continuous testing + +Il continuous testing è una metodologia in cui i test vengono eseguiti automaticamente ad ogni commit o ad ogni modifica del codice sorgente. + +Solitamente viene utilizzato in congiunzione con il concetto di _continuous integration_, ovvero una metodologia di sviluppo software in cui i membri di un team integrano il proprio lavoro frequentemente, generalmente ogni giorno o più volte al giorno. Ogni integrazione viene verificata da un'automazione di build (compilazione) che permette di individuare errori di integrazione il prima possibile. + +### Test-driven development + +Il test-driven development (TDD) è una metodologia di sviluppo software che prevede di scrivere i test prima di scrivere il codice. +La parola "test" nell'acronimo è spesso mal interpretata. Il TDD non è uno strumento per testare l'applicazione, ma per far emergere il design dell'applicativo partendo dagli obiettivi, sottoforma di test, che vogliamo soddisfare. Questo ci permette di rispettare il principio YAGNI (_You aren't gonna need it_), ovvero non scrivere codice per esigenze future, ma solo per soddisfare l'implementazione dei test da soddisfare. + +Il TDD inizia con la scrittura dei test prima di scrivere il codice effettivo. Il ciclo TDD - Spesso chiamato _red-green-refactor_ - è semplice ma potente: + +1. Scrivi un Test: Inizia scrivendo un test che descriva il comportamento che desideri implementare. Questo test inizierà sicuramente come un test fallito, poiché il codice non esiste ancora. + +2. Scrivi il Codice Minimale: Scrivi il codice minimo necessario per far passare il test. In questa fase, non preoccuparti troppo della qualità del codice; l'obiettivo è far passare il test. + +3. Rifattorizza il Codice: Ora che il test è passato, puoi iniziare a migliorare la qualità del tuo codice. Rimuovi duplicazioni, migliora la leggibilità e assicurati che il codice sia pulito e ben strutturato. + +Un altro vantaggio del TDD è che si sta automaticamente creando una documentazione tecnica. Guardando la descrizione dei test, è facile comprendere come debba comportarsi l'applicazione. + +Non c'è rosa senza spine! Il TDD non è una pratica facile da padroneggiare. Un ottimo modo per iniziare, è l'esercitazione attraverso esercizi mirati, chiamati _kata_, spesso usati in sede di colloquio. + +**Ping Pong TDD** + +Tendenzialmente quando si fa Test Driven Development si è da soli davanti al proprio programma da completare e davanti alla propria tastiera. Esiste però una pratica che porta più persone a fare Test Driven Development insieme che prende il nome di _Ping Pong TDD_. +Questo è un metodo molto coinvolgente di applicare il TDD. + +Come accennato, è un pre-requisito del metodo essere almeno in due. + +Le regole di questo _gioco_ si basano sull'alternarsi alla tastiera quando si scrive un test. Il primo "turno" è diverso da tutti i successivi: chi si trova per primo alla tastiera scrive un test che fallisce, poi passa la tastiera al suo pair. Da questo e per tutti i turni successivi, quando una persona inizia il proprio turno deve: + +- Far diventare verdi i test scrivendo il codice di produzione adatto. +- Scrivere un test rosso. + +Una volta che il test rosso viene scritto, il turno sarà finito e la tastiera tornerà a chi ha iniziato la sessione di ping pong. In pratica ad ogni turno l'obiettivo è far passare i test e successivamente crearne di nuovi fino al completamento del software. + +### Behavior-driven development + +Il behavior-driven development (BDD) è una metodologia che permette di esplicitare i requisiti funzionali, tramite test. Questo permette una maggior comprensione degli sviluppi, creando un dialogo tra Product Team e Dev Team, con i test come lingua comune. + +Questo tipo di test viene scritto con un linguaggio chiamato _gherkins_, composto da Feature e vari scenari. Ogni scenario è composto da: + +1. Given: una fase di creazione delle pre-condizioni. +2. When: un'azione sotto test. +3. Then: una condizione da verificare. + +Di seguito un esempio che descrive una semplice ricerca su Google: + +``` +Feature: Google Searching + As a web surfer, I want to search Google, so that I can learn new things. + + Scenario: Simple Google search + Given a web browser is on the Google page + When the search phrase "panda" is entered + Then results for "panda" are shown +``` + +## Test Coverage + +La test coverage è una metrica che indica la percentuale di codice sorgente che viene eseguita (_coperta_) durante l'esecuzione dei test. Questa metrica è molto importante, in quanto permette di capire quanto il codice sorgente è stato testato. Solitamente si cerca di raggiungere una test coverage del 100%, ma questo non è sempre possibile, oltre che non necessario. Una test coverage del 100% non garantisce che il codice sorgente sia privo di bug, esattamente come non lo garantisce una coverage del 50%. Come in moltissimi altri aspetti della programmazione, la parola _dipende_ assume un significato molto importante. + +**La test coverage ci dice quanto del nostro codice si comporta come ci aspettiamo, ma non è detto che ciò che ci aspettiamo sia corretto.** + +### Over-testing + +Altra nota importante è relativa alla _coverage 100%_: solitamente si sconsiglia l'adozione di una coverage così alta in quanto si rischia di incorrere in un fenomeno chiamato _over-testing_, nel quale si testano tutte le possibili casistiche, anche quelle che non hanno senso e che impiegano molto tempo ad essere scritte. Questo fenomeno è molto pericoloso, in quanto si rischia di scrivere codice per il mero raggiungimento di un numero, la coverage appunto, che non aggiunge valore al prodotto e che non soddisfa alcun requisito funzionale o non funzionale. diff --git a/docs/it/testing/piramide.png b/docs/it/testing/piramide.png new file mode 100644 index 0000000000000000000000000000000000000000..21b391997ecdb287c7c674af7924c4b43f0e0fe4 GIT binary patch literal 4532 zcmd6rS6EZs(#HdY7^DTFLJ$NY^cH#*h;NkMLT{QN1OX{ZM^p?*6RDy19;62d9n7nu z5D-BSr5UA&2+|R$C!V|S;=4cl+0Qd;X75>RU#wa4`|o%QGkx~6d}jdw0K1_93Jm}- z(uWL@U?APxmE=~Y8=wc$6bS${C9@u3nd!dJEd#VE01z$)07OOu00;C?>(_0hdEfrh5n&U`(4?hL!;)(R^D0DyEGqL9|1 zQ){y!`R8_z-)v4&D5F4gnK4b%Qd z?r|~lH;hywQcAxD@sx&%N*Od~KGlbqlw@HI7MFzZepama%?AF|=6W&o3AtCwn9Xz}LY}oq9Gmd?pwP!|y zxj{Ml8`J9#hNOnz`#o60&tpkE;KCEi=;!qySPRRb4d9cObqg`7 z-n{jMz$g|k`?_N4oj2RSk-ypG-XUT2UK-UUT>}^kYa}?I*G6vKvs^hi$-!t!^N|SF zQQ)P~1_^4t+d0b17#UG3ze?`>8!d}|C;^HNNLF-|3FtT06xZNi?S8e~Z7R07aQNu~ zp9`P0&E1)-Jhu!e3&{nhQ_j((wTKZCCEpYz_6|8rVETu}u z^S8n47FHzFw773ir_y5#Q2>5^+h>o3(i-pFRwNoY33uM8!}$;(XThk%(oMgdwa+XPafu{3yKs zg)-i16;bU!ro6C3yufaiMwqMyHZSKT1o^ya2Fh!UJ4+=xe|{!n)!f^G7S*4=i@vO5 z`N1yK+aMvyz8s~c`Q%HrG|V#xQoVccbz5w?Z%;s{LyNI>R6kuH~sN5xQU4W0`q|6xupb88^uL|r@G$0_PF z@Xge~*f;u$+UcLE&1S+xtc{kVWBxpNiDZkLwi~Dcnui}(@3=h3HuQI`oNm9g&B8%y zuJF4r(^{dMJMWD5+#z>WJP|-yP$P%hniEEWzdwB)Qw!fbPtkB6{b*V({^_MzR&TI8 zr7KV>{o@V84cJ6*7qC&9Uf!9e_q!C6XxFuF;4hiL+ex)k-B2Wx)~7#X&wzr>sGQaV zTRi6v-0zxh`gxC;BzcFJ>xj3Hv+FI^vI;_u{2a&+{P5wbAtDxk4p=EXGFFv!r&<)= z=QC{9g{qZFm6Xdm{pO4KK}-EP;m~#(b&Z0qyU{-=I!Hs{!)oXIi?;$mlt5dV z{d>ua_-iL$vI6pUha=QzueseVC{SR7y;yl&ixOUyBqq-E$jvo1vyaiZQDfo-;A4q+ zqq37~q0jA+r5&up^JPO$(ECEOJ8!QC7ALIz_(y!t)4AVPhQ+#xt><$K_{+zrmqhF> zYBX^sxLY2g?LtW1>=22(J41DkFp;mvDt9%qH~7=bJ;kW-tJkk@w?O{P4IApmVNafR z#8=s;+J&arWP?{nSo4Q}-gyg{!}7iiB}+IQr549b%t%=4m>LJQ=g<8-CKO&^m)D>;Ff*VrXGU4Y0BQLo*59D#liYO zw6^q$)nkPnW-$PwOk(0JAMYyz&^`Z^@5mkg$lPN5&*lD~&Ns&G{@{!@!>1VL+f#bf zpR~b-WAx4(sP!IWAnVO4;$t}+%E}M9N6IqYAD=|Dza2~XDk}#(`S+|Z|0M>uFPB#h z1Y*&4rIUx*b+A_hGj9X#P=9p4(AOT0n6mt`A7|H*#WWGsTkHVH2^gJ{fCuEocaW0v_@MeL6+apdprN;BfV^XcD zsLKyPt=?q6M~H`uCd1mrGi!nJ-|8`cp(T*Xl05rmsY17NTXXWRu9~P!jx<3`tp*#FH z`)@zcCeu9+Lox#FPF*aV_bokS=_i=R2WBuoTJ-Jwc2n|lhPD2j7_TqHG*AL5dyzMq z^i>A$dE>{N+j(uX4S8y`1nWolOO(r?QMMXHI*k)l(h|^epL$eSTxoC~TAtQ4XKEah z|GFjzo?&nk$CZzP$To@vusrmD7)g82k%%b6=-EY` zkTmpA&idJsZVz*7FOA`!ML zUmm^I(ag^D&O?SXcZ%`_VyL^;HCk=?{AQcC@~}PHY%31>_QzZW9*i-5X&3y}N8CYv=>i zCU9Uo@mE;A+;U1=v2C07_CZV4{kiooHeuvk(QWNAXuzj6KMQV7HKvLxwIQm z68I>v7YqY2st=GkwnQa!b>ASs5-J$!d<8rML#6Iu#VGNh68Q548@%|HCP&m8t|52X zD2uIpltuarjo+klfe|k4c{5wXW)QuVtHcQ(Dg=N*u;{e%zo)R%K^f3YJo}vysANGs zA9LxLtrRE)yS5RBl#mQp%AlEpEQK#x7&kT`C197}q3KB=OGO@N1cd}DA-BmRujIi{ zEI~LKiVxlYm_7jHxrmDQ`7dLYkb^E#_Pa%*6HDq;yJXYG@X?zF2n^etr};4m}zZntDHW6id^NvZ%J% zu+;BUw1%oJyO+=5?cTI*Xh^nDm8NhHlDiet+zahg}Rw#7aYEqHa0{grA+Yw+Rj5?k+k= z^?3RV(BBC17t<$6|MNK6>WlF|EMg8~<<&n4xKR+Kifd2RF>Z$X5eT<2;61J92j-SfUQ|?t|K1@yhXx%8>!^8jC8c;wiWpas3Fj-x= zSLH1q_|oRGwL%OnILaXP7`%c$iK^rNCM+*+Sh91IRDoJvXRfR!H9 z1%AqO{HgrC)VwbENS9*#EUKs+N6pAl|5petW!JgL8)ZS&LCPp+1dBU$o5}_yR)|^2 z+w}&ap8w=0nl2=m7TtkJW=TWu6(fmZmx4Ou6V;Px(pCPJ0Z08TRf=VFA_%z{ojWKg z-u&9rc|yiavp~g8E43?k96N?7%J<3bae-B2iFDL?lZ|v6@1<{I9K^BP7~I>qqaSlcZ$nIg z{py!it{~tcFDhnnFgo8CazHk^&ZT_^0#l3oTWwdLY8L#}H>iFa1fJ$jjlPZbR*c1@ zAPJBE3Zi#HJFUUm<{OD+{nS_SK$Th?WKiS35(<@bdxXwJoiBOx1aaJKs&R^>zeuDC z{{8s8c7KwIoB7HN|KMB0qXfyF`G63>q7Tod%~=a_{a4}^M=@zt?eWMyL9Q1%h~6l? zZ1BG#;o;T8M?7HuRyo&@RRQ|14bi}B_JMBLKzGes_uT0QpomaVlT|>-Dk7{AYMKg4 rnkwqj2!tjAf!A5i{67gker}$)u>U_{`<8_iJpo{N%?wq46@&i|4R9=i literal 0 HcmV?d00001 From 2b7f7b65d77c0a3ef8f0d49bb3dfeff570f83d17 Mon Sep 17 00:00:00 2001 From: Michael Di Prisco Date: Sat, 23 Dec 2023 13:47:43 +0100 Subject: [PATCH 3/9] Aggiunta all'indice del libro del capitolo Testing --- docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.md b/docs/index.md index 3a6544d2..ece22a27 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,3 +2,4 @@ - [Introduzione](./it/introduzione.md) - [Cosa significa essere Dev](./it/cosa-significa-essere-dev.md) +- [Testing](./it/testing.md) From 424cd4bb04212cd0d6bc7dcf9e5230cd3daec9e2 Mon Sep 17 00:00:00 2001 From: Michael Di Prisco Date: Thu, 28 Dec 2023 21:57:17 +0100 Subject: [PATCH 4/9] Aggiunto Capitolo sulle architetture software (#123) Co-authored-by: Simone Gizzi Co-authored-by: Angelo Cassano Co-authored-by: Paolo Martinoli <81316809+ugho16@users.noreply.github.com> Co-authored-by: Tommaso Allevi Co-authored-by: Corrado Petrelli --- docs/it/architetture-software.md | 253 +++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 docs/it/architetture-software.md diff --git a/docs/it/architetture-software.md b/docs/it/architetture-software.md new file mode 100644 index 00000000..462c9876 --- /dev/null +++ b/docs/it/architetture-software.md @@ -0,0 +1,253 @@ +# Architetture Software + +Il termine "architettura software" viene spesso utilizzato in maniera molto generica e impropria. In questo documento cercheremo di dare una definizione e di descriverne le principali. + +Inoltre, cercheremo di dare un'idea di "chi si occupa di architetture software" e di descrivere il suo ruolo all'interno di un team di sviluppo. + +L'argomento è molto vasto e complesso, per cui proveremo a dare una visione generale, senza entrare troppo nel dettaglio, in quanto ogni singola sezione di questo capitolo potrebbe concretizzarsi in un libro a sé stante. + +## Cos'è l'architettura software? + +Wikipedia ci dà uno spunto di partenza: + +> L'architettura software è l'insieme delle strutture necessarie per ragionare su un sistema software e la disciplina per creare tali strutture e sistemi. Ogni struttura comprende elementi software, relazioni tra loro e proprietà di entrambi gli elementi e delle relazioni. + +In altre parole, l'architettura software è l'insieme di tutte le decisioni prese durante la progettazione di un sistema software. + +## I diversi aspetti dell'architettura software + +L'architettura software è un argomento molto vasto e complesso, ma possiamo identificare alcuni punti chiave che si applicano nella maggior parte dei casi: + +- **Componenti e moduli**: identificano i principali componenti o moduli del software e descrivono le loro responsabilità. Questi componenti possono essere funzioni, classi o persino interi microservizi in un sistema distribuito. +- **Flusso e comunicazione dei dati**: descrive il modo in cui i dati attraversano le diverse parti del sistema, inclusi meccanismi di input e output, database e servizi esterni. Comprendere il flusso di dati è fondamentale per garantire una comunicazione e un'elaborazione efficiente dei dati. +- **Comportamento del sistema**: definisce il comportamento previsto del software in varie condizioni, incluso il modo in cui vengono gestiti gli errori, ripristinati i guasti e organizzati gli adattamenti per far fronte all'aumento del carico. +- **Attributi di qualità**: soddisfano i requisiti non funzionali, come prestazioni, sicurezza, scalabilità e manutenibilità. Le decisioni di progettazione per ottimizzare il software vengono prese in funzione di queste qualità. +- **Vincoli e modelli**: l'architettura software spesso opera entro determinati vincoli, come budget, stack tecnologico o standard di conformità. Chi si occupa dell'architettura sfrutta i modelli di progettazione e le migliori pratiche per soddisfare questi vincoli, ottenendo al tempo stesso la funzionalità desiderata. + +In sostanza, l'architettura software fornisce un approccio strutturato alla costruzione di sistemi software complessi, garantendo che siano scalabili, manutenibili e in grado di soddisfare i requisiti e gli standard di qualità previsti. È una disciplina cruciale nell'ingegneria del software che aiuta chi sviluppa a prendere decisioni informate e a creare software che resistano alla prova del tempo. + +## Il contesto aziendale + +Chi si occupa di architetture software non può vivere in una bolla e non può esulare dal contesto aziendale nel quale si trova: ogni progetto va contestualizzato tenendo conto di queste caratteristiche durante la fase di progettazione per rendere l'implementazione più semplice. + +Essere quindi in grado di ascoltare e recepire le richieste e i cambiamenti del business e saper rispecchiare il tutto nel proprio lavoro quotidiano è fondamentale per prendere decisioni coerenti e creare architetture efficaci. + +L'architettura software gioca un ruolo fondamentale nel plasmare non solo gli aspetti tecnici di un sistema software ma anche l'organizzazione e la cultura più ampia all'interno della quale viene sviluppato e mantenuto. Un'architettura software ben progettata può favorire una cultura organizzativa positiva in diversi modi. In primo luogo, può promuovere la collaborazione e la comunicazione tra i team di sviluppo fornendo un modello chiaro della struttura e dei componenti del sistema. Quando i membri del team hanno una comprensione condivisa dell'architettura, diventa più facile per loro lavorare insieme in modo efficace, allineare i propri sforzi e prendere decisioni informate, promuovendo una cultura del lavoro di squadra e della cooperazione. + +Inoltre, l'architettura del software può seguire la strategia e gli obiettivi generali dell'organizzazione. Un'architettura ben ponderata può garantire che il sistema software sia allineato con gli obiettivi aziendali, rendendo più facile per l'organizzazione adattarsi alle mutevoli condizioni del mercato e alle esigenze dei clienti. Questo allineamento tra software e obiettivi aziendali può aiutare a promuovere una cultura agile e reattiva, in cui l'organizzazione è più propensa ad abbracciare il cambiamento e l'innovazione. + +In sintesi, l'architettura software non rappresenta solo un aspetto tecnico ma è un potente strumento in grado di plasmare la cultura dell'organizzazione. Quando si progetta tenendo conto della collaborazione, della comunicazione e in funzione degli obiettivi aziendali, si può promuovere una cultura del lavoro di squadra, dell'adattabilità e dell'innovazione all'interno dell'organizzazione, contribuendo in definitiva al successo dei progetti di sviluppo software e dell'azienda nel suo insieme. + +## Chi si occupa di architetture software? + +Chi si occupa di architettura del software è di solito una persona con una certa esperienza nel campo dell'ingegneria del software, ed è responsabile della progettazione e della supervisione della struttura di alto livello e della visione tecnica di un progetto o sistema software. Queste figure sono fondamentali per colmare il divario tra i requisiti concettuali di una soluzione software e la sua diretta implementazione. Il ruolo va oltre il codice: implica prendere decisioni strategiche sulla progettazione del sistema, garantire che sia in linea con gli obiettivi dell'organizzazione e ottimizzarlo in base ai vincoli prestabiliti. + +Di seguito le caratteristiche chiave che chi ricopre questo ruolo dovrebbe avere: + +- **Competenza tecnica**: questa figura dovrebbe avere una profonda conoscenza di vari linguaggi di programmazione, metodologie di sviluppo software e modelli architetturali. Deve rimanere aggiornata con le tecnologie emergenti e le tendenze nell'ingegneria del software. Seppure ci siano varie opinioni sulla necessità di conoscere più di un linguaggio di programmazione, è indubbio che conoscerne più di uno possa aiutare a trovare soluzioni più efficaci in modo particolare se aiuta la comprensione dei limiti che i vari contesti pongono. +- **Attitudine al problem-solving**: sono essenziali forti capacità analitiche e di risoluzione dei problemi. Questa figura deve analizzare problemi complessi, identificare soluzioni e prendere decisioni che incidono sulla progettazione complessiva del sistema. +- **Capacità di comunicazione**: una comunicazione efficace è fondamentale poiché le persone che ricoprono questo ruolo devono collaborare con team interfunzionali, parti interessate e con il team di sviluppo. Devono articolare la propria visione, le scelte progettuali e i concetti tecnici alle parti interessate non tecniche, facendo da ponte tra i due mondi. +- **Leadership**: Queste figure spesso assumono ruoli di leadership, guidando i team di sviluppo, facendo da mentor a figure junior e garantendo che la visione architetturale venga seguita durante tutto il ciclo di vita del progetto. +- **Design Thinking**: Le persone che ricoprono questo ruolo dovrebbero possedere una mentalità orientata al design, concentrandosi sulla creazione di soluzioni eleganti ed efficienti. Ciò include la progettazione per scalabilità, prestazioni, sicurezza ed esperienza utente. +- **Business thinking**: comprendere il contesto di business aziendale e gli obiettivi che l'azienda si è posta di raggiungere. Queste figure devono allineare le loro decisioni tecniche con gli obiettivi strategici dell'organizzazione. +- **Adattabilità**: il panorama del software è in continua evoluzione. La figura dovrebbe essere aperta e adattarsi a nuove tecnologie e metodologie e capace di rivalutare e riadattare l'architettura quando necessario, non solo per necessità tecniche, ma anche per rispondere ai cambiamenti del mercato e per soddisfare le esigenze dei clienti. + +Sebbene sia vero che il ruolo viene ricoperto da persone con una certa esperienza, non è detto che una figura junior non possa occuparsi di architetture software. Anzi, è molto importante che lo faccia, in quanto è un ottimo modo per imparare e crescere, ma il consiglio è di iniziare in un contesto controllato, più piccolo in modo da poter sperimentare meglio. L'affiancamento di una figura senior che possa guidare è sicuramente di aiuto per una persona junior. + +## Misurare la bontà di un'architettura + +Il termine _fitness function_ viene spesso adottato quando si parla di architetture evolutive, ovvero architetture software il cui scopo è quello di evolvere nel tempo, adattandosi ai cambiamenti del business e del mercato. Possono essere assimilabili a delle metriche che permettono di valutare quanto un'architettura software sia adatta a raggiungere gli obiettivi prefissati o ad eventuali obiettivi futuri del business. + +Apiumhub nel 2020 ha pubblicato un [post](https://apiumhub.com/tech-blog-barcelona/architectural-fitness-function) sul proprio blog in cui definisce questo concetto in maniera molto chiara: + +> La _fitness function_ è un tipo di funzione obiettivo utilizzata per riassumere quanto una determinata soluzione di architettura software sia vicina al raggiungimento degli obiettivi prefissati. Nel definire un'architettura evolutiva, l'architetto del software cerca un algoritmo "migliore"; la funzione fitness definisce cosa significa "migliore" in questo contesto. + +Esempi di fitness function possono essere: punteggio di scalabilità, percentuale di errori, tempo medio di risposta, quantità di messaggi persi dal broker, ecc. + +Poiché gli obiettivi prefissati di un'architettura variano da progetto a progetto, non esiste una _fitness function_ che è possibile usare ovunque. Di seguito diamo alcune idee di implementazione. + +### Triggered Fitness function + +Le _triggered fitness function_ (funzioni di fitness _attivate_ o _triggerate_) vengono eseguite in base a un evento particolare, ad esempio il team di sviluppo che esegue un test unitario, una pipeline di distribuzione che esegue una serie di operazioni o una persona del QA che esegue determinate attività stabilite. + +Questo tipo di funzioni ha da un lato il vantaggio di poter essere eseguito in maniera molto rapida, ma dall'altro lato ha il difetto di non essere rappresentativo di una situazione reale. Infatti, questo tipo di fitness function non tiene in considerazione il carico di lavoro che il sistema deve gestire durante il _day-by-day_, ma solo situazioni isolate e controllate. + +Queste funzioni di fitness vengono spesso lanciate durante una _pipeline_ di distribuzione, in modo da intercettare eventuali variazioni prima che il software venga rilasciato in produzione. + +Questo tipo di _fitness function_ richiede solitamente più manutenzione rispetto alle _continuous fitness function_, poiché deve essere adattato durante la vita del software, in base alle modifiche che vengono apportate. + +Alcuni esempi sono i test unitari, i test di integrazione, ecc. + +### Continuous Fitness function + +Le _continuous fitness function_ (funzioni di fitness _continue_) vengono eseguite in modo continuo sull'ambiente in analisi, tramite raccolta di metriche in tempo reale o comunque a cadenze rapide. Questo tipo di funzioni di fitness sono utili per monitorare il sistema e rilevare eventuali problemi prima che si verifichino, o analizzare dei trend. + +Questo tipo di funzioni ha da un lato il vantaggio di rappresentare la situazione reale, dall'altro lato ha il difetto di non essere replicabile, in quanto si basa su dati presi dall'ambiente che si sta analizzando (solitamente quello di produzione). + +Queste funzioni di fitness vengono spesso lanciate in un ambiente di produzione, in modo da avere contezza del reale contesto nel quale vengono eseguite. + +Alcuni esempi sono il monitoraggio dei tempi medi di risposta, il monitoraggio dei messaggi inviati e ricevuti in una coda, ecc. + +## Quali sono le principali architetture software? + +Esistono diverse architetture software, ognuna con i suoi pro e i suoi contro. In questa parte del libro, descriviamo le principali architetture software che, nel corso dei decenni, sono diventate uno standard de facto grazie alle loro molteplici implementazioni e casi di successo. + +Per scegliere quale architettura usare in diversi contesti, possiamo fare riferimenti alle seguenti caratteristiche: + +- **Start-up**: Il tempo necessario per definire l'architettura software e cominciare a sviluppare funzionalità. Tale tempo non è da sottovalutare poiché potrebbe richiede, in base al contesto aziendale, una serie di procedure che possono essere automatizzate da tools come le `platform engineering tools`. +- **Costi**: Il costo che si affronta nell'arco della vita di un progetto o un prodotto che implementi questa architettura. Da considerare che nell'effettiva valutazione dei costi bisogna differenziare eventuali costi di avvio, da pagare una tantum, da costi ricorrenti, da pagare periodicamente per la manutenzione. +- **Sviluppo e manutenzione**: La facilità con il quale è possibile effettuare modifiche e manutenzione al software. Per semplicità, anche l'aspetto del testing viene incluso in questo punto. +- **Tracciabilità**: La facilità con la quale è possibile individuare problemi o bug all'interno del software. +- **Scalabilità**: La facilità con la quale è possibile scalare il software, ovvero la capacità di gestire un carico di lavoro maggiore. Questo punto non fa riferimento alla scalabilità orizzontale o a quella verticale e non tiene conto dei costi, ma dell'impegno tecnico necessario per scalare il software. +- **Performance**: La velocità con la quale il software è in grado di elaborare i dati per rispondere ad un'esigenza di business. + +Questi punti chiave sono da intendersi come una valutazione soggettiva, in quanto ogni architettura software può essere implementata in modi diversi, con conseguenze diverse, valutando criteri e parametri differenti in base alle proprie necessità e, pur essendo un elenco piuttosto esaustivo, mix di queste architetture hanno dimostrato di essere vincenti in molti casi, anche a discapito di quanto riportato qui sopra. + +I punti chiave sono espressi con dei voti che vanno da 1 a 5, dove 1 è il voto più basso e 5 il voto più alto. Per _alto_ si intende il valore migliore per il punto chiave in questione, mentre per _basso_ si intende il valore peggiore per il punto chiave in questione, ovvero il valore che si vorrebbe evitare. Nel caso di _costi_, ad esempio, un voto alto significa che i costi sono bassi, mentre un voto basso significa che i costi sono alti. + +Segue una tabella riepilogativa dei punti di forza e di debolezza di ogni architettura. + +| | **Monolite** | **Monolite modulare** | **Microkernel** | **Microservizi** | **Service-based** | +| --------------------------- | --------------- | --------------------- | --------------- | ---------------- | ----------------- | +| **Start-up** | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️ | ⭐️⭐️⭐️ | +| **Costi** | ⭐️⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | +| **Sviluppo e manutenzione** | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️ | ⭐️⭐️⭐️ | +| **Tracciabilità** | ⭐️⭐️⭐️⭐️ | ⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | +| **Scalabilità** | ⭐️ | ⭐️ | ⭐️⭐️ | ⭐️⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | +| **Performance** | ⭐️⭐️ | ⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | ⭐️⭐️⭐️⭐️ | + +Nelle sezioni che seguono verranno indicati alcuni termini che possono non essere familiari a tutti. Per questo motivo, quanto segue è un glossario dei termini più utilizzati. + +Quando parliamo di _scalabilità verticale_ ci riferiamo all'incremento delle risorse hardware a disposizione del sistema (CPU, RAM, storage, ecc.) quando queste non sono più sufficienti per gestire il carico di lavoro. + +Quando parliamo di _scalabilità orizzontale_ ci riferiamo alla replicazione dei componenti del sistema, in modo da poter gestire un carico di lavoro maggiore. Le tecniche di scalabilità orizzontale sono varie e possono essere implementate in modi diversi, in base alle esigenze del sistema. + +Quando parliamo di _layer applicativi_ ci riferiamo a un livello di astrazione del software. Il database, le API, il front-end, ecc. sono tutti layer del software. + +### Monolite + +Il monolite è un'architettura software in cui tutte le funzionalità sono sviluppate e distribuite come un singolo pacchetto. È il tipo di architettura più semplice da implementare, in quanto non richiede particolari accorgimenti per la comunicazione tra i vari componenti, dal momento che questi ultimi risiedono all'interno dello stesso applicativo. + +Trattasi dell'architettura software più semplice da implementare e più diffusa, ma anche la più difficile da scalare, in quanto non è possibile replicare i singoli componenti, ma è necessario scalare l'intero sistema. In questi casi, infatti, al monolite viene affiancato il concetto di _scalabilità verticale_. + +Solitamente questa architettura viene identificata anche come _Layered Architecture_. + +In questa architettura i layer applicativi sono tutti parte dello stesso applicativo. + +È importante notare che storicamente questa architettura è spesso risultata la più sensibile al concetto di _stratificazione del codice_, ovvero il continuo sviluppo di funzionalità una sopra l'altra in sostituzione o sovrapposizione di precedenti, rendendo il codice sempre più complesso e difficile da mantenere. Questo fenomeno è stato spesso chiamato _Big Ball of Mud_. + +- **Start-up**: 5. Il monolite è l'architettura software più semplice da implementare, in quanto non richiede particolari accorgimenti per la comunicazione tra i vari componenti o una necessità di valutazioni iniziali elevate. Molti linguaggi di programmazione, inoltre, offrono dei framework che permettono di implementare un monolite in pochi minuti. Fra i principali framework troviamo Ruby on Rails, Django, Spring Boot, Laravel, ecc. +- **Costi**: 3. Pur essendo un'architettura _a basso costo_ in termini di start-up, il costo cresce esponenzialmente per via della necessità di _scalare orizzontalmente_. +- **Sviluppo e manutenzione**: 4. Il monolite è tra le architetture software più semplici da sviluppare e mantenere, per gli stessi motivi espressi nella voce _start-up_. I framework sono ormai molto maturi e permettono di sviluppare e mantenere un monolite in maniera molto semplice. +- **Tracciabilità**: 4. Poiché tutti i componenti fanno parte dello stesso processo o blocco, è facile individuare la porzione di codice che ha generato un problema o un bug. +- **Scalabilità**: 1. Il monolite è tra le architetture software più difficili da scalare, in quanto non è possibile replicare i singoli componenti, ma è necessario scalare l'intero sistema. In questi casi, infatti, al monolite viene affiancato il concetto di _scalabilità verticale_. La valutazione è dovuta alla necessità, nella maggior parte delle implementazioni di questo tipo, di dover riavviare il sistema per scalare le risorse hardware. +- **Performance**: 2. La performance del monolite è legata alla capacità di scalare le risorse hardware a disposizione del sistema. Di conseguenza, la curva di crescita dei tempi di risposta tende a crescere sempre di più. Solitamente le performance, seppur buone nelle prime fasi di vita del software, tendono a degradare nel tempo. + +### Monolite Modulare + +Il monolite modulare è un'architettura software in cui tutte le funzionalità sono sviluppate e distribuite come un singolo pacchetto, ma con la differenza che il codice è organizzato in moduli. Questi moduli possono essere sviluppati e distribuiti in maniera indipendente, ma sono comunque parte dello stesso _blocco_, inteso che l'applicativo online è unico, come nel caso del monolite _classico_. + +I moduli devono essere quanto possibile indipendenti tra di loro in modo da avere una suddivisione delle funzionalità segregata. La forza di questa architettura è comunque la possibilità, seppur da tenere sotto controllo, di far comunicare tra di loro i moduli tramite delle interfacce pubbliche. + +Da non confondersi con altre architetture, in questo caso i moduli sono parte dello stesso processo o applicativo, rendendo necessaria la _scalabilità verticale_. + +In questa architettura i layer applicativi sono tutti parte dello stesso applicativo. + +- **Start-up**: 4. Essendo una variante del monolite, lo start-up è molto semplice, ma la necessità di organizzare il codice in moduli può richiedere un po' di tempo. +- **Costi**: 3. Pur essendo un'architettura _a basso costo_ in termini di start-up, il costo cresce esponenzialmente per via della necessità di _scalare orizzontalmente_. +- **Sviluppo e manutenzione**: 5. Rispetto a un monolite _classico_, il monolite modulare è più semplice da sviluppare e mantenere, in quanto i moduli hanno un compito ben definito e sono quanto più possibile indipendenti tra di loro. +- **Tracciabilità**: 2. Compattando i moduli in un unico blocco, è più difficile individuare la porzione di codice che ha generato un problema o un bug in quanto solitamente il codice dei singoli moduli viene minificato o comunque ottimizzato per la produzione. +- **Scalabilità**: 1. Il monolite, anche in forma modulare, è l'architettura software più difficile da scalare, in quanto non è possibile scalare i singoli componenti, ma è necessario scalare l'intero sistema. In questi casi, infatti, al monolite viene affiancato il concetto di _scalabilità verticale_. La valutazione è dovuta alla necessità, nella maggior parte delle implementazioni di questo tipo, di dover riavviare il sistema per scalare le risorse hardware. +- **Performance**: 1. La performance del monolite modulare presenta le stesse problematiche del monolite _classico_, con l'aggiunta che per far funzionare questa architettura è necessario un ulteriore livello di astrazione, ovvero il modulo, che può portare ad un degrado delle performance. + +## Microkernel + +Chiamata anche _architettura a plugin_, si compone essenzialmente di un nucleo centrale che si occupa di gestire le comunicazioni tra i vari componenti, che sono sviluppati e distribuiti come plugin. +Questi plugin possono essere sviluppati e distribuiti in maniera indipendente, ma funzionando attorno ad un nucleo centrale, faranno sempre parte dello stesso _blocco_, inteso che l'applicativo online è unico, come nel caso del monolite _classico_. + +Il concetto principale attorno a questa architettura è l'indipendenza totale tra i plugin. Per definizione, nessun plugin dovrebbe avere come dipendenza un altro plugin. + +In questa architettura i layer applicativi sono tutti parte dello stesso applicativo. + +- **Start-up**: 4. Essendo una variante del monolite, lo start-up è molto semplice, ma la necessità di organizzare il codice in un nucleo centrale e implementare un sistema di plugin può richiedere più tempo. +- **Costi**: 3. Pur essendo un'architettura _a basso costo_ in termini di start-up, il costo cresce esponenzialmente per via della necessità di _scalare orizzontalmente_. +- **Sviluppo e manutenzione**: 4. Trattasi di un'architettura semplice da mantenere e sulla quale aggiungere funzionalità, ma la necessità di non far comunicare i plugin tra di loro può aggiungere una lieve complessità. +- **Tracciabilità**: 3. Testare e tracciare eventuali bug in questa architettura è mediamente complesso. L'isolamento dei plugin aiuta con il testing, ma la correlazione col nucleo centrale a volte può rallentare il processo di tracciamento. +- **Scalabilità**: 2. Le difficoltà di scalabilità sono anche in questo caso dovute alla _singola unità di rilascio_ o _single deployment unit_, ovvero trattandosi di un unico applicativo, è necessario scalare l'intero sistema, dovendo quindi ricorrere alla _scalabilità verticale_. +- **Performance**: 4. Processi di comunicazione semplici e isolabilità rendono questa architettura molto performante. + +## Microservizi + +La _buzzword_ per eccellenza degli ultimi anni. + +Questa architettura software si compone di un insieme di servizi indipendenti tra di loro, ognuno con un compito ben definito, che comunicano tra di loro attraverso un meccanismo di comunicazione _solitamente_ asincrono. + +A differenza delle architetture _a singolo blocco_ viste sopra, questa architettura permette di scalare i singoli componenti, in quanto ogni componente è un applicativo separato (servizio) e viene rilasciato in maniera indipendente. + +In questa architettura ogni microservizio solitamente ha il proprio database e il proprio back-end (basato su API), mentre il front-end è solitamente un'interfaccia grafica che comunica con i microservizi attraverso le API, a prescindere da dove risieda o da come sia implementato. I database sono solitamente piccoli e si occupano di gestire solo i dati necessari al microservizio in questione. + +A differenza delle altre architetture citate, la condivisione del database è da considerarsi un _anti-pattern_, ovvero una pratica da non adottare, in quanto può portare a problemi di _coupling_ tra i microservizi, esattamente l'opposto di quanto si vuole ottenere con questa architettura. + +Per definizione i microservizi non dovrebbero comporsi di più di una manciata di endpoint e relative funzioni, in quanto altrimenti si parla più di _service-based architecture_. + +Da notare che il _decoupling_ creato da questa architettura può portare ad un notevole aumento della complessità. + +- **Start-up**: 2. Lo start-up di un'architettura di questo tipo è complessa, in quanto è necessario stabilire sistemi di _orchestrazione_ o di _coreografia_ dei microservizi. Inoltre, il tipo di comunicazione (sincrono o asincrono) e il protocollo adottato (HTTP, AMQP, ecc.) devono essere valutati con attenzione. +- **Costi**: 4. Potendo scalare indipendentemente i singoli microservizi, i costi sono contenuti, in quanto è possibile scalare solo i microservizi che ne hanno bisogno, e solo nei momenti in cui si ritiene necessario. +- **Sviluppo e manutenzione**: 2. Il sistema di orchestrazione o coreografia dei microservizi può aggiungere una complessità non indifferente, soprattutto se non si ha esperienza in questo campo. Inoltre, la necessità di comunicare tra i microservizi può aggiungere un ulteriore livello di complessità. +- **Tracciabilità**: 3. Testare e tracciare eventuali bug in questa architettura è complesso. L'isolamento dei microservizi aiuta in questo caso, ma la tracciabilità è piuttosto complessa e richiede integrazione di _distributed tracing_ o _open telemetry_. +- **Scalabilità**: 5. La scalabilità è il punto di forza di questa architettura, in quanto ogni microservizio può essere replicato indipendentemente dagli altri. +- **Performance**: 4. La performance di questa architettura è legata alla capacità di scalare i singoli microservizi. Con una buona configurazione di auto-scaling si possono raggiungere eccellenti risultati, anche se la necessità di mettere in comunicazione, via HTTP, socket o qualsiasi altra forma, una quantità elevata di sistemi può impattare sulle performance. + +## Service-based + +Il _service-based è un'architettura software in cui l'applicativo viene suddiviso in una manciata di servizi (Solitamente da 3 a 12) che comunicano tra di loro attraverso un meccanismo di comunicazione \_solitamente_ asincrono. + +Ci si aspetta che i servizi siano in costante comunicazione tra di loro e che rispettino dei contratti (interfacce) precedentemente stabiliti. Questo tipo di architettura è molto simile a quella dei microservizi, ma con la differenza che i servizi sono solitamente più grandi e con un compito ben definito. + +In questa architettura ogni servizio solitamente ha il proprio database, il proprio back-end e il proprio front-end, anche se ci sono casi in cui il database possa essere condiviso tra i servizi (in questo caso si suggerisce di utilizzare un utente dedicato per l'accesso alle singole tabelle o agli schemi di pertinenza), altri in cui il front-end vive in un applicativo separato o, ancora, altri in cui il front-end è unico per tutti i servizi. + +Questa architettura viene spesso indicata come "l'anello mancante" tra il monolite e i microservizi, anche se la dimensione dei servizi e il successivo _decoupling_ sono temi piuttosto complessi da gestire. + +- **Start-up**: 3. Lo start-up di un'architettura di questo tipo è complessa, ma non quanto quella a microservizi, anche se molte delle problematiche sono simili. +- **Costi**: 4. Potendo scalare indipendentemente i singoli servizi, i costi sono contenuti, in quanto è possibile scalare solo i servizi che ne hanno bisogno, e solo nei momenti in cui lo si ritiene necessario. +- **Sviluppo e manutenzione**: 3. Come per lo start-up, le sfide e le necessità sono simili a quelle dei microservizi, ma trattandosi di entità più grandi, la complessità diminuisce. +- **Tracciabilità**: 4. Testare e tracciare eventuali bug in questa architettura è piuttosto semplice vista la normale dimensione dei servizi. L'isolamento aiuta, e anche qui si suggerisce l'integrazione di _distributed tracing_ o _open telemetry_. +- **Scalabilità**: 4. La scalabilità è il punto di forza di questa architettura, in quanto ogni servizio può essere replicato indipendentemente dagli altri, ma la dimensione degli stessi può rendere più complicato del previsto il processo. +- **Performance**: 4. La performance di questa architettura è legata alla capacità di scalare i singoli servizi. Con una buona configurazione di auto-scaling si possono raggiungere eccellenti risultati, anche se la necessità di mettere in comunicazione, via HTTP, socket o qualsiasi altra forma, una quantità elevata di sistemi può impattare sulle performance. + +## Altre architetture e pattern + +Architetture come la _space-based architecture_ o la _service-oriented architecture_ vengono utilizzate in contesti specifici e non sono solitamente utilizzate come architetture software di riferimento, di conseguenza vengono citate solo per completezza d'informazione. + +Una nota importante riguarda la _cell-based architecture_ che si pone come punto di incontro tra i microservizi e la _service-based architecture_. Partendo dal concetto di microservizi, potremmo identificare una _cell_ come un conglomerato di microservizi che rispondono a una necessità di business con una interfaccia unificata. Se si parte invece dal concetto di _service-based_, potremmo identificare una _cell_ come ulteriore scomposizione per facilitarne la manutenzione e la scalabilità. + +Altri termini, come la _event-driven architecture_ o la _event-sourcing architecture_ in realtà spesso si riferiscono ad un pattern di progettazione, ovvero un modo di progettare un sistema software, e non un'architettura software a tutti gli effetti. Il concetto di _event-driven_ viene infatti _affiancato_ più che _sostituito_ ad un'architettura software, come nel caso dei microservizi o del _service-based_. + +## Documentazione + +### Architecture Decision Records + +Gli _Architecture Decision Records_ (ADR) sono un modo per documentare le decisioni prese durante la progettazione di un sistema software. Questo tipo di documentazione è molto utile per capire il perché di determinate scelte e per capire come il sistema è stato progettato. + +A differenza di una classica documentazione tecnica o di un diagramma, le ADR sono molto più semplici da scrivere e da leggere, in quanto sono composte da pochi elementi: + +- **Titolo**: il titolo della decisione presa. +- **Stato**: lo stato della decisione presa. Solitamente può essere _Proposta_, _Accettata_, _Completata_, _Rifiutata_ o _Sostituita_. +- **Contesto**: il contesto in cui è stata presa la decisione. +- **Decisione**: la decisione presa. +- **Conseguenze**: le conseguenze della decisione presa. + +Le ADR vengono spesso utilizzate nelle aziende in cui si fa leva sul _BDD_ (Behavior Driven Development) per la stesura dei ticket nel proprio sistema di ticketing, puntando ad uno specifico ADR per dare informazioni aggiuntive e contesto a chi legge il ticket. + +## Conclusioni + +L'architettura software è un argomento molto vasto e complesso, materia che ognuno di noi dovrebbe conoscere e comprendere, in quanto influenza ogni aspetto dello sviluppo software. + +Un'architettura scelta in maniera frettolosa o senza una valutazione attenta può portare a conseguenze disastrose, come ad esempio un sistema che non riesce a gestire il carico di lavoro o che non riesce a soddisfare i requisiti di qualità e scalabilità richiesti. + +D'altro canto, si consiglia a chiunque legga questi contenuti di non basarsi sulle mere valutazioni fatte, che sono generaliste e non applicabili a tutti i contesti, ma di approfondire l'argomento e di valutare con attenzione ogni aspetto, in quanto ogni architettura software ha i suoi pro e i suoi contro, e ogni progetto ha le sue esigenze, e spesso la verità sta nel mezzo o, come piace dire a noi dev: _dipende_. + +## Riferimenti + +La lista di architetture software è ispirata e rivisitata a partire dal materiale prodotto e distribuito da [Mark Richards](https://www.developertoarchitect.com/), autore di molti libri sull'architettura software, video e webinar pubblicati su varie piattaforme, tra cui O'Reilly e YouTube. From b30541ff283f48355658bfef0db9e947ae829a3a Mon Sep 17 00:00:00 2001 From: Michael Di Prisco Date: Thu, 28 Dec 2023 21:59:28 +0100 Subject: [PATCH 5/9] feat: aggiunto capitolo architetture software all'indice (#189) --- docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.md b/docs/index.md index ece22a27..a62c551b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,3 +3,4 @@ - [Introduzione](./it/introduzione.md) - [Cosa significa essere Dev](./it/cosa-significa-essere-dev.md) - [Testing](./it/testing.md) +- [Architetture Software](./it/architetture-software.md) From f7b8d67820ffa65c2c78814f10a199d56611573e Mon Sep 17 00:00:00 2001 From: Lorenzo Zabot Date: Thu, 11 Jan 2024 13:13:31 +0100 Subject: [PATCH 6/9] ci: bump gh actions versions (#178) --- .github/workflows/formatting-validation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/formatting-validation.yml b/.github/workflows/formatting-validation.yml index e7125723..f2fd0820 100644 --- a/.github/workflows/formatting-validation.yml +++ b/.github/workflows/formatting-validation.yml @@ -8,9 +8,9 @@ jobs: format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 18 - name: Prettier Check - run: npm run format:check \ No newline at end of file + run: npm run format:check From 6a767472ce09eb71b278f4cec0b720317d2a1d4d Mon Sep 17 00:00:00 2001 From: Livio Francisconi <90481242+Livio74@users.noreply.github.com> Date: Thu, 11 Jan 2024 14:13:06 +0100 Subject: [PATCH 7/9] fix: sistemazione fine riga unix anche su prettier (#188) --- .prettierrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index 6e59ae61..a61d7fb5 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { "singleAttributePerLine": true, - "trailingComma": "es5" + "trailingComma": "es5", + "endOfLine": "lf" } From 988503b05327050d412d5fa503b36c9376ec3288 Mon Sep 17 00:00:00 2001 From: Michael Di Prisco Date: Sat, 13 Jan 2024 14:13:12 +0100 Subject: [PATCH 8/9] chore: aggiunto link al libro nel readme (#193) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 88a2d1da..25807825 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,10 @@ Questo progetto nasce da un post su LinkedIn che ha raccolto decine di persone attorno all'obiettivo di realizzare un libro completamente Open Source. Dalla scelta del tema alla stesura del contenuto, il tutto verrà gestito e condiviso con la community e con chiunque voglia contribuire al progetto. +## Vuoi leggerlo? + +Il libro è e sarà sempre disponibile online in maniera Open Source. Vuoi leggerlo? [Clicca qui!](https://il-libro-open-source.github.io/book/) + ## Come contribuire Puoi contribuire al progetto in moltissimi modi. From 1dc54fb96c0e54eb06ea9d2a64eefeb1c136826a Mon Sep 17 00:00:00 2001 From: Michael Di Prisco Date: Wed, 17 Jan 2024 18:53:59 +0100 Subject: [PATCH 9/9] feat: aggiunti altri idee al CONTRIBUTING.md (#194) --- CONTRIBUTING.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 593fc24b..3c73d0ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,6 +28,22 @@ Per formattare i file markdown con Visual Studio Code è necessario installare l Un buon consiglio è tenere attivo il flag `Format On Save` direttamente nelle impostazioni di vscode per evitare di dover formattare ogni volta a mano. +### JetBrains IDE (WebStorm, IntelliJ, ecc.) + +Per formattare i file markdown con IDE JetBrains è necessario installare l'estensione [Prettier](https://plugins.jetbrains.com/plugin/10456-prettier), tranne per WebStorm che include già Prettier di default. + +Alcuni suggerimenti di configurazione si possono trovare [qui](https://prettier.io/docs/en/webstorm). + +### Vim + +Per formattare i file markdown con Vim è necessario installare il plugin [vim-prettier](https://github.com/prettier/vim-prettier). + +Alcuni suggerimenti di configurazione si possono trovare [qui](https://prettier.io/docs/en/vim). + +### Altri IDE + +Nella documentazione di Prettier sono presenti le istruzioni per configurare il tool nel proprio IDE preferito: [Editor Integration](https://prettier.io/docs/en/editors). + ## Conventional commits Per mantenere uno storico e poter costruire dei changelog è richiesto a tutti i contributori del progetto di utilizzare i [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).