Le applicazioni generate da Livebase sono sistemi completi in grado di interrogare e gestire database relazionali. Le operazioni consentite spaziano dalla semplice manipolazione di singoli oggetti/righe di classi/tabelle (inserimento, modifica, cancellazione), all’esecuzione di query molto complesse che coinvolgono centinaia di classi e sfruttano tutto il potere offerto dal Designer: oltre alla struttura statica del dominio, il nostro ambiente di sviluppo consente di definire direttamente nel modello dell’applicazione anche della logica applicativa sotto forma di espressioni, filtri, operatori d’aggregazione.
Lo scopo di Livebase è realizzare rapidamente le applicazioni e in modo intuitivo seguendo un approccio dichiarativo e low code.
La nostra filosofia abbraccia inoltre l’evoluzione dei sistemi. Un sistema che evolve non solo deve poter scalare (aumentare il volume di interazioni, di dati, di utenti…) o offrire nuovi servizi e funzionalità: è importante infatti che gli scenari d’evoluzione possibili siano molteplici e differenti. A tale scopo, gli strumenti di manutenzione evolutiva da noi forniti supportano i modellatori/sviluppatori in questa delicata attività.
Requisiti complessi #
Cosa succede quando, durante l’evoluzione del sistema, emerge la necessità di realizzare dei requisiti complessi?
Innanzitutto: cos’è un requisito complesso? Si tratta, nella maggior parte dei casi, di una qualche funzionalità che è semplice da descrivere o immaginare a livello concettuale, ma la cui realizzazione può risultare difficile – o addirittura impossibile – quando non si utilizza uno strumento conveniente o non si segue l’approccio adeguato.
Supponiamo di aver realizzato una Cloudlet per gestire un sistema di e-commerce a cui gli utenti finali interagiscono mediante un front-end dedicato, mentre gli amministratori utilizzano la GUI configurata nel modello per gestire il back-office. Ad esempio, alcune interazioni potrebbero essere le seguenti:
- Un amministratore effettua il login sull’applicazione generata;
- Un amministratore effettua l’upload di un file .pdf;
- Un utente conferma un acquisto: l’applicazione riceve dal front-end una richiesta “conferma di creazione” (save) di un oggetto della classe Ordine.
Immaginiamo di definire, nella nostra applicazione, un comportamento in risposta a ciascuna interazione:
- L’applicazione esegue dei controlli di sicurezza aggiuntivi prima di autenticare il membro della Cloudlet;
- L’applicazione accede al file, ne elabora il contenuto e crea uno o più oggetti popolati con le informazioni in esso contenute;
- L’applicazione risale al Cliente associato all’Ordine e invia una email a questi che contiene un riepilogo sui dettagli dell’acquisto, corredato da una ricevuta compilata in un file .pdf.
Abbiamo quindi descritto tre requisiti che riguardano la gestione di eventi, l’elaborazione di file e l’interazione con servizi esterni.
È possibile codificare queste azioni nel modello, usando esclusivamente gli strumenti low-code offerti da Livebase? A oggi la risposta è probabilmente no; tuttavia, anche se riuscissimo a re-immaginare il requisito per poter dichiarare query, filtri, espressioni in grado di realizzarlo, la soluzione sarà inutilmente complicata. Inoltre, il modello risultante verrebbe sporcato da elementi intermedi che, presi singolarmente, non sarebbero riutilizzabili e non aggiungerebbero quindi alcun valore all’applicazione.
Estendere l’applicazione con i plugin #
Una soluzione efficace consiste nel modificare il codice sorgente dell’applicazione e implementare direttamente il comportamento desiderato sfruttando un linguaggio di programmazione ad alto livello. È qui che entrano in gioco i plugin Livebase.
Come vedremo in questa guida, i plugin sono uno strumento semplice ma estremamente flessibile, pensati sia per estendere le funzionalità base dell’applicazione che per definire interi processi automatizzati e realizzare integrazioni con servizi esterni.
Modeling + Coding = Profit! #
Abbiamo evidenziato la relazione che lega la complessità dei requisiti al potere espressivo degli strumenti low code; d’altronde, lo scopo dello strumento è quello di aiutare il modellatore a realizzare, nel minor tempo possibile, la maggior parte dei requisiti di sistema.
Prendendo per esempio un qualunque sistema sufficientemente specializzato, e considerando gli strumenti attualmente offerti da Livebase, possiamo assumere che questo insieme rappresenti l’80/85% dei requisiti totali (la parte in verde); in particolare, si tratta di tutte le funzionalità basilari dell’applicazione fino a un livello sufficientemente complesso (query, filtri, report, etc.).
I plugin hanno l’obiettivo di facilitare la realizzazione del rimanente 15/20%. In questo senso, il loro ruolo è decisivo per due motivi:
- rendere l’evoluzione del sistema indipendente da quella dello strumento di sviluppo: lo sviluppo di Livebase e dei plugin procede di pari passo, e future versioni di Livebase potrebbero aprire il supporto a scenari prima gestibili solo tramite plugin (la parte in giallo);
- supportare i requisiti più complessi: nessuno strumento low code, per quanto potente, potrà mai essere universale; ogni sistema avrà sempre dei requisiti che richiederanno codice ad hoc (la parte in rosso), ed è per via di questi che incoraggiamo lo sviluppo di plugin.
I Service Handler #
Il meccanismo alla base di un Plugin Livebase è il Service Handler: nel modello è possibile dichiarare delle entità, dette appunto Handler, responsabili della gestione di alcuni servizi dell’applicazione generata.
Nell’engine model, un Handler è un elemento di una classe denotato da un nome e da un tipo; ciascun diverso tipo è pensato per iniettare logica custom in un punto specifico dell’applicazione generata.
Quando genera l’applicazione, Livebase controlla quindi la presenza di Handler nel modello e genera per ciascuno un’interfaccia Java SPI (Service Provider Interface). Queste vengono collezionate poi nel jar SPI, una libreria che può essere utilizzata per realizzare l’implementazione dei Service Handler.
Vediamo un esempio di un plugin in azione:
Nel modello in figura è presente la dichiarazione di un FormActionHandler su Class1, a cui corrisponderà una Handler interface nello SPI. Quando l’utente clicca sul bottone myAction presente sulla form di Class1 in fase di edit, il servizio corrispondente verrà invocato: la sua Handler implementation avrà accesso ai campi compilati dei tre attributi e potrà cambiarne il valore visualizzato o usarli per qualunque altro scopo (una generica action).
Il nostro obiettivo è quindi fornire il codice atto a gestire la chiamata allo specifico Service Handler; il plugin risultante conterrà le classi Java che implementano le Handler Interface più tutti i package di supporto ed eventuali dipendenze a runtime.
Servizi e ambiente d’esecuzione #
L’interconnessione a runtime tra la Cloudlet e i rispettivi plugin è resa possibile grazie all’ambiente di esecuzione basato su OSGi. In esso, Cloudlet e plugin sono bundle che cooperano pubblicando e ricercando servizi su un apposito registro del framework.
Per ulteriori letture rimandiamo all’approfondimento Plugin: Ambiente di esecuzione.
Sviluppare Plugin Livebase #
In questo articolo abbiamo introdotto i concetti fondamentali legati ai Plugin Livebase: gli Handler, la SPI e i servizi. In seguito illustreremo come sviluppare un generico plugin e approfondiremo gli strumenti a disposizione, le metodologie e le best practice.
Continua la lettura: Ciclo di sviluppo