Principi di sviluppo delle moderne applicazioni da NGINX. Parte 1

Ciao, amici. In vista del lancio del corso «Sviluppatore Backend in PHP», condividiamo tradizionalmente con voi la traduzione di materiale utile.

Il software sta risolvendo sempre più compiti quotidiani, diventando al contempo sempre più complesso. Come ha detto una volta Marc Andreessen, esso sta assorbendo il mondo.

Principi di sviluppo delle moderne applicazioni da NGINX. Parte 1

Di conseguenza, negli ultimi anni gli approcci allo sviluppo e alla consegna delle applicazioni sono cambiati radicalmente. Si sono verificati spostamenti di portata tettonica, che hanno portato all'emergere di un insieme di principi. Questi principi si sono rivelati utili nella formazione del team, nella progettazione, nello sviluppo e nella consegna della tua applicazione agli utenti finali.

I principi possono essere riassunti come segue: l'applicazione deve essere piccola, orientata alla rete e avere un'architettura focalizzata sullo sviluppatore. Basandoti su questi tre principi, puoi creare un'applicazione robusta e complessa, che può essere consegnata rapidamente e in sicurezza all'utente finale, oltre a essere facilmente scalabile e ampliabile.

Principi di sviluppo delle moderne applicazioni da NGINX. Parte 1

Ognuno dei principi proposti ha diversi aspetti che discuteremo per dimostrare come ciascun principio contribuisca al raggiungimento dell'obiettivo finale, ovvero la rapida consegna di applicazioni affidabili, facili da gestire e da utilizzare. Esamineremo i principi confrontandoli con i loro opposti per chiarire cosa significhino, ad esempio, "Assicurati di utilizzare il principio della piccolezza».

Ci auguriamo che questo articolo ti inviti a utilizzare i principi suggeriti per la costruzione di applicazioni moderne, che garantiranno un approccio unificato al design nel contesto di un stack tecnologico in continua crescita.

Applicando questi principi, scoprirai di seguire le ultime tendenze nello sviluppo software, incluso l'approccio DevOps allo sviluppo e alla consegna delle applicazioni, all'uso di container (ad esempio, Docker) e framework per l'orchestrazione dei container (ad esempio, Kubernetes), e all'uso di microservizi (inclusa l'Architettura a Microservizi NGINX e architettura di rete per applicazioni basate su microservizi.

Che cos'è un'applicazione moderna?

Applicazioni moderne? Stack moderno? Cosa significa esattamente "moderno"?

La maggior parte degli sviluppatori ha solo una comprensione generale di cosa componga un'applicazione moderna, quindi è necessario fornire una definizione chiara di questo concetto.

Un'applicazione moderna supporta più client, che si tratti di un'interfaccia utente realizzata con la libreria JavaScript React, di un'app mobile per Android o iOS, o di un'applicazione che si connette a un'altra tramite API. Un'applicazione moderna implica la presenza di un numero indefinito di client per cui fornisce dati o servizi.

Un'applicazione moderna offre un'API per accedere ai dati e ai servizi richiesti. L'API deve essere invariabile e costante, piuttosto che scritta specificamente per una richiesta proveniente da un determinato client. L'API è accessibile via HTTP(S) e fornisce accesso a tutte le funzionalità presenti nell'interfaccia grafica o nella CLI.

I dati devono essere disponibili in un formato comune e compatibile, come JSON. L'API fornisce oggetti e servizi in una forma chiara e organizzata; ad esempio, un'API RESTful o GraphQL offre 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 applicazioni con interfacce HTTP e punti finali API chiari. L'approccio scelto permetterà alla tua applicazione di ricevere e inviare dati in formato JSON senza difficoltà. In altre parole, lo stack moderno è conforme agli elementi dell'App a Dodici Fattori. microservizi.

Le versioni più popolari di questo tipo di stack si basano su Java, Python, Node, Ruby, PHP e Go. L'Architettura a Microservizi NGINX rappresenta un esempio di stack moderno, implementato in ciascuno dei linguaggi menzionati.

Si prega di notare che non promuoviamo esclusivamente un approccio microservizi. Molti di voi lavorano con monoliti che devono evolversi, mentre altri affrontano applicazioni SOA che si espandono e si sviluppano per diventare applicazioni microservizi. Altri stanno implementando applicazioni senza server, mentre alcuni integrano combinazioni di quanto sopra. I principi esposti nell'articolo si applicano a ciascuno di questi sistemi con alcune lievi modifiche.

Principi

Ora che abbiamo raggiunto una comprensione comune su cosa siano le applicazioni moderne e lo stack moderno, è tempo di esplorare i principi architettonici e di sviluppo che vi saranno di grande aiuto nello sviluppo, nell'implementazione e nel supporto di un'applicazione moderna.

Uno dei principi è "creare piccole applicazioni"; chiamiamolo semplicemente il principio della piccolezza. Esistono applicazioni incredibilmente complesse, composte da un gran numero di componenti mobili. A sua volta, costruire un'applicazione da piccoli componenti discreti semplifica la sua progettazione, manutenzione e funzionalità complessiva. (Nota che abbiamo detto «semplifica», e non «rende semplice»).

Il secondo principio consiste nel fatto che possiamo aumentare la produttività degli sviluppatori, aiutandoli a concentrarsi sulle funzionalità che stanno sviluppando, liberandoli al contempo dalle preoccupazioni riguardanti l'infrastruttura e il CI/CD durante l'implementazione. Quindi, in breve, il nostro approccio è incentrato sugli sviluppatori..

Infine, tutto ciò che riguarda la tua applicazione deve essere connesso in rete. Negli ultimi 20 anni, abbiamo fatto grandi progressi verso un futuro in 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'applicazione della logica di rete nell'architettura presenta vantaggi significativi che si abbinano bene con il principio della piccolezza e il concetto di approccio, incentrato sugli sviluppatori..

Se terrete a mente i principi elencati durante lo sviluppo e l'implementazione dell'applicazione, avrete un indiscutibile vantaggio nello sviluppo e nella consegna del vostro prodotto.

Esaminiamo più da vicino questi tre principi.

Principio della piccolezza

È difficile per il cervello umano elaborare contemporaneamente una grande quantità di informazioni. In psicologia, il termine carico cognitivo descrive la quantità totale di sforzi mentali necessari per mantenere le informazioni nella memoria. Ridurre il carico cognitivo sugli sviluppatori è una priorità, in quanto consente loro di concentrarsi sulla risoluzione dei problemi invece di dover mantenere in mente un modello complesso dell'intera applicazione e delle funzionalità in fase di sviluppo.

Principi di sviluppo delle moderne applicazioni da NGINX. Parte 1

Le applicazioni vengono decomposte per i seguenti motivi:

  • Riduzione del carico cognitivo sugli sviluppatori;
  • Accelerazione e semplificazione dei test;
  • Consegna rapida delle modifiche all'applicazione.


Esistono diversi modi per ridurre il carico cognitivo sugli sviluppatori, ed è qui che entra in gioco il principio della piccolezza.

Quindi, tre modi per ridurre il carico cognitivo:

  1. Ridurre i tempi che devono essere presi in considerazione durante lo sviluppo di una nuova funzione: più breve è il periodo, minore è il carico cognitivo.
  2. Ridurre il numero di righe di codice su cui si lavora contemporaneamente: meno codice significa meno lavoro.
  3. Semplificare il processo di apportare modifiche incrementali all'applicazione.

Riduzione dei tempi di sviluppo

Torniamo ai tempi in cui la metodologia waterfall era lo standard per il processo di sviluppo, e i tempi di sei mesi a due anni per lo sviluppo o l'aggiornamento di un'applicazione erano comuni. In genere, gli ingegneri leggevano prima i documenti pertinenti, come il documento sui requisiti del prodotto (PRD), il documento di riferimento del sistema (SRD), il piano di architettura e iniziavano a combinare tutti questi elementi in un unico modello cognitivo, secondo il quale scrivevano codice. Man mano che i requisiti e, di conseguenza, l'architettura cambiavano, era necessario fare uno sforzo considerevole per informare l'intero team degli aggiornamenti del modello cognitivo. Questo approccio, nel peggiore dei casi, poteva semplicemente paralizzare il lavoro.

Il cambiamento più significativo nel processo di sviluppo delle applicazioni è stata l'implementazione della metodologia agile. Una delle caratteristiche fondamentali della metodologia agile è lo sviluppo iterativo. Questo, a sua volta, riduce il carico cognitivo degli ingegneri. Invece di richiedere al team di sviluppatori di realizzare un'applicazione in un lungo ciclo, agile l'approccio consente di concentrarsi su piccole porzioni di codice che possono essere rapidamente testate e distribuite, ricevendo anche feedback. Il carico cognitivo dell'applicazione è passato da un lasso di tempo di sei mesi a due anni, considerando l'enorme quantità di specifiche, a due settimane per l'aggiunta o la modifica di funzionalità, focalizzandosi su una comprensione più sfumata di un'applicazione complessa.

Spostare l'attenzione da applicazioni massicce a piccole funzioni specifiche, che possono essere completate in uno sprint di due settimane, con uno sguardo avanti che non contempla più di una funzione del prossimo sprint, rappresenta un cambiamento significativo. Questo ha consentito di aumentare la produttività dello 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 originale, 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 consiste nell'alleggerire la base di codice. Di norma, le applicazioni moderne sono massicce: un'applicazione aziendale affidabile può essere composta da migliaia di file e centinaia di migliaia di righe di codice. A seconda di come sono organizzati i file, le relazioni e le dipendenze tra codici e file possono essere più o meno evidenti. Anche il debug dell'esecuzione del codice può presentare delle difficoltà, a seconda delle librerie utilizzate e di quanto bene gli strumenti di debug separano librerie/pacchetti/moduli dal codice utente.

Costruire un modello mentale funzionale del codice dell'applicazione può richiedere un tempo considerevole, imponendo nuovamente un carico cognitivo significativo allo sviluppatore. Questo è particolarmente vero per le basi di codice monolitiche, dove c'è una grande quantità di codice e l'interazione tra i componenti funzionali non è ben definita, mentre le separazioni tra gli oggetti di attenzione sono spesso sfocate, poiché non vengono rispettati i confini funzionali.

Uno dei modi più efficaci per ridurre il carico cognitivo degli ingegneri è passare a un'architettura a microservizi. In un approccio a microservizi, ogni servizio si concentra su un insieme specifico di funzioni; il significato del servizio è di solito ben definito e comprensibile. I confini del servizio sono chiari: ricordate 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 è generalmente limitata a pochi servizi utente e a diversi servizi del fornitore, che utilizzano chiamate API semplici e pulite, ad esempio tramite REST. Questo riduce notevolmente il carico cognitivo sull'ingegnere. La sfida più complessa è comprendere il modello di interazione tra i servizi e come avvengono cose come le transazioni tra più servizi. In definitiva, l'uso dei microservizi riduce il carico cognitivo, diminuendo la quantità di codice, delineando confini chiari per i servizi e garantendo una comprensione delle relazioni tra utenti e fornitori.

Piccole modifiche incrementali

L'ultimo elemento del principio piccole cose è la gestione delle modifiche. Una particolare tentazione per gli sviluppatori è esaminare il codice sorgente (anche, forse, il proprio codice più vecchio) e dichiarare: "Questo è spazzatura, dobbiamo riscrivere tutto." A volte questa è la scelta giusta, ma altre volte no. Impone al team di sviluppatori il peso di un cambiamento globale del modello, il che, a sua volta, porta a un'alta carico cognitivo. È meglio che gli ingegneri si concentrino su modifiche che possono apportare durante lo sprint, in modo da poter rilasciare le funzionalità necessarie in modo tempestivo, anche se in modo graduale. Il prodotto finale dovrebbe somigliare a ciò che era stato pianificato, ma con alcune modifiche e test per soddisfare le esigenze del cliente.

Quando si riscrive grandi parti di codice, a volte risulta impossibile effettuare rapidamente la consegna delle modifiche, poiché qui entrano in gioco altre dipendenze del sistema. Per controllare il flusso delle modifiche, è possibile utilizzare la disattivazione delle funzionalità (feature hiding). In pratica, questo significa che la funzionalità esiste in produzione, ma non è accessibile tramite impostazioni delle variabili di ambiente (env-var) o qualche altro meccanismo di configurazione. Se il codice ha superato tutti i processi di qualità, può trovarsi in produzione in uno stato nascosto. Tuttavia, questa strategia funziona solo se la funzione verrà infine attivata. In caso contrario, si limiterà a ingombrare il codice e a creare un carico cognitivo che lo sviluppatore dovrà gestire per lavorare in modo produttivo. La gestione delle modifiche e le modifiche incrementali aiutano a mantenere il carico cognitivo degli sviluppatori su un livello gestibile.

Gli ingegneri devono affrontare molte difficoltà anche quando si tratta di implementare semplici funzionalità aggiuntive. È saggio da parte della dirigenza ridurre il carico superfluo sul team, affinché possa concentrarsi sugli elementi chiave delle funzionalità. Ci sono tre cose che puoi fare per supportare il tuo team di sviluppo:

  1. Utilizzare una metodologia agile, per limitare le scadenze entro le quali il team deve concentrarsi sulle funzioni chiave.
  2. Implementare la propria applicazione come un insieme di microservizi. Questo limiterà il numero di funzionalità da implementare e rafforzerà i confini che riducono il carico cognitivo durante il lavoro.
  3. Preferire modifiche incrementali a quelle grandi e ingombranti, apportando piccole modifiche al codice. Utilizzare l'hiding delle funzionalità per implementare cambiamenti, anche se non saranno visibili subito dopo l'aggiunta.

Se applicherai il principio della piccolezza nel tuo lavoro, il tuo team sarà molto più felice, si concentrerà meglio sull'implementazione delle funzionalità necessarie e avrà maggiori probabilità di rilasciare rapidamente cambiamenti di qualità. Ciò non significa, però, che il lavoro non possa diventare complesso; talvolta, al contrario, l'implementazione di nuove funzionalità richiede modifiche a diversi servizi e questo processo può essere più difficile rispetto a un'architettura monolitica. In ogni caso, i vantaggi derivanti dall'applicazione dell'approccio della piccolezza ne valgono la pena.

Fine della prima parte.

Presto pubblicheremo la seconda parte della traduzione, ma ora attendiamo i vostri commenti e vi invitiamo a giorno delle porte aperte, che si terrà oggi alle 20.00.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster