Typescript e la programmazione procedurale/Scripting | Aulab

GUIDE PER ASPIRANTI PROGRAMMATORI

Typescript e la programmazione procedurale/Scripting

Lungo tutta la guida la conoscenza di TypeScript e del suo sistema di tipi sono state il fulcro della nostra trattazione. Ma, in fin dei conti, un linguaggio di programmazione è tanto efficace quanto è espressivo e ci permette di organizzare il codice in un modo che rappresenti e descriva la realtà del dominio in…

Lezione 27 / 30
Enza Neri
Immagine di copertina

Vuoi avviare una nuova carriera o fare un upgrade?

Trova il corso Digital & Tech più adatto a te nel nostro catalogo!

Lungo tutta la guida la conoscenza di TypeScript e del suo sistema di tipi sono state il fulcro della nostra trattazione. Ma, in fin dei conti, un linguaggio di programmazione è tanto efficace quanto è espressivo e ci permette di organizzare il codice in un modo che rappresenti e descriva la realtà del dominio in cui il nostro software opera. 

In queste discussioni finali vedremo come possiamo strutturare l’architettura del nostro codice secondo i principali paradigmi, partendo dal più semplice, nonché più vicino alla macchina: la programmazione procedurale, normalmente utilizzata nel cosiddetto scripting. Scrivere script significa essenzialmente scrivere degli elenchi di istruzioni per la macchina: ci concentriamo sul come fare le cose, passaggio per passaggio, organizzando le nostre istruzioni in modo tale che il risultato finale sia quello atteso. 

Generalmente, nello scripting si fa un uso abbastanza limitato o nullo della segregazione dei moduli, vale a dire che si tende a integrare il codice attraverso l’uso e la modifica di variabili, funzioni e oggetti globali

Questo è il campo in cui TypeScript ci tornerà meno utile. Come il nome stesso rivela, JavaScript nasce per essere un linguaggio di scripting, con cui animare il comportamento delle prime, semplicissime pagine web. Questo significa che la scala della nostra codebase è presumibilmente piccola e non abbiamo molto bisogno di tipizzare il nostro codice, perché le funzioni che definiamo sono sufficienti a farci comprendere il dominio in cui operiamo; non avremo nemmeno troppi problemi a modificare più volte tipi e valori delle nostre variabili. 

Eppure, già in uno scenario così semplice ed elastico, possiamo utilizzare TypeScript per chiarire cosa intendiamo fare con le nostre variabili e funzioni

Prendiamo ad esempio uno script che gestisce il dietro le quinte di una pagina web che rappresenta un contatore:

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>
  <title>Page Title</title>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
</head>
<body>
  <p>Count: <span id="counter">0</span></p>
  <button id="increment">Increment</button>
  <button id="reset">Reset</button>
  <script src='main.js'></script>
</body>
</html>
// recuperiamo e tipizziamo gli elementi della pagina
const incrementBtn = document.querySelector("#increment") as HTMLButtonElement;
const resetBtn = document.querySelector("#reset") as HTMLButtonElement;
const counterSpan = document.querySelector("#counter") as HTMLSpanElement;

// iniziamo lo stato a 0
let count = 0; // count: number

// attiviamo gli event handlers
incrementBtn.addEventListener("click", increment);
resetBtn.addEventListener("click", reset);

// definiamo le "funzioni" (in realtà sono procedure)
// che muteranno lo stato della nostra pagina
function increment(): void {
  count++;
  updateView();
}

function reset(): void {
  count = 0;
  updateView();
}

function updateView(): void {
  counterSpan.innerText = String(count);
}

In questo blocco di codice si notano diverse cose tipiche della programmazione procedurale

  • lo stato è rappresentato da variabili che vengono aggiornate durante l’esecuzione 
  • non ci sono livelli di confinamento per lo stato dell’applicazione 
  • le funzioni dichiarate sono in realtà procedure, nel senso che non fanno calcoli per restituire un risultato, ma eseguono istruzioni per aggiornare lo stato 

In un caso così semplice (o anche un po’ più complesso di così, ma non molto più complesso), l’organizzazione delle cose va più che bene; ben diverso è immaginare, ad esempio, di coinvolgere un backend che fornisca lo stato iniziale, gestire le logiche di caricamento e aggiornamento, eventuali errori di rete, eccetera.

In genere, in una codebase organizzata in modo esclusivamente procedurale, il codice tenderà a riempirsi di controlli a runtime (if, switch) e istruzioni di control flow (cicli, eccezioni, ecc) perché ogni operazione è in teoria disponibile ma, prima di effettuarla, bisognerà verificare che lo stato corrente sia sensato rispetto a tale operazione.

Cosa succederebbe se inizializzassimo lo stato a undefined mentre attendiamo la risposta dal server e qualcuno cliccasse il pulsante di reset o di incremento? Dovremmo inizializzare questi pulsanti in modo che siano disabilitati, e abilitarli manualmente all’arrivo dei dati. 

E se tentando di aggiornare il contatore ci fosse un errore di comunicazione con il server? Dovremmo di nuovo ricordarci di disattivare i pulsanti.

E se la nostra pagina avesse più di un contatore? Come faremmo a confinare i diversi contatori? 

Queste casistiche non sono così rare: le moderne web app gestiscono decine di logiche in contemporanea, tra interazione dell’utente, comunicazione con uno o più back-end, animazioni, validazioni, eccetera. 

La prima cosa da fare è assicurarsi di avere la possibilità di dividere e segregare le parti di codice che riguardano funzionalità diverse, e permettere a queste diverse parti di interagire secondo protocolli ben definiti. Ed è proprio in questo che TypeScript ci darà una gran mano.

Sei indeciso sul percorso? 💭

Parliamone! Scrivici su Whatsapp e risponderemo a tutte le tue domande per capire quale dei nostri corsi è il più adatto alle tue esigenze.

Oppure chiamaci al 800 128 626