Sono appassionato di tecnologia da tutta la vita. Ho iniziato con Turbo Pascal da bambino e da allora ho lavorato con sistemi embedded, sviluppo front-end/back-end e progetti di machine learning.
iOS/macOS è entrato in scena durante un breve corso universitario. Nel giro di un mese, avevo imparato un nuovo linguaggio e ottenuto uno stage in Readdle. Cinque anni dopo, sono diventato Principal Engineer. Nel frattempo, continuo a fare mentoring ai nuovi compagni di team, a partecipare ai colloqui e a sviluppare capacità di leadership per continuare a crescere.
Il mio percorso, da zero esperienza con le piattaforme Apple fino al ruolo che ricopro oggi, mi ha spinto a riflettere sul mio approccio all'apprendimento e a delineare le direzioni chiave che mi hanno aiutato a crescere. Credo che la mia esperienza possa essere preziosa per altri ingegneri che si sentono bloccati o incerti sui prossimi passi da compiere.
Ecco gli approcci e le risorse principali che hanno aiutato me e che potrebbero aiutare anche te.
Come i progetti personali hanno accelerato la mia crescita
Dopo aver raggiunto il livello middle, ho incontrato un plateau professionale. Avevo la sensazione di completare i task in modo rapido ed efficiente, risolvere bug senza problemi e avere una solida comprensione di come progettare l'architettura di nuove funzionalità. Ma non riuscivo davvero a capire cosa mi separasse dall’essere un vero Senior Engineer.
Il cambiamento è avvenuto gradualmente. Guardandomi indietro, mi sono reso conto che la differenza non stava in un grande progetto al lavoro o in una promozione. È stato tutto il tempo che avevo trascorso a programmare al di fuori del lavoro.
La sera e nei fine settimana, realizzavo piccoli progetti, a volte solo per divertimento, a volte per testare un'idea. Questi progetti personali mi hanno esposto a problemi reali al di fuori del mio ambito abituale. Quell'esperienza pratica si è tradotta direttamente nel mio lavoro e mi ha dato un vantaggio nell'affrontare problemi non familiari.
La lezione più importante è stata che la maggior parte delle competenze nello sviluppo software non sono legate a un singolo linguaggio o a una singola piattaforma. Ecco alcuni esempi:
- Anche se stai leggendo dell’architettura delle app iOS/macOS, probabilmente riconoscerai schemi simili nello sviluppo web o nei sistemi embedded.
- La conoscenza di Python nel contesto del machine learning può aiutarti a scrivere rapidamente lo script necessario per automatizzare i processi di CI in un dominio completamente diverso.
- Le basi dei sistemi operativi ti aiuteranno a comprendere intere classi di problemi in qualsiasi linguaggio di programmazione. Dopotutto, qualsiasi programma, indipendentemente dal linguaggio, interagisce in ultima analisi con il sistema operativo in modo simile.
- Uno dei primi libri che ho letto è stato Effective Java—un linguaggio che non uso da anni. Ma quel libro mi ha insegnato principi object-oriented che si applicano ovunque. È questo il tipo di conoscenza che resta.
- Se ti piace programmare, questi progetti personali non sembreranno lavoro. Nella mia esperienza, i migliori ingegneri sono quelli che scrivono codice perché amano costruire e imparare.
Modi per imparare qualsiasi cosa
Alcune persone sembrano imparare più in fretta di altre. Può trattarsi di un nuovo linguaggio di programmazione, di un pattern, di un'architettura o persino di qualcosa di completamente non legato allo sviluppo, come imparare a giocare a scacchi. Credo che sia perché imparare è di per sé una competenza—una meta-competenza che puoi allenare.
Riflettendo sul mio percorso di apprendimento, ho notato pattern ricorrenti nel modo in cui affronto nuovi argomenti. Penso che questo derivi dai miei anni a scuola e all'università, dove destreggiarmi tra più discipline ha spinto il mio cervello a ottimizzare pattern simili. Questo mi ha permesso di imparare più velocemente.
Ora ho un processo specifico per imparare qualcosa di nuovo. Non credo che questo processo sia rivoluzionario, ma mi ha permesso di restare concentrato e intenzionale sia nell’apprendimento sia nella crescita personale. In questa sezione ti accompagnerò attraverso le tre fasi del mio approccio all’apprendimento: Selezione, Strutturazione e Pratica.
Selezione
Una buona fonte di informazioni è un primo passo cruciale quando si impara una nuova competenza. Ecco alcuni consigli basati sulla mia esperienza:
- La maggior parte delle informazioni su qualsiasi argomento è disponibile gratuitamente. Raramente c’è bisogno di pagare corsi o lezioni, a meno che tu non sia assolutamente certo che il contenuto sia unico. Ma se sei agli inizi, non avrai ancora l’esperienza necessaria per distinguere tra intuizioni autentiche e materiale di scarsa qualità.
- Le risorse testuali sono di solito più concise e più facili da assimilare dei video, soprattutto se leggi velocemente. Con il tempo, ho imparato a scorrere rapidamente i contenuti e a filtrare le informazioni irrilevanti, cosa che è più difficile con i video.
- Con il tempo, ho sviluppato la capacità di scorrere rapidamente i contenuti e filtrare le informazioni irrilevanti, cosa che non è possibile con i materiali video perché il loro formato è lineare e richiede tempo. È anche più facile aggiungere un segnalibro o copiare un frammento di testo che cercare il momento giusto in un video.
- Le risorse in inglese sono molto più facili da trovare rispetto alle risorse in altre lingue, soprattutto quando si parla di programmazione e tecnologia. Perciò, saper leggere e capire velocemente l'inglese è indispensabile!
- Non saltare i classici. I libri consigliati ripetutamente (come Clean Code o Design Patterns) sono spesso ancora il miglior materiale disponibile.
- Consiglio anche di costruire la tua libreria personale di libri su argomenti diversi. In questo modo, avrai sempre materiale affidabile a portata di mano. Personalmente, tengo una semplice cartella sul mio computer.
Strutturazione
Una volta che ho raccolto alcune fonti solide, organizzo le informazioni. Questo processo include:
- Elaborare le fonti. Mentre leggo un libro o un articolo, evidenzio i punti chiave con dei segnalibri oppure li copio nei miei appunti per consultarli in futuro.
- Incrociare le informazioni. Soprattutto quando l'argomento è soggettivo, è molto importante confrontare diverse soluzioni e prospettive. Le informazioni che coincidono in diverse fonti differenti sono probabilmente vere. Quando le fonti sono in conflitto, di solito rimando la decisione finché non ho acquisito più esperienza personale con l’argomento. Più avanti, con una comprensione più profonda, posso scegliere l'approccio migliore.
- Centralizzare la conoscenza. Per analizzare tutte le informazioni ricevute e trovate, è necessario conservarle in un unico posto. Uso Obsidian per centralizzare la mia conoscenza. È gratuito e trovo il formato markdown molto pratico.
- Archiviare. Di solito salvo articoli e link utili in semplici elenchi markdown. Questo mi aiuta a trovare rapidamente una risorsa specifica senza dover scavare nella cronologia del browser. Inoltre, se in futuro torno sull'argomento, ho già salvato una buona base di partenza.
Pratica
Leggere non basta. Impari davvero solo quando costruisci qualcosa. Cerco di consolidare ogni argomento che studio creando piccoli progetti. Quando si tratta di programmazione, questo di solito significa creare una semplice applicazione che dimostri la mia capacità di applicare le competenze necessarie. La pratica rapida rivela subito anche eventuali lacune nella comprensione. Spesso pensavo di aver capito tutto ciò che mi serviva, per poi imbattermi in problemi inaspettati dopo appena 10 minuti di implementazione.
Un esempio che mi è rimasto impresso è l'apprendimento delle architetture UI. Quando ho studiato per la prima volta MVVM nel contesto dello sviluppo iOS, pensavo che l'architettura fosse semplice e lineare. Ma quando ho provato a costruire una semplice app to-do list, mi sono subito scontrato con una lacuna nelle mie conoscenze. Le risorse spiegavano come la View comunica con il ViewModel e come il ViewModel interagisce con il Model, ma nessuna affrontava chi dovesse creare cosa e in che modo!
La mia applicazione aveva una tabella che mostrava le attività correnti della to-do list. Dovevo creare un ViewModel separato per ogni attività? Oppure un unico ViewModel per l'intera tabella? E se avessi avuto bisogno di entrambi i ViewModel? Chi crea quale dei due? Queste domande mi hanno aperto la strada alla comprensione di come coordinare i componenti in architetture simili.
Più tardi, mentre lavoravo a PDF Expert, il nostro team ha deciso di provare a implementare MVVM. Sono riuscito a costruire l'architettura e ad aiutare a guidare il team nello sviluppo di quella funzionalità. È il tipo di esperienza che non avrei acquisito se prima non avessi costruito da solo quella piccola e disordinata app per le cose da fare.
I miei consigli sui progetti personali
- Trova ispirazione e un'idea. Di solito l'idea arriva prima, poi la collego a un obiettivo di apprendimento specifico. L’idea non deve essere unica né particolarmente utile, perché lo scopo principale è fare esperienza. Per esempio, potrei decidere di creare un'app per il monitoraggio delle abitudini. Da lì, posso scegliere di concentrarmi sull'architettura oppure usare questa idea per progettare una UI d'impatto con animazioni. Oppure forse devo costruire un server per quest'app? Potrebbe essere un'ottima opportunità per provare nuove tecnologie backend.
- Definisci cosa significa “finito”. Se provi a portare ogni progetto in produzione, devi dedicare molto tempo a ciascuno. Perciò, credo che tu debba definire i traguardi che vuoi raggiungere con ogni progetto.
- Il perfetto è nemico del buono. Se ti lasci assorbire troppo dal tentativo di trovare la soluzione “perfetta”, potresti perdere del tutto la motivazione.
- Riduci al minimo le attività non necessarie. La palette di colori esatta conta davvero in un'app pensata per insegnarti l'architettura? O il sistema di logging? I progetti più preziosi sono stati quelli concentrati su un unico obiettivo di apprendimento. Meno tempo passo sui dettagli a bassa priorità, più posso investire in ciò che conta davvero.
10 argomenti che hanno cambiato il mio modo di sviluppare software
Ecco 10 aree che ho esplorato da solo e che hanno avuto un impatto sulla mia carriera.

Architetture UI delle applicazioni
Qualsiasi ingegnere che abbia lavorato su progetti basati su interfacce utente conosce i classici schemi di organizzazione del codice. Chi non ha mai sentito parlare di MVC, MVP, MVVM? Nella mia esperienza, una semplice conoscenza teorica può darti la sicurezza per iniziare un nuovo progetto, ma senza esperienza pratica spesso crolla al primo segno di complessità.
Una volta pensavo di aver capito perfettamente come funziona MVVM, ma non avevo l’esperienza necessaria per provarlo davvero. Me ne sono reso conto quando ho provato a sviluppare una piccola applicazione MVVM. È diventato chiaro che avevo bisogno di coordinator e router per navigare e assemblare quel miscuglio di classi in una struttura coerente. Quell’esperienza mi ha insegnato una lezione fondamentale: non esiste un’architettura valida per tutto. Un'architettura che funziona bene in un progetto (o persino in una sola schermata) potrebbe essere inadatta altrove.
Design pattern
Chiunque abbia affrontato colloqui da sviluppatore si è probabilmente imbattuto in domande sui design pattern. Molti ingegneri sembrano riconoscere certi pattern in teoria, ma fanno fatica ad applicarli nella pratica. Il modo più semplice per colmare quel divario è costruire un piccolo progetto incentrato sull’implementazione di un pattern specifico.
Il libro originale usa spesso un editor di testo come esempio. Nella mia esperienza, editor di documenti di vario tipo richiedono l'uso di molti design pattern. Può trattarsi di un editor di testo, di un editor di immagini o persino di un programma per creare diagrammi.
Testing
Il testing del codice è una pietra angolare delle codebase stabili. E anche se l'idea sembra semplice – “basta scrivere test!” – scrivere test utili è spesso tutt'altro che banale.
La sfida principale è che mantenere i test consuma risorse del team. Se devi riscrivere i test dopo ogni refactoring del codice, il valore complessivo di quei test diventa discutibile. Questo concetto è noto come Test Fragility e, nella mia esperienza, non è conosciuto quanto dovrebbe. Puoi approfondire la teoria del testing, per esempio, in questo libro.
Una forte attenzione al testing influisce anche sulla qualità del codice. In generale, il codice scritto pensando al testing sarà più modulare ed esporrà un'API più pulita e più semplice. È facile provare il testing nella pratica – basta integrare i test in un progetto esistente o avviarne uno nuovo con un focus sulla scrittura dei test.
Algoritmi e strutture dati
Conoscere gli algoritmi non è un requisito imprescindibile nello sviluppo software moderno. Molte aziende includono ancora sfide algoritmiche nei colloqui, anche se queste competenze potrebbero non servire nel lavoro quotidiano. Tuttavia, credo che valga la pena investire tempo nello studio degli algoritmi perché è divertente e interessante. Inoltre, oggi puoi esplorare questi argomenti in modo interattivo tramite piattaforme come LeetCode.
Se dovessi mai avere la possibilità di partecipare a competizioni di programmazione algoritmica come ACM ICPC, ti consiglio vivamente di provarci. Anche se questa conoscenza all’inizio non sembra direttamente utile, le tecniche di ottimizzazione del codice possono essere applicate a qualsiasi progetto, e partecipare a una competizione di squadra è un’esperienza che probabilmente ricorderai con piacere.
Multithreading
Il multithreading è un argomento affascinante. Puoi passare anni a scrivere codice senza comprendere nemmeno i concetti di base. Ogni sviluppatore sa che bloccare il thread principale congelerà l'app. Ma se qualcosa va storto, solo gli sviluppatori che comprendono davvero il codice multithread e riescono a visualizzare l'intera sequenza temporale degli eventi possono diagnosticare quei bug sfuggenti, quasi fantasma.
Secondo me, comprendere le primitive di sincronizzazione, i thread e le conseguenze del trascurare questi concetti è uno dei fattori chiave che separano uno sviluppatore mid-level da uno Senior. Per capire i concetti di base, consiglio il libro gratuito The Little Book of Semaphores.
Per fare pratica, puoi provare a scrivere un programma che esegua un'elaborazione pesante in background e sincronizzi i risultati con la UI, soprattutto se il lavoro in background stesso coinvolge più thread. Simulare processi fisici può essere un ottimo punto di partenza per questo tipo di progetto.
Programmazione grafica
I processori grafici sono una delle poche parti di un computer con cui la maggior parte degli sviluppatori raramente deve interagire direttamente. Per la maggior parte delle applicazioni, il rendering della UI avviene sul CPU oppure è astratto rispetto al dispositivo GPU reale, quindi non devi nemmeno pensarci. Ma quando il numero di elementi sullo schermo cresce abbastanza e le astrazioni di alto livello non riescono più a stare al passo con i frame rate richiesti, allora devi approfondire. Comprendere i problemi che le GPU sono progettate per risolvere, così come la capacità di “spiegare” loro che cosa deve essere renderizzato, può aiutarti a identificare rapidamente soluzioni in situazioni simili.
Un progetto classico per imparare la programmazione grafica è costruire un motore di gioco. Se ami i videogiochi come me, probabilmente ti sei chiesto come vengono programmati. Online ci sono tantissime risorse per imparare Metal, DirectX, OpenGL o Vulkan. Non aspettarti però che il tuo progetto diventi il prossimo Unreal Engine. Ma se riesci ad arrivare al punto in cui hai costruito un piccolo gioco che gira sul tuo motore, ti garantisco che incontrerai sfide affascinanti e acquisirai conoscenze preziose.
Programmazione embedded
Quando ho scoperto per la prima volta che anche i più piccoli dispositivi elettronici intorno a noi eseguono i propri programmi e processori, ne sono rimasto subito affascinato e ho voluto provare a costruire qualcosa di simile. Tuttavia, lo sviluppo per microprocessori comporta molte limitazioni. Questi sistemi di solito hanno meno di 128 kilobyte di memoria e l'allocazione dinamica della memoria in genere è fuori discussione.
Scrivere ed eseguire il debug di codice embedded presenta molte sfide. Ma, come risultato, puoi vedere il tuo codice prendere vita nel mondo reale. Anche solo far lampeggiare un semplice LED per me è sembrato un grande traguardo. Capire come funzionano i microcontrollori è un primo passo importante verso la comprensione di come funzionano le CPU moderne e i sistemi operativi. Quando lavori con dispositivi embedded, potresti perfino dover ricorrere all'assembly specifico della piattaforma (di solito ARM).
Oggi è più facile che mai iniziare con lo sviluppo embedded. Microcontrollori economici come la linea STM32 sono un ottimo punto di partenza, e molte schede pronte all'uso includono programmatori integrati che si collegano via USB. Le possibilità sono infinite, dall'illuminazione dinamica di una stanza fino alla creazione del tuo hub IoT smart home.
Disassemblatore
A volte, poter guardare un livello più in profondità nel proprio codice può essere preziosissimo. Per esempio, nello sviluppo per le piattaforme Apple, lavoriamo spesso con librerie Apple per lo più closed-source. Quando qualcosa non si comporta come previsto, di solito è necessario aprire una segnalazione tramite Feedback Assistant e aspettare (a volte per anni!) una risposta. Ma con l'aiuto di un disassemblatore, spesso puoi guardare sotto il cofano e capire come funziona davvero il codice closed-source.
Comprendere il codice assembly del tuo programma può essere utile anche nel contesto dell'ottimizzazione. Solo ispezionando il codice compilato puoi sapere davvero che cosa sta facendo il tuo codice. Personalmente, per questo scopo uso Hopper Disassembler su macOS.
Compilatori
Il mondo della programmazione ha i suoi “club segreti”. Se pensiamo alle persone i cui prodotti hanno l'impatto maggiore sul maggior numero di ingegneri, arriviamo inevitabilmente a chi costruisce i compilatori dietro ai nostri linguaggi di programmazione preferiti. Fino a quando non ho dedicato del tempo a studiare i compilatori in prima persona, questi programmi mi sembravano pura magia. Ma anche imparandone le basi, la nebbia della magia ancora non ti permette di cogliere fino in fondo la genialità di chi ha creato interi linguaggi di programmazione.
La buona notizia è che sull'argomento sono disponibili moltissime risorse e libri. Due dei miei preferiti sono Engineering a Compiler e, naturalmente, il classico Dragon Book. Puoi iniziare a esplorare lo sviluppo del tuo linguaggio di programmazione partendo dal tutorial Kaleidoscope di LLVM. Nello sviluppo software del “mondo reale”, a meno che tu non sia un compiler engineer, questa conoscenza può darti una comprensione molto più profonda del comportamento dei linguaggi e degli errori più oscuri. Inoltre, la maggior parte dei compilatori è open-source, il che ti permette di contribuire a progetti enormi e ad alto impatto. Per esempio, contribuire al repository di Swift aggiunge un valore significativo al portfolio di qualsiasi sviluppatore.
Fondamenti dei sistemi operativi
Se esistono progetti ancora più complessi dei compilatori, i sistemi operativi sono i primi che mi vengono in mente. Da sviluppatori che trascorrono la maggior parte del tempo lavorando al computer, è sorprendentemente facile dimenticare che un sistema operativo è solo un altro programma, come quelli che scriviamo noi stessi. Un enorme strato di astrazioni dall'hardware crea l'illusione che ogni programma in user space giri sul proprio processore con la propria memoria. Queste astrazioni sono così accurate che il codice scritto e compilato una volta può funzionare in modo affidabile su una grandissima varietà di configurazioni hardware.
Il libro Operating Systems: Three Easy Pieces è un ottimo punto di partenza per capire come funzionano i sistemi operativi. E se ti interessano nello specifico gli aspetti interni di iOS o macOS, ti consiglio la risorsa gratuita MacOS X and iOS Internals. Acquisire una comprensione di come funziona un sistema operativo colma il divario finale tra l'hardware e il codice che scriviamo. Per uno sviluppatore, questo significa avere un controllo e una comprensione quasi completi di ciò che accade quando il tuo programma viene eseguito.
Per concludere
Guardandomi indietro, non ho seguito un piano rigido. Ho semplicemente continuato a imparare, costruire e inseguire ciò che mi interessava. Quella curiosità si è trasformata in una carriera.
Se ti senti a tuo agio ma ti chiedi cosa venga dopo, prova ad ampliare i tuoi orizzonti. Esplora qualcosa di nuovo. Il tempo che investi nei progetti personali e nell'apprendimento darà frutti nel tempo, e i divari tra i livelli — Junior, Middle, Senior e Principal — inizieranno a ridursi più velocemente di quanto pensi.
C’è sempre altro da imparare. Ma con ogni progetto, ogni errore e ogni nuovo concetto, stai andando avanti. Continua a costruire.
— Andrii Zinoviev, Principal Product Engineer
Vuoi entrare a far parte del nostro team Engineering e avere un impatto su milioni di persone? Scopri le nostre posizioni aperte!
The Readdle Team