Nella prima parte di questo mini viaggio abbiamo visto un confronto fra gli ambienti di sviluppo, i componenti e i simulatori/emulatori utilizzabili per sviluppare per Android e iOS. In questo post parliamo di una delle cose più importanti (sembrerà strano ma è così :)) quando si scrive codice: il linguaggio di programmazione!

Objective C vs Java

Da profano prima di questa avventura avevo pensato:

Objective C è una estensione del C, io conosco java, conosco un po’ di C e C++ che ci vorrà a imparare Objective C! Ho imparato l’ereditarietà in JavaScript non mi spaventa più niente!

Ok, Objective C è una estensione del C ma del C che siamo abituati a vedere c’è proprio poco: le parentesi graffe, il punto e virgola, i tipi primitivi, l’if e il while. Vedendo un listato di codice Objective C ho avuto la stessa impressione che ho avuto a suo tempo davanti a una regular expression bella incasinata! Per capirsi per creare un oggetto Persona passando nome e cognome è necessario scrivere questo codice:

Persona *p = [[Persona alloc] initWithSurname: @"Rossi" name: @"Mario"];

A prima vista si notano almeno tre cose che mi hanno fatto impazzire:

  1. per creare una stringa è necessario usare una @, ok dopo un po’ ci si fa l’abitudine;
  2. per invocare un metodo su un oggetto non si usa la notazione oggetto.metodo(parametro) o oggetto->metodo(parametro) ma [oggetto metodo: parametro]. Questa notazione è dura da digerire per chi non l’ha mai vista soprattutto nel caso di chiamate a più metodi in cascata…;
  3. nel caso di metodi con più di un parametro tutti i parametri hanno una label (nell’esempio name: è la label del secondo parametro). Questa cosa può essere comoda visto che per simulare un comportamento analogo in Java è necessario scrivere un builder. Però all’inizio è dura entrare nel meccanismo e per scrivere ogni chiamata a un metodo c’è da pensarci per bene.

Una caratteristica interessante di Objective C (altrimenti sembro di parte) sono le property: invece di dover scrivere i getter e i setter basta scrivere un @synthesize. Quando si usa si può addirittura usare la notazione con il punto e scrivere persona.nome! Però i puristi non usano questa notazione con il punto, forse per non essere scambiati per javisti…

Linguaggi statici e dinamici

A prima vista Objective C potrebbe sembrare un linguaggio con typing statico, in realtà non lo è del tutto! Se si invoca un metodo che non esiste viene generato solo uno warning. Si potrebbe parlare per ore sulle differenze fra linguaggi statici e dinamici, ne ha parlato benissimo Paolo Perrotta in un talk a BetterSoftware, se avete tempo date un’occhiata al video. Personalmente faccio il tifo per quelli statici (qualcuno di voi forse l’aveva già intuito! :D). La comodità dell’autocomplete, di poter eseguire un refactoring e di sapere dove viene invocato un certo metodo (vi ricordate quei menu che mancano su Xcode?) non li baratterei mai con la possibilità di aggiungere metodi al volo e altre cose tipiche dei linguaggi non strong typed.

Una cosa che ancora non ho capito se amare o odiare è che nel caso di una chiamata di un metodo su un oggetto null (o nil come si definisce in Objective C) non succede niente, non viene lanciata nessuna eccezione. Può essere comodo per evitare di scrivere if di guardia, ma può rendere più complicata la fase di debug. Mettendo insieme questo e il fatto che Objective C non è strong typed si può eseguire tranquillamente una chiamata a un metodo non definito su un oggetto nil:

NSObject *obj = nil;
[obj metodoNonEsistente];

L’esecuzione di queste due righe di codice genera solo uno warning in compilazione, a runtime funziona tutto e non vengono sollevate eccezioni. Comodo? Dipende dai punti di vista!

Organizzazione delle classi: i package

I nomi delle classi in Objective C spesso iniziano con due lettere maiuscole, per esempio le classi che rappresentano stringhe e date sono rispettivamente NSString e NSDate. Queste due lettere identificano la libreria di appartenenza della classe, in questo caso NS sta per NeXTSTEP, sistema operativo sviluppato alla NeXT, azienda fondata da Steve Jobs nel periodo in cui non era alla Apple. Ma la domanda nasce spontanea: non potevano usare i package come nei linguaggi di programmazione moderni? La risposta è sconvolgente per chi ha sviluppato in un progetto con almeno 10 classi: non hanno usato i package perchè in Objective C non esistono! Per questo motivo è nata la comoda convenzione di mettere un prefisso di due caratteri che indica la libreria per evitare conflitti sui nomi…

Garbage collector C vs retain/release

Quando si inizia a sviluppare in Java (magari arrivando dal C/C++) una delle cose più affascinante è sicuramente il Garbage Collector. Niente più malloc e chiamate simili, niente più memory leak perchè pensa a tutto il Garbage Collector! L’entusiasmo iniziale svanisce quando si sviluppa lato server e c’è da capire come funziona il Garbage Collector nei dettagli perchè la ram non basta mai. A quel punto ci si imbatte in 1000 parametri da passare alla Java virtual machine, si scopre che il Garbage Collector blocca tutto e quello che sembrava una magia si trasforma in un incubo! 🙁

In Objective-C il Garbage Collector esiste ma solo se si sviluppa per Mac (e quindi non è utilizzabile su iOS). La gestione della memoria avviene in modo manuale, i due metodi fondamentali sono retain e release. Con retain si aumenta il retain count dell’oggetto, con release si diminuisce. Quando il retain count torna a zero la memoria viene automaticamente rilasciata. Semplice? Non troppo soprattutto quando si passano oggetti fra più metodi. Per aiutare lo sviluppatore è stato creato anche il metodo autorelease, invocando questo metodo in pratica l’oggetto sarà liberato al primo momento utile automaticamente. Questo argomento meriterebbe un post intero (o forse anche un libro!) e sicuramente non sono io la persona giusta per scriverlo…

A partire da iOS 5 è stato introdotto l’Automatic Reference Counting, se viene abilitato a livello di compilatore non c’è più bisogno di invocare manualmente retain e release. ARC è concettualmente diverso da un Garbage Collector: esegue un’analisi statica del codice e inserisce automaticamente retain e release dove necessario. Non so se i puristi dell’Objective-C usano questa feature, si potrebbe avere qualche byte che viene liberato con qualche millisecondo di ritardo e il sistema potrebbe perdere in reattività! 🙂

Insomma è utile il Garbage Collector o no? Secondo me la risposta è sicuramente si, c’è sicuramente una piccola perdita del controllo della memoria (il Garbage Collector parte più o meno quando vuole) ma il gioco vale sicuramente la candela.

Conclusioni

Siamo arrivati alla fine di questo viaggio, sono stato di parte? Un po’ si ma avrei potuto fare di peggio… Sicuramente iOS e Android sono due ottimi sistemi operativi, la diffusione e il numero di applicazioni sugli store parla da solo. Quale dei due è meglio usare? La risposta giusta ovviamente non esiste! L’unica cosa di cui sono convinto è che se conoscete Java per iniziare a sviluppare su Android non dovrete faticare troppo, dopo un bel corso di tre giorni sarete pronti a sviluppare la vostra prima applicazione (fine messaggio promozionale!). Non mi sento di dire la stessa cosa per gli sviluppatori C/C++, mi dispiace per voi ma passare a Objective-C non sarà così banale. E voi, avete fatto un viaggio simile? Sono l’unico che ha incontrato queste difficoltà?

60 Posts

Software Architect con esperienza su piattaforma J2EE e attualmente focalizzato principalmente in progetti di sviluppo di applicazioni Android. Attualmente sono in Nana Bianca dove mi occupo dello sviluppo di alcune app Android. Coautore della seconda edizione di Android Programmazione Avanzata e docente di corsi di sviluppo su piattaforma Android. Follow me on Twitter - LinkedIn profile