AZIENDA

News & Eventi

Cosa succede nell’Hi-Tech, dove tutto cambia ogni giorno.

 - 26 febbraio 2021

In arrivo su Swift i costrutti async e await

Un altro passo verso la semplicità e la potenza per il linguaggio delle piattaforme Apple.

Una delle fonti principali di gioie e dolori di uno sviluppatore, sia esso di app mobile, di API o di
front end di varia natura, è lo sviluppo asincrono: eventi che vengo avviati in un preciso momento
ma dei quali non si conosce il termine.
Il caso tipico è quello delle chiamate di rete, sempre più presenti in app connesse e full online, che
si aggiornano ad ogni battito di ciglia. Lo strumento per eccellenza impiegato in Swift (e non solo)
per gestire l’asincronicità è la completion closure. Essa rappresenta una sequenza di istruzioni che
viene lasciata in sospeso e che verrà eseguita solamente nel momento in qui l’evento di cui si
attende la conclusione terminerà effettivamente.
L’utilizzo delle closure, oltre a frammentare il flusso logico del codice, diventa complesso e poco
comprensibile quando sono coinvolte più operazioni asincrone, quando vanno gestiti casi di errore
o quando diverse operazioni asincrone dipendono le une dalle altre.
Capita abbastanza di frequente di incontrare closure innestate le une nelle altre al fine di accodare
più operazioni dipendenti tra loro.

Definizione funzioni:

serviceCall(completion: (response) -> void)
downloadRawDataFromUrl(url, completion: (data) -> void)
decodeImage(data, completion: (image) -> void)
applyFilters(image, completion: (image) -> void)

Esecuzione codice:

serviceCall { (response)
	downloadRawDataFromUrl(response.url) { (rawData)
		decodeImage(rawData) { (image)
			applyFilters(image) { (result)
				completionClosure(result)
			}
		}
	}
}

Il codice è poco leggibile, poco mantenibile o riutilizzabile e difficile da modificare. L’utilizzo di
closure aumenta il rischio di retain cycle (condizioni nelle quali una o più risorse vengono
trattenute indefinitamente in memoria perché posseggono un riferimento forte tra loro che
genera un circolo non più deallocabile), è maggiormente prono a dimenticanze relative alla
chiamata di ritorno (return) per interrompere l’esecuzione dopo la chiamata alla completion
closure o viceversa.

E’ stata avanzata la proposta di una evoluzione di Swift atta a importare nel linguaggio i costrutti
async e await, già presenti in altri linguaggi: grazie ad essi sarebbe possibile scrivere codice
asincrono utilizzando medesimi controlli di flusso e sintassi di quello sincrono, senza la necessità di
abusare delle closure. Essi inoltre getterebbero le basi per altre evoluzioni molto interessanti,
come la gestione della concorrenza, della priorità e cancellazione dei task.
Per un confronto immediato, lo pseudo-codice presentato in precedenza se tutte le funzioni
chiamate fossero dichiarate come async potrebbe essere scritto come

response = await serviceCall()
rawData = await downloadRawDataFromUrl(response.url)
result = await applyFilters(decodeImage(rawData))

Il risultato è più leggibile e comprensibile, meno prono ad errori di varia natura. Await genera un
cosiddetto punto di sospensione opzionale, raggiunto il quale la funzione potrebbe cedere il
proprio thread in attesa di ottenere un risultato. Una volta ottenuto, l’esecuzione del codice
proseguirà normalmente, in maniera del tutto analoga a quanto avviene per le funzioni sincrone.
Non resta che da sperare che la proposta via bene accolta dalla community che regola e fa
evolvere Swift, per poterla avere a disposizione alla prossima release del linguaggio.

Fonte: https://github.com/apple/swift-evolution