Continuiamo a parlare delle anticipazioni disponibili al momento sul framework Singular. Nonostante solo poco materiale sia stato rilasciato, possiamo comunque già fare alcune considerazioni sulle caratteristiche generali di questo framework, in attesa del primo rilascio ufficiale.
A che punto è Singular?
Lo scorso mese abbiamo parlato per la prima volta di Singular, proprio su queste pagine e sono passati almeno un paio di mesi dalla presentazione ufficiale fatta da Daniel Kurka alla GWT.create. Ma il fatto è che Singular… ancora non è stato rilasciato ufficialmente.
Questo non significa che non ci siano informazioni o notizie al di là della presentazione citata: alcuni documenti di progetto iniziano ad essere disponibili e chiariscono, tra l’altro, i Singular Models e la loro serializzazione [1], la Dependency Injection [2], il linguaggio d’espressione [3] e ci mettono in grado di capire come il framework stia crescendo.
Però, purtroppo, una release pubblica non è ancora disponibile e, a giudicare dalle voci, Singular verrà rilasciato, almeno in beta, nei prossimi mesi. Inoltre, durante la GWTcon [4] in programma per l’11 novembre 2015, ce ne parlerà approfonditamente il suo autore, Daniel Kurka, che ha già confermato la sua partecipazione, e che ci mostrerà come ottenere il meglio da questo framework.
Quello che c’è: applicazioni native e cross-platform
In ogni caso, anche in assenza del codice di cui potremo parlare non appena verrà rilasciato, c’è di sicuro almeno un aspetto di questo framework “in fieri” che vale la pena di essere analizzato e cioè come questo possa permettere di realizzare applicazioni cross–platform e native.
I test di performance mostrati da Daniel alla GWT.create mettono a confronto AngularJS e Singular e mostrano quanto quest’ultimo sia in grado di portare benefici su quelli che vengono considerati i punti deboli di Angular, cioè il tempo di bootstrap delle applicazioni (“initial rendering 20x faster”) e le prestazioni in generale (“runtime 5x faster”). L’aspetto più interessante di Singular come tecnologia è la possibilità di generare letteralmente molteplici applicazioni native per impieghi diversi (web, Android, iOS, …) a partire dalla medesima code-base.
Ma c’è di più
A differenza di GWT, Singular non è un toolkit ma piuttosto un framework che introduce dei constraint, e fornisce una guida nella realizzazione della struttura dell’applicazione. Proprio vinconlando la struttura delle applicazioni, riesce nella sfida di permettere l’adattamento del medesimo codice a dispositivi/sistemi operativi/contesti diversi. E, come avremo modo di vedere, questo adattamento può essere automatico o personalizzabile.
Un’architettura “canonica”
Per la verità, l’architettura di una applicazione Singular non dovrebbe sorprendere nessuno che abbia scritto, secondo i canoni comunemente accettati, una interfaccia utente. Lo schema infatti è il più classico MV(P)C e, al livello di dettaglio del grafico, non cambia molto se, accanto a Model e View, si pensa ai Contoller oppure ai Presenter (figura 1).
Figura 1 – Lo schema dell’architettura è un “canonico” MV(P)C.
Proprio in questa basilare, e aurea, separazione delle responsabilità si annida l’opportunità di generare letteralmente versioni diverse della medesima applicazione: M e C si riutilizzano, V si genera (o riscrive se si vuole) per ogni piattaforma. E, se le viste sono sottili come la buona pratica raccomanda, il grosso del codice si conserva. Ma c’è di più: la struttura di Singular permette ancora una migliore situazione. Come si vede in figura 2, Singular spinge la riusabilità del codice ancora oltre, sostanzialmente mutuando da Angular l’idea delle direttive.
Figura 2 – Singular mutua da Angular l’idea delle direttive e garantisce una migliore riusabilità del codice.
Infatti, con questo approccio, quello che lo sviluppatore scrive è sostanzialmente il Controller; successivamente, costruendo lo scope (in terminologia Angular) viene definito implicitamente il Model; infine le direttive, insieme ai template che costituiscono la View, servono a descrivere l’interazione con ciò che sarà renderizzato a schermo.
Considerazioni sulle diverse piattaforme
A questo punto, per rendere la nostra applicazione basata su Singular condivisibile tra piattaforme diverse, gli aspetti da comprendere sono sostanzialmente due:
- come rendere trasferibile la application logic;
- quale tecnologia usare per associare le direttive con lo screen (le template in una parola).
Trasferire la application logic: Android vs iOS
Per il primo aspetto viene naturalmente in aiuto il fatto che, usando GWT, possiamo scrivere l’intera logic in Java e lasciare che sia il compilatore java-to-javascript a costruire “per noi” un’applicazione eseguibile da un browser. Non è poi una sorpresa poter usare su Android direttamente il codice Java, essendo questo il linguaggio naturale per lo sviluppo di applicazioni per questo sistema operativo.
La strada per iOS sembra più complessa in quanto, in linea di principio, il codice Java non è riutilizzabile su iOS dove sarebbe naturale utilizzare Objective-C. In questo aspetto viene in aiuto il tool J2ObjC, “un tool a linea di comando realizzato da Google che in grado di tradurre il codice Java in linguaggio ObjectiveC per la piattaforma iOS (iPhone/iPad)” [5].
Definito, in un talk tenuto da uno degli sviluppatori di Google [6], l’equivalente di GWT per iOS, J2ObjC funge da tecnologia abilitante in Singular per rendere riutilizzabili le applicazioni anche su iPhone ed iPad. Differentemente da quanto si potrebbe pensare a una prima lettura J2ObjC, è tutto meno che un tool sperimentale. Infatti vale la pena di prestare attenzione che esplicitamente Google ammette che proprio sulla base di questo transpiler (una via di mezzo tra un translator e un compiler) è stata realizzata, e continua a essere sviluppata, Inbox per iOS [7].
Descrivere le viste
La questione circa la tecnologia per associare le direttive con lo screen risulta essere una falsa preoccupazione. Come viene descritta l’interfaccia grafica delle applicazioni nelle tre piattaforme prese in considerazione? Vediamo un rapidissimo riepilogo.
- Web: si usa HTML;
- Android: grazie a file XML;
- iOS: UiBuilder.
Tutte le piattaforme hanno insomma una qualche forma di DSL per la descrizione delle UI; quindi è facile immaginere come sia possibile generare le UI per piattaforme diverse. E, soprattutto, è semplice capire che è possibile utilizzare la medesima logica di applicazione e riscrivere per le piattaforme solo il template, cosa che nell’impiego reale è assai più importante visto che oltretutto ha un costo marginale rispetto alla gestione di tre intere applicazioni distinte.
Questo significa insomma che possiamo mantenere la logica dell’applicazione completamente sincronizzata fra le versioni ma al contempo non rinunciare alla personalizzazione delle interfacce utente sulle singole piattaforme.
Un esempio: comparazione tra HTML e file XML
Diamo un’occhiata alla descrizione di una vista per il web e a una per Android. Nel codice, ovviamente, abbiamo omesso tutte le property non significative per l’esempio.
Vediamo un template HTML come il seguente:
{{echoh}}
Ebbene, il codice appena visto esprime la medesima UI di un file di layout XML per Android fatto in questo modo:
<LinearLayout xmlns_android="http://schemas.android.com/apk/res/android" xmlns_tools="http://schemas.android.com/tools" ... tools_context="..."> tools:ng-controller="MyController"> android_inputType="text" tools:bind-text="name"/> tools:on-click="echoName()"/> tools:bind-text="echoh"/>
Date descrizioni delle UI equivalenti, non è sorprendente che Singular sia in grado di permetterci di utilizzarle sulle rispettive piattaforme con la medesima application logic, scritta e mantenuta una sola volta.
Punti in sospeso: API diverse
Con quanto detto fino a questo punto risulta chiara la strategia per la generazione di applicazioni cross-platform ma resta da esplorare ancora una questione: piattaforme diverse hanno a disposizione API diverse per accedere praticamente a ogni risorsa.
La semplice esigenza di effettuare una richiesta HTTP lascerebbe lo sviluppatore Singular nella situazione di dover effettuare un fork della codebase per utilizzare anche solo su web o su Android due API completamente diverse. Una situazione analoga la si avrebbe per accedere, ad esempio, alla fotocamera oppure al salvataggio su memoria: è pertanto necessaria una libreria di interfacce che, astraendo dalle specifiche implementazioni, offrano una API uniforme sulle diverse piattaforme.
Layer di astrazione
Dall’analisi di Daniel Kurka gli aspetti che necessiterebbero di queso layer di astrazione non sarebbero di per se’ moltissimi: connessioni di rete, memoria per salvataggio dati, localizzazione, multimedia, preferenze, notifiche; non moltissimi ma comunque un numero sufficientemente alto da non consentire di rendere Singular utilizzabile senza scrivere un bel pò di codice.
Fortunatamente, viene in aiuto in questo ambito un altro progetto, da lungo tempo utilizzato e maturo: PhoneGap. Intendiamoci, non stiamo dicendo di utilizzare con Singular l’approccio delle applicazioni che comunemente vengono definite ibride: applicazioni scritte in JavaScript, impacchettate in un’applicazione nativa che, attraverso la API di PhoneGap appunto, fornisce l’accesso a finzioni non disponibili nella webview.
Stiamo immaginando di riutilizzare il lavoro fatto dagli sviluppatori di PhoneGap (ora Apache Cordova [8], per la verità) nell’astrarre le feature native dei dispositivi in una forma utilizzabile uniformemente sulle diverse piattaforme. In PhoneGap poi questa astrazione viene utilizzata per offrire dei metodi utilizzabili da JavaScript. Singular, invece, si inserisce direttamente al livello del binding per offrire le medesime API alle applicazioni Java senza richiedere di ricostruire le astrazioni ma solo di definire nuovi binding. Proprio nella delicata stabilizzazione di questi binding sembra essere attualmente al lavoro il team di Singular.
Testing
Un’ultima cosa, che con questa struttura risulta essere particolarmente semplice, è il testing: infatti scollando completamente le viste, interamente descritte dai template e dalle direttive, allo sviluppatore resta in carico il test del solo codice che implementa l’application logic. Questo codice, in questo contesto, è “pure java” e quindi è testabile senza troppo sforzo di mocking e, soprattutto, senza trucchi che richiedano di mascherare l’implementazione specifica della UI.
Conclusioni
Con questi due articoli abbiamo voluto presentare in anteprima Singular, un framework che promette di essere una piccola rivoluzione per lo sviluppo di applicazioni cross-platform. Pur avendo solo elementi preliminari, abbiamo potuto comunque descrivere le caratteristiche principali e la “filosofia” che stanno dietro questa promettente iniziativa di Google. Certamente, con il rilascio delle prime versioni del framework potremo capire se e come certe criticità sono state affrontate: le premesse ci sono tutte e confidiamo davvero che Singular possa diventare uno degli strumenti più usati e più utili rilasciato negli ultimi anni.