Le Portable Class Libraries costituiscono in Xamarin un approccio alternativo agli Shared Project, per la condivisione del codice tra le diverse edizioni dell'app destinate a diversi sistemi operativi. Vediamo dunque cosa sono le PCL e facciamo alcune considerazioni per capire quale tra i due approcci sia più conveniente e in quali casi.
Portable Class Libraries
Per introdurre l'approccio delle Portable Class Libraries esaminiamo l'architettura di un'app cross-platform con condivisione di codice basata su PCL:
Nella figura le frecce servono a mostrare che:
- Ogni "Platform-Specific Application Project" (iOS app, Android app, Windows Phone app) referenzia la PCL
- Che è possibile impiegare caratteristiche di una determinata piattaforma attraverso l'utilizzo del design pattern Dependency Injection (DI).
La Dependency Injection offre le linee guida per includere le funzionalità specifiche di una piattaforma nella nostra soluzione, fornendo un modo per implementare i pattern Strategy e/o Bridge descritti da Gang of Four (GoF).
DependencyService
In pratica applicare i principi della DI significa definire nel codice condiviso interfacce (classi astratte) che vengono implementate (estese) in ogni piattaforma tramite sottoclassi. A questo punto, sarà possibile integrare queste specifiche implementazioni all'interno della PCL.
Xamarin offre la classe DependencyService, utile appunto per implementare i principi del DI attraverso:
- la creazione di un'interfaccia,
INomeClasse
, definita nel PCL; - l'implementazione specifica delle interfacce del PCL all'interno dei progetti delle piattaforme di interesse e opportunamente registrate tramite il tag
[assembly]
come segue:
[assembly: Xamarin.Forms.Dependency(typeof(NomeClasse_PIATTAFORMA))]
doveNOMECLASSE_PIATTAFORMA
è il nome della classe relativo alla piattaforma (Android, iOS, WindowsPhone, eccetera...) che la implementa - l'invocazione del metodo specifico all'interno del codice condiviso usando il metodo
Get
diDependecyService
come segue:
DependencyService.Get<INOMECLASSE>.Nome_Metodo
NOTA: È importante sottolineare che quanto descritto è da utilizzare solo ed esclusivamente nel caso in cui sia necessario ricorrere a funzionalità specifiche delle piattaforme supportate.
Gestione delle piattaforme
Una soluzione Xamarin.Forms (Portable) contiene al suo interno una PCL generata durante la creazione della soluzione stessa, e referenziata dalle piattaforme supportate da Xamarin. In particolare, per conoscere e modificare le piattaforme supportate dal PCL, è sufficiente:
- selezionare il progetto PCL (ha la dicitura Portatile o Portable);
- premere ALT + INVIO.
A questo punto si aprirà la finestra delle proprietà, in cui alla voce Libreria, sotto la dicitura Destinazione, è riportato l'elenco di tutte le piattaforme supportate.
È interessante notare che oltre alle piattaforme presenti nella soluzione, ritroviamo la compatibilità con il .NET Framework e ASP.NET Core. Cliccando su Modifica verrà visualizzata una nuova finestra di dialogo in cui è possibile modificare le piattaforme di destinazione della PCL.
La selezione delle piattaforme di destinazione genera un profilo associato alla PCL tramite il quale è possibile riutilizzare la PCL in altre soluzioni Xamarin per ogni piattaforma di destinazione specificata nel profilo. Inoltre, in base alle piattaforme supportate si ha a disposizione uno specifico insieme di librerie basate sul .NET Framework per lo sviluppo dell'app.
Nella figura seguente sono riportate le principali funzionalità supportate, al variare del .NET Framework.
In particolare, dalla colonna di Xamarin si evince che Xamarin.iOS e Xamarin.Android supportano tutte le caratteristiche riportate in tabella. Xamarin.Forms è quindi fortemente limitato da Windows Phone e dalla versione del .NET Framework richiedendo così allo sviluppatore di impiegare meccanismi più articolati per fornire servizi basilari ed essenziali come, ad esempio, la localizzaione dell'utente.
Una volta effettuata la scelta delle piattaforme e sviluppato il codice condiviso (opportunamente strutturato in layer), la compilazione dell'intera soluzione genererà una DLL che sarà referenziata da tutti i progetti. La DLL così creata potrà essere riutilizzata non solo nei progetti della soluzione, ma anche in altre soluzioni, cosa non possibile con l'approccio Shared Project in cui il codice condiviso può essere impiegato solo all'interno dei progetti della stessa soluzione.
Portable Class Library o Shared Assets Projects?
Quale approccio è dunque più conveniente per la condivisione del Core Project tra le piattaforme supportate? Ecco pro e i contro dei due approcci, che possono aiutarci a scegliere il più adatto alla nostra soluzione.
Approccio | Portable Class Library | Shared Assets Project |
---|---|---|
Pro | Condivisione del codice tra i vari progetti | Condivisione del codice tra i progetti |
Creazione durante la compilazione di una DLL che può essere richiamata in altre soluzioni | Il codice può essere gestito con le direttive del compilatore | |
Refactoring del codice più semplice | Possibilità di includere referenze specifiche delle piattaforme | |
Contro | Utilizzo di un sottoinsieme di funzioni del .NET Framework limitato dalle piattaforme supportate | La compilazione del progetto non genera un assembly come output da referenziare in altri progetti (inclusi quelli Shared) |
Complessità nell'aggiungere comportamenti specifici delle piattaforme | Refactoring del codice delle direttive del compilatore è più complesso | |
Considerazioni | Un buon approccio per progetti in cui l'assembly generato deve essere condiviso con altri sviluppatori | Ottimo approccio di condivisione del codice che permette una gestione più semplice delle specifiche funzionalità delle piattaforme |
Largamente impiegato rispetto a SAP | Consigliabile se il codice non deve essere condiviso ad altri sviluppatori ed è utilizzato solo all'interno della soluzione |
Il dibattito su quale sia l'approccio più conveniente è aperto anche tra gli sviluppatori di Xamarin. In questo suo post, ad esempio, Jason Smith (Software Engineering Manager di Xamarin) dichiara che l'approccio migliore è PCL in quanto permette una migliore gestione del progetto a lungo termine evitando il cosiddetto spaghetti code. Al contrario, Miguel de Icaza (CTO di Xamarin) sostiene (in risposta) l'esatto opposto, ritenendo che l'utilizzo di una PCL sia poco maneggevole e imponga limitazioni sul .NET Framework e complicazioni nella realizzazione di funzioni semplici.
La scelta tra l'approccio PCL e quello SAP rimane pertanto condizionata dai nostri obiettivi: sta a noi valutare i pro e i contro e comprendere quale si adatti meglio alle nostre esigenze.