Ciao, amici. In attesa del lancio del corso , tradizionalmente condividiamo con voi la traduzione di materiale utile.
Il software sta risolvendo un numero sempre maggiore di compiti quotidiani, diventando sempre più complesso. Come disse una volta Marc Andreessen, sta assorbendo il mondo.

Di conseguenza, negli ultimi anni, gli approcci allo sviluppo e alla consegna delle applicazioni sono cambiati drasticamente. Si sono verificati spostamenti di portata tettonica, che hanno portato alla nascita di un insieme di principi. Questi principi si sono rivelati utili per formare team, progettare, sviluppare e consegnare la tua applicazione agli utenti finali.
I principi possono essere riassunti nei seguenti modi: l'applicazione deve essere piccola, collegata alla rete e avere un'architettura orientata agli sviluppatori. Facendo leva su questi tre principi, puoi creare un'applicazione affidabile e complessa che può essere rapidamente e in sicurezza consegnata all'utente finale, oltre a essere facilmente scalabile e ampliabile.

Ognuno dei principi proposti ha una serie di aspetti che discuteremo per mostrare come ciascun principio contribuisca al raggiungimento dell'obiettivo finale, che è una rapida consegna di applicazioni affidabili, facili da mantenere e utilizzare. Considereremo i principi in confronto alle loro opposizioni, per chiarire cosa significa, ad esempio, "Assicurati di utilizzare il principio della piccolezza».
Speriamo che questo articolo ti incoraggi a utilizzare i principi suggeriti per costruire applicazioni moderne che garantiscano un approccio unificato alla progettazione nell'ambito di un crescente stack tecnologico.
Applicando questi principi, scoprirai di adottare le ultime tendenze nello sviluppo del software, incluso l'approccio per lo sviluppo e la consegna delle applicazioni, l'uso dei container (ad esempio, ) e framework per l'orchestrazione dei container (ad esempio, ), l'uso dei microservizi (inclusa l'Architettura a Microservizi e per applicazioni basate su microservizi.
Cosa sono le applicazioni moderne?
Applicazioni moderne? Stack moderno? Cosa significa esattamente "moderno"?
La maggior parte degli sviluppatori ha solo una conoscenza generale di cosa sia un'applicazione moderna, quindi è necessario fornire una definizione chiara di questo concetto.
Un'applicazione moderna supporta più client, sia che si tratti di un'interfaccia utente basata sulla libreria JavaScript React, di un'app mobile per Android o iOS, o di un'app che si collega ad un'altra tramite API. Un'applicazione moderna implica la presenza di un numero indefinito di client, per i quali fornisce dati o servizi.
Un'applicazione moderna fornisce API per accedere ai dati e ai servizi richiesti. L'API deve essere invariabile e costante, e non scritta specificamente per una richiesta concreta proveniente da un client specifico. L'API è accessibile tramite HTTP(S) e consente l'accesso a tutte le funzionalità disponibili nell'interfaccia grafica (GUI) o nella linea di comando (CLI).
I dati devono essere disponibili in un formato comune e compatibile, come JSON. L'API fornisce oggetti e servizi in una forma comprensibile e organizzata; ad esempio, le API RESTful o GraphQL offrono un'interfaccia adeguata.
Le applicazioni moderne sono costruite su stack moderni, e uno stack moderno è quello che supporta tali applicazioni. Questo stack consente agli sviluppatori di creare facilmente un'app con interfaccia HTTP e endpoint API chiari. L'approccio scelto consentirà alla tua applicazione di ricevere e inviare dati in formato JSON con facilità. In altre parole, lo stack moderno corrisponde agli elementi dell'App a Dodici Fattori per .
Le versioni popolari di questo tipo di stack si basano su , , , , e . L'Architettura a Microservizi incarna un esempio di stack moderno implementato in ciascuno dei linguaggi menzionati.
Si prega di notare che non promuoviamo esclusivamente un approccio a microservizi. Molti di voi lavorano con monoliti che devono evolversi, mentre altri gestiscono applicazioni SOA che si espandono e si sviluppano per diventare applicazioni a microservizi. Altri ancora si stanno dirigendo verso l'implementazione di applicazioni serverless, mentre alcuni stanno adottando combinazioni di quanto sopra. I principi esposti nell'articolo sono applicabili a ciascuno di questi sistemi con alcune leggere modifiche.
Principi
Ora che abbiamo raggiunto una comprensione generale di cosa siano le moderne applicazioni e lo stack moderno, è tempo di immergerci nei principi di architettura e sviluppo che vi saranno di grande aiuto nella creazione, implementazione e supporto di un'applicazione moderna.
Uno dei principi è "creare piccole applicazioni", chiamiamolo semplicemente il principio della piccolezza. Ci sono applicazioni incredibilmente complesse costituite da molti componenti mobili. Allo stesso modo, costruire un'applicazione utilizzando piccoli componenti discreti semplifica la sua progettazione, manutenzione e gestione complessiva. (Nota che abbiamo detto "semplifica" e non "rende semplice").
Il secondo principio è che possiamo aumentare la produttività degli sviluppatori aiutandoli a concentrarsi sulle funzionalità che stanno sviluppando, liberandoli così dalle preoccupazioni relative all'infrastruttura e al CI/CD durante l'implementazione. Quindi, in poche parole, il nostro approccio è orientato agli sviluppatori.
Infine, tutto ciò che riguarda la vostra applicazione dovrebbe essere connesso in rete. Negli ultimi 20 anni abbiamo fatto notevoli progressi verso un futuro di rete, poiché le reti sono diventate più veloci e le applicazioni più complesse. Come abbiamo già scoperto, un'applicazione moderna deve essere utilizzata in rete da molti diversi client. L'adozione di un pensiero di rete nell'architettura porta notevoli vantaggi, che si combinano bene con il principio della piccolezza e il concetto di approccio, orientato agli sviluppatori.
Se durante la progettazione e l'implementazione di un'applicazione ricorderete i principi sopra citati, avrete un vantaggio innegabile nello sviluppo e nella consegna del vostro prodotto.
Esaminiamo questi tre principi in modo più dettagliato.
Il principio della piccolezza
Il cervello umano fatica a elaborare una grande quantità di informazioni contemporaneamente. In psicologia, il termine carico cognitivo indica la quantità complessiva di sforzi mentali necessari per mantenere le informazioni in memoria. Ridurre il carico cognitivo per gli sviluppatori è una priorità, poiché in questo modo possono concentrarsi sulla risoluzione dei problemi invece di dover tenere a mente il modello complesso dell'intera applicazione e delle funzionalità in fase di sviluppo.

Le applicazioni vengono scomposte per i seguenti motivi:
- Ridurre il carico cognitivo per gli sviluppatori;
- Accelerare e semplificare il testing;
- Consegna rapida delle modifiche nell'applicazione.
Esistono diversi modi per ridurre il carico cognitivo per gli sviluppatori, ed è qui che entra in gioco il principio della piccolezza.
Quindi, tre modi per ridurre il carico cognitivo:
- Ridurre le scadenze che devono considerare quando sviluppano una nuova funzione: più breve è il timeframe, minore è il carico cognitivo.
- Ridurre il numero di righe di codice su cui si lavora contemporaneamente: meno codice implica meno carico.
- Semplificare il processo di apportare modifiche incrementali all'applicazione.
Riduzione delle scadenze nello sviluppo
Torniamo a quei tempi in cui la metodologia waterfall era lo standard per il processo di sviluppo, e scadenze di sei mesi a due anni per lo sviluppo o l'aggiornamento di un'applicazione erano la norma. In genere, gli ingegneri leggevano prima i documenti pertinenti, come i requisiti di prodotto (PRD), il documento di riferimento del sistema (SRD), il piano architettonico e iniziavano a mettere insieme tutte queste cose in un unico modello cognitivo, secondo il quale scrivevano il codice. Man mano che i requisiti e, di conseguenza, l'architettura cambiavano, era necessaria una notevole quantità di sforzi per informare l'intero team sugli aggiornamenti del modello cognitivo. Questo approccio, nel peggiore dei casi, poteva paralizzare completamente il lavoro.
La più grande svolta nel processo di sviluppo delle applicazioni è stata l'introduzione della metodologia agile. Una delle caratteristiche principali della metodologia agile – è uno sviluppo iterativo. Questo, a sua volta, porta a una riduzione del carico cognitivo sugli ingegneri. Invece di richiedere al team di sviluppo di realizzare l'applicazione in un lungo ciclo, agile l'approccio consente di concentrarsi su piccole porzioni di codice che possono essere testate e distribuite rapidamente, ricevendo anche un feedback. Il carico cognitivo dell'applicazione è passato da un intervallo di sei mesi a due anni, considerando l'enorme quantità di specifiche, a un'aggiunta o modifica di funzione ogni due settimane, mirata a una comprensione più sfumata di una grande applicazione.
Spostare il focus da un'applicazione massiccia a funzioni piccole e specifiche, che possono essere completate in uno sprint di due settimane, guardando non oltre una funzione del prossimo sprint, rappresenta un cambiamento significativo. Questo ha permesso di aumentare la produttività nello sviluppo, riducendo al contempo il carico cognitivo, che oscillava costantemente.
Nella metodologia agile si presume che l'applicazione finale sarà una versione leggermente modificata del concetto iniziale, quindi il punto finale dello sviluppo è necessariamente ambiguo. Solo i risultati di ciascun sprint specifico possono essere chiari e definiti.
Piccole basi di codice
Il passo successivo per ridurre il carico cognitivo è diminuire la base di codice. In genere, le applicazioni moderne sono massicce: un'applicazione aziendale robusta può consistere di migliaia di file e centinaia di migliaia di righe di codice. A seconda della struttura dei file, le relazioni e le dipendenze tra codice e file possono essere ovvie o meno. Anche il debug dell'esecuzione stessa del codice può presentare problemi, a seconda delle librerie utilizzate e di quanto bene gli strumenti di debug distinguano tra librerie/pacchetti/moduli e codice utente.
Costruire un modello mentale operativo del codice di un'applicazione può richiedere un notevole quantitativo di tempo e ripristinare un'elevata carico cognitivo per lo sviluppatore. Questo è particolarmente vero per i codici monolitici, dove esiste una grande quantità di codice, il cui interazione tra i componenti funzionali non è chiaramente definita, e la divisione degli oggetti di attenzione è spesso sfocata, poiché non vengono rispettati i confini funzionali.
Uno dei modi più efficaci per ridurre il carico cognitivo sugli ingegneri è passare a un'architettura a microservizi. Nel paradigma dei microservizi, ogni servizio si concentra su un insieme di funzionalità; il che significa che la logica del servizio è generalmente ben definita e comprensibile. I confini del servizio sono altrettanto chiari: ricorda che la comunicazione con il servizio avviene tramite API, quindi i dati generati da un servizio possono essere facilmente trasferiti a un altro.
L'interazione con altri servizi è solitamente limitata a diversi servizi utente e alcuni servizi del fornitore, che utilizzano chiamate API semplici e pulite, ad esempio tramite REST. Questo significa che il carico cognitivo per l'ingegnere si riduce notevolmente. La sfida più complessa rimane quella di comprendere il modello di interazione dei servizi e come cose come le transazioni si svolgono tra più servizi. Alla fine, l'uso dei microservizi riduce il carico cognitivo, diminuendo la quantità di codice, delineando confini chiari per il servizio e garantendo una comprensione delle relazioni tra utenti e fornitori.
Piccole modifiche incrementali
L'ultimo elemento del principio piccolezze – questo è la gestione del cambiamento. Per i programmatori è una tentazione particolare dare un'occhiata al codice sorgente (anche, forse, al loro stesso codice più vecchio) e affermare: «Questa è spazzatura, dobbiamo riscrivere tutto questo.» A volte è la decisione giusta, altre volte no. Questo comporta per il team di sviluppo il peso di un cambiamento globale del modello, il che porta a un carico cognitivo su larga scala. È meglio che gli ingegneri si concentrino sui cambiamenti che possono apportare nel corso dello sprint, per poi rilasciare tempestivamente le funzionalità necessarie, anche se gradualmente. Il prodotto finale dovrebbe assomigliare a quanto pianificato in precedenza, ma con alcune modifiche e test per soddisfare le esigenze del cliente.
Durante la riscrittura di grandi parti di codice, a volte diventa impossibile effettuare rapidamente la consegna delle modifiche, poiché entrano in gioco altre dipendenze del sistema. Per controllare il flusso delle modifiche, è possibile utilizzare l'associazione di funzionalità (feature hiding). In linea di principio, ciò significa che la funzionalità è presente in produzione, ma non è accessibile tramite impostazioni di variabili ambientali (env-var) o qualche altro meccanismo di configurazione. Se il codice ha superato tutti i processi di verifica della qualità, può trovarsi in produzione in uno stato nascosto. Tuttavia, questa strategia funziona solo se la funzione alla fine verrà attivata. Altrimenti, non farà altro che ingombrare il codice e aggiungere un carico cognitivo che lo sviluppatore dovrà affrontare per lavorare in modo produttivo. La gestione del cambiamento e le modifiche incrementali aiutano a mantenere il carico cognitivo degli sviluppatori a un livello gestibile.
Gli ingegneri devono affrontare molte difficoltà anche quando si tratta di implementare funzionalità aggiuntive semplici. Da parte della direzione, sarebbe saggio ridurre il carico eccessivo sul team, affinché possa concentrarsi sugli elementi chiave della funzionalità. Ci sono tre cose che puoi fare per aiutare il tuo team di sviluppatori:
- Utilizzare una metodologia
agile, per limitare il tempo durante il quale il team deve concentrarsi sulle funzionalità chiave. - Realizza la tua applicazione come una serie di microservizi. Questo limiterà il numero di funzionalità implementate e solidificherà i confini che mantengono il carico cognitivo durante il lavoro.
- Preferisci cambiamenti incrementali piuttosto che grandi e ingombranti, modifica piccoli pezzi di codice. Utilizza l'astro di funzionalità per implementare cambiamenti, anche se non saranno visibili immediatamente dopo l'aggiunta.
Se applichi il principio della piccolezza nel tuo lavoro, il tuo team sarà molto più felice, si concentrerà meglio nell'implementare le funzionalità necessarie e avrà maggiori probabilità di rilasciare cambiamenti di qualità più rapidamente. Ma questo non significa che il lavoro non possa complicarsi; a volte, al contrario, l'implementazione di una nuova funzionalità richiede la modifica di diversi servizi e questo processo può essere più complicato rispetto a quello in un'architettura monolitica. In ogni caso, i vantaggi dell'applicazione dell'approccio della piccolezza valgono lo sforzo.
Fine della prima parte.
Presto pubblicheremo la seconda parte della traduzione, e nel frattempo aspettiamo i vostri commenti e vi invitiamo al , che avrà luogo già oggi alle 20:00.
Fonte: habr.com
