Scroll Top
Via Antonio Amato, 20/22 84131 Salerno (SA)

Clean Code nei framework front-end

clean code

(articolo redatto da Gaetano De Pascale)

Il panorama dello sviluppo front-end è in costante evoluzione, alimentato dalla crescente complessità delle applicazioni web moderne e dalla continua necessità di performance e velocità. In questo contesto dinamico, la scrittura di codice pulito, manutenibile e riutilizzabile, è diventata una priorità fondamentale. La vitalità ed il successo di un’applicazione web si riflette non solo nella sua funzionalità, ma anche nella qualità del codice che la supporta.

Sfide del moderno sviluppo web

Con l’avvento di framework potenti come Angular, React (e mi fermo ai due più famosi ma potrei citarne almeno 10 di discreto successo), la capacità di costruire UI/UX sofisticate ha raggiunto nuove vette. Tuttavia, questa crescita esponenziale ha portato con sé una complessità senza precedenti. Applicazioni che in passato erano relativamente semplici, ora richiedono soluzioni scalabili e manutenibili per far fronte alle sfide del moderno sviluppo web.

  • La manutenibilità diventa cruciale quando si pensa a come l’applicazione evolverà nel tempo. Un codice ben strutturato, che aderisce ai principi SOLID e utilizza design pattern efficaci, offre la flessibilità necessaria per apportare modifiche senza generare effetti a catena indesiderati. La manutenibilità garantisce una gestione agevole del codice nel corso del tempo, promuovendo la longevità e la facilità di sviluppo.
  • La scalabilità, d’altra parte, è cruciale per far fronte all’aumento di traffico e complessità. Un’applicazione front-end ben scalabile può gestire efficacemente una crescita significativa degli utenti e delle funzionalità senza compromettere le performance. La progettazione di codice pulito gioca un ruolo centrale nella realizzazione di applicazioni che possono espandersi in modo armonioso all’aumentare delle esigenze.
  • Le performance sono il terzo pilastro essenziale. Un’applicazione front-end deve essere reattiva e veloce, fornendo un’esperienza utente fluida. Un codice ben ottimizzato, che riduce al minimo le richieste di rete ed il carico di rendering, contribuisce in modo significativo al successo di un’applicazione. L’attenzione alla performance non solo migliora l’esperienza dell’utente, ma può anche influenzare il posizionamento nei motori di ricerca, sottolineando l’importanza di un approccio oculato alla scrittura del codice.

In questo scenario complesso e in continua evoluzione, il concetto di “Clean Code” emerge come un fondamentale pilastro per il successo. Scrivere codice pulito e organizzato non è solo una questione di estetica, ma una strategia di lungo termine per affrontare le sfide dello sviluppo front-end moderno. Una base solida di principi SOLID, design pattern appropriati, HTML semantico e CSS ben strutturato costituiscono la fondamenta per applicazioni front-end di successo.

Principi SOLID per il Codice Modulare e Manutenibile

Una delle fondamenta per scrivere codice pulito (non solo nei framework front-end) è l’applicazione dei principi SOLID. Questi principi, introdotti da Robert C. Martin, forniscono linee guida chiare per la progettazione di codice pulito e modulare. Abbiamo già trattato questo argomento in altri articoli più in dettaglio, e per un maggiore approfondimento rimandiamo direttamente ad una lettura di quanto già scritto:

Best Practices

Struttura e Organizzazione dei Componenti

  • Single Responsibility Principle (SRP): Mantieni i tuoi componenti concentrati su una singola responsabilità. Se un componente diventa troppo grande, considera la possibilità di suddividerlo in pezzi più piccoli e gestibili.
  • Separazione delle responsabilità: Separa i componenti in due categorie: componenti contenitore (responsabili dei dati e della logica) e componenti di presentazione (orientati al rendering). Questa separazione migliora la chiarezza del codice e la riutilizzabilità.
  • Struttura delle Cartelle: Organizza i tuoi file in una struttura logica di cartelle. Raggruppa i componenti correlati e considera l’uso di directory come components, containers e utils per mantenere l’ordine.
    Ad esempio, anche avere un’unica cartella per gli stili della nostra applicazione

styles/
header.css
footer.css
nav.css
buttons.css
cards.css

con tanti file può creare confusione e rendere più difficoltoso capire la struttura e l’obiettivo di ogni singolo elemento.

Preferiamo sempre un’organizzazione più intuitiva:

styles/

layout/

header.css

footer.css

nav.css

base/

cards.css

bootstrap-overrides/

buttons.css

Nomi descrittivi

  • Componenti: Scegli nomi di componenti che rappresentino accuratamente il loro scopo o ruolo nell’applicazione. Usa sostantivi o frasi di sostantivi descrittivi che comunicano chiaramente cosa fa il componente.
  • Variabili e Funzioni: Opta per nomi di variabili e funzioni che spieghino il loro scopo o i dati che contengono/manipolano. Usa camelCase per le variabili e lettere minuscole per le funzioni.
  • File e Directory: Nomenclatura dei file e delle directory in modo da rifletterne i contenuti. Usa lettere minuscole, trattini e underscore per migliorare la leggibilità.
  • Props e State: Quando si passano props o si definisce lo stato del componente, attribuisci loro nomi che ne indicano lo scopo e i dati che contengono.
  • Event Handling: Nella definizione degli handler, utilizza nomi che descrivano l’azione che compiono o l’evento che gestiscono.

Formattazione Coerente

  • Indentazione: Usa un’indentazione coerente per ciascun livello di nidificazione. Una scelta comune è utilizzare due o quattro spazi per ciascun livello. Scegli uno stile e attieniti ad esso per l’intero progetto.
  • Posizionamento delle Parentesi Graffe: Posiziona le parentesi di apertura sulla stessa linea del blocco a cui sono associate. Questa è una pratica comune in JavaScript.
  • Spaziatura e Formattazione: Usa una spaziatura coerente intorno agli operatori, all’interno degli oggetti letterali e prima/dopo le parentesi. Aggiungi spazi dopo le virgole e i due punti.
  • Lunghezza delle Linee: Cerca di mantenere le linee ragionevolmente corte (solitamente intorno a 80-100 caratteri) per migliorare la leggibilità del codice. Se una linea è troppo lunga, considera la possibilità di suddividerla in più righe.
  • Lunghezza dei componenti e delle Funzioni: Cerca di evitare una classe faccia troppe cose, considera di spezzarla in più parti, e cerca di fare in modo che la lunghezza di una funzione non superi mai quella dello schermo.
  • Nomenclatura Coerente: Utilizza convenzioni di denominazione coerenti per variabili, funzioni, componenti e altri identificatori. Scegli uno stile di denominazione (camelCase, PascalCase, ecc.) e applicalo uniformemente.
  • Organizzazione degli Import: Mantieni ordinati e raggruppati logicamente gli import. Puoi utilizzare strumenti come ESLint o Prettier per formattare automaticamente gli import.
  • Allineamento del Codice: Allinea verticalmente blocchi di codice simili per una migliore raggruppamento visivo e chiarezza.
  • Commenti: Non riempire il codice di commenti, ma cerca di renderlo sempre quanto più autoesplicativo applicando le altre regole già descritte. Usa commenti su una sola linea (//) per spiegazioni brevi e commenti su più linee (/* */) per spiegazioni più lunghe o commenti a blocco.

Evitare Numeri e Stringhe Magiche

  • Sostituisci i “numeri magici” e le “stringhe magiche” con costanti o variabili per migliorare la manutenibilità del codice e ridurre il rischio di errori.

Destructuring

  • Utilizza la destructuring per estrarre elementi individuali da strutture di dati come array, oggetti o tuple e assegnarli a variabili in modo più conciso e intuitivo.

Evita Ternari Nidificati

  • Evita di annidare troppo profondamente gli operatori ternari, poiché ciò può rendere il codice difficile da seguire. Considera l’uso di istruzioni if o la scomposizione della logica complessa in funzioni separate.

Commenti e Documentazione

  • Utilizza i commenti per spiegare logiche complesse, intenti o decisioni nel tuo codice. Tuttavia, cerca di scrivere codice autoesplicativo che richieda un minimo di commenti.

Riuso e Modularizzazione

  • Riusa il codice creando componenti riutilizzabili e funzioni di utilità. Ciò riduce la duplicazione del codice e rende la base del codice più manutenibile.

Gestione dello Stato

  • Utilizza soluzioni di gestione dello stato appropriate per la complessità della tua applicazione e i requisiti specifici del progetto.Gestione degli Errori
  • Implementa una gestione degli errori adeguata, includendo gli error boundaries e blocchi try-catch per affrontare errori imprevisti.

Design Pattern

Prima di mostrare alcuni dei principali pattern da utilizzare nello sviluppo front-end è necessario definire cosa sia un design pattern.

Possiamo definirli, senza addentrarci in definizioni complesse, come soluzioni ricorrenti e già collaudate a problemi comuni che si incontrano durante lo sviluppo. Rappresentano, infatti, un insieme di convenzioni o regole per affrontare nello stesso modo le stesse tipologie di problemi senza dover ogni volte riscrivere e reinventare la ruota. Una delle parole chiave infatti è riuso. Un’ulteriore vantaggio che porta l’applicazione dei design pattern è l’organizzazione del codice che viene facilmente riconosciuta da altri sviluppatori che possono, così, collaborare senza problemi.

Non pretendiamo di parlare di tutti i design pattern in questo articolo, ma vogliamo portare solo due esempi applicati al mondo front-end.

MVC – Model View Controller

È un design pattern architetturale che suddivide un’applicazione in tre componenti principali: Model (Modello), View (Vista) e Controller. Questo design pattern aiuta a organizzare e strutturare il codice in modo da separare le responsabilità e facilitare la manutenibilità del software.

In Angular, il pattern MVC è implementato attraverso il concetto di MVVM (Model-View-ViewModel). Tuttavia, la distinzione tra Model, View e Controller è ancora chiaramente presente.

1. Model (Modello)

Il Model rappresenta i dati e la logica di business dell’applicazione. Nei progetti Angular, il Model può essere rappresentato da classi TypeScript che definiscono la struttura e il comportamento dei dati.

 2.View (Vista)

La View è responsabile di mostrare i dati all’utente e di rispondere agli input utente. In Angular, la View è rappresentata principalmente dai template HTML. La View non contiene logica di business, ma comunica con il Controller attraverso eventi.

3.Controller (Controllore)

Il Controller gestisce la logica di business e funge da intermediario tra il Model e la View.

In Angular, il Controller è implementato attraverso i componenti.

I componenti contengono metodi e proprietà che gestiscono la logica di business e interagiscono con il Model.

In questo esempio semplificato, UserComponent è il Controller che gestisce il Modello (User) e interagisce con la Vista attraverso il template HTML. Angular fornisce un sistema di dependency injection che facilita l’iniezione del Model nei componenti, creando così una chiara separazione tra le responsabilità.

In sintesi, Angular adotta e adatta il pattern MVC attraverso i componenti, i template e i servizi, fornendo un’architettura chiara e organizzata per lo sviluppo di applicazioni front-end scalabili e manutenibili.

Flux

Il pattern Flux è un design pattern architetturale introdotto da Facebook per gestire lo stato dell’applicazione in modo predittivo e mantenibile, specialmente in applicazioni React. Il suo obiettivo principale è semplificare la gestione dello stato e la gestione degli aggiornamenti dell’interfaccia utente, fornendo un flusso unidirezionale dei dati.

1. Actions (Azioni)

Le azioni rappresentano gli eventi o i cambiamenti nello stato dell’applicazione. In React, le azioni sono oggetti che contengono un tipo e dati associati. Le azioni vengono innescate da eventi nell’interfaccia utente o da richieste asincrone.

2. Dispatcher (Dispatcher)

Il Dispatcher è un hub centrale che riceve tutte le azioni e le inoltra agli store. È un singleton che gestisce il flusso delle azioni all’interno dell’applicazione.

3. Stores (Memorie)

Gli stores contengono lo stato dell’applicazione e la logica per gestirlo. Possono registrarsi presso il Dispatcher per ricevere azioni e aggiornare il proprio stato. Rilanciano un evento quando il loro stato cambia, notificando le componenti interessate

4. Views (Viste)

Le viste (o componenti React) rappresentano l’interfaccia utente. Agiscono come osservatori sugli stores e vengono aggiornate quando lo stato cambia. Inviano azioni al Dispatcher quando l’utente interagisce con l’interfaccia utente.

Performance: Un Altro Pilastro Fondamentale

Immagina di costruire una strada attraverso una città. Se la strada è ben progettata, senza ostacoli e con segnaletica chiara, i veicoli possono muoversi agevolmente e raggiungere la destinazione più rapidamente. Analogamente, nel contesto dello sviluppo front-end, il Clean Code è come la progettazione di una strada ben ottimizzata, contribuendo in modo significativo alle performance dell’applicazione.

  1. Reattività e Velocità
    Il Clean Code promuove una struttura chiara e organizzata.
    Questo non solo facilita la comprensione del codice da parte degli sviluppatori, ma rende anche più agevole l’ottimizzazione delle performance. La leggibilità del codice è fondamentale per identificare e risolvere inefficienze.
    Un codice chiaro e ben strutturato permette agli sviluppatori di individuare rapidamente le aree che richiedono ottimizzazione.
  2. Riduzione delle Richieste di Rete
    Un Clean Code può contribuire a ridurre il carico di rete, un aspetto critico per le performance front-end. Strutture ben progettate possono minimizzare la quantità di dati trasferiti tra il server e il client.
    L’uso efficiente delle risorse, come la compressione dei file e la gestione delle cache, è più agevole quando il codice è pulito e segue le migliori pratiche.
  3. Ottimizzazione del Carico di Rendering
    Un codice ben strutturato facilita l’ottimizzazione del processo di rendering dell’interfaccia utente. Componenti organizzati e riutilizzabili consentono di evitare il rendering eccessivo e migliorano la gestione delle risorse.
    L’attenzione al Clean Code durante lo sviluppo delle interfacce utente aiuta a evitare il sovraccarico di operazioni costose durante il rendering.
  4. Influenza sul Posizionamento nei Motori di Ricerca
    Un’applicazione web veloce e reattiva è cruciale per l’esperienza dell’utente, e i motori di ricerca valorizzano questo aspetto. Google, ad esempio, tiene in considerazione la velocità di caricamento delle pagine come uno dei fattori di ranking.
    Il Clean Code contribuisce a un’ottimizzazione efficace, migliorando le performance e, di conseguenza, l’indicizzazione nei motori di ricerca.

Conclusioni

In conclusione, la scrittura di codice pulito non è solo una questione estetica, ma svolge un ruolo fondamentale nella creazione di applicazioni front-end che sono non solo funzionali ma anche facili da comprendere, manutenere e gestire in team. Seguire le best practice descritte contribuirà significativamente alla qualità complessiva del tuo codice.

Infine, l’utilizzo di strumenti di formattazione automatica può garantire che le pratiche di formattazione siano uniformi in tutto il progetto, riducendo così la possibilità di errori legati alla formattazione.


Se anche tu vuoi occuparti di importanti progetti di  sviluppo software
dai un’occhiata alle nostre opportunità di lavoro e conosciamoci subito!