Italian [risolto] B4J - Progettare un sistema modulare tipo plug-ins

ivanomonti

Expert
Licensed User
Longtime User
Buon giorno a tutti, io ho la fissa che un buon software è fatto di espansibilità nel tempo, molte aziende lo fanno da adobe con i plugins aggiuntivi come tanti altri, mi piacerebbe fare lo stesso, hai tempi remoti leggevo tutti i file .Jar dentro una folder chiamata plugins e creavo il suo menu, alla voce selezionata (esecutabile) si lanciava un modulo non previsto ai tempi del software dove aggiungeva nuove funzioni.

In questo modo se il cliente richiedeva un aggiunta io creavo il nuovo modulo e lo integravo nel software precedente che lo leggeva come se fosse parte del programma.

Quello che mi chiedevo se esiste un modo più elegante per creare un sistema del genere?
 

Star-Dust

Expert
Licensed User
Longtime User
Mi pare che tu qualche anno fa avevi suggerito un sistema del genere.
Se non erro spiegavi che creavi le varie parti dell'App come Software separati e un App che funga da menu generale.
Man mano che trovava un file Jar nuovo aggiornava il menu (forse con un archivio online di corrispondenza) Al momento del click avvia l'App esterna (il jar per intenderci) che lavora poi sugli stessi archivi.

Se non ricordo male eri proprio tu a spiegarlo
 

ivanomonti

Expert
Licensed User
Longtime User
@Star-Dust si l'ho fatto ma sono passati anni da allora, mi chiedevo se nel frattempo fosse fatta una soluzione più elegante.
 

Star-Dust

Expert
Licensed User
Longtime User
@Star-Dust si l'ho fatto ma sono passati anni da allora, mi chiedevo se nel frattempo fosse fatta una soluzione più elegante.
La mia memoria funziona ancora...
Se non c'è in Java, non sarà aggiunta in B4J e non è detto che venga implementata.
Però non mi sono documentato in merito, quindi non mi sbilancio nel dire che non esiste
 

ivanomonti

Expert
Licensed User
Longtime User

Star-Dust

Expert
Licensed User
Longtime User
E' un FrameWork e potrebbe appoggiarsi a codice che è eseguito esternamente.
Crea un apagina html/java e in parte viene eseguita dal Browser.
Inoltre immagino abbia un suo piccolo motore interprete di alcune istruzioni che gli permetta di creare dinamicamente viste nella WebApp e parti di codice Java che sono interpretate dal browser
 

ivanomonti

Expert
Licensed User
Longtime User
@Star-Dust vedo che il mio sistema è ancora valido hahahah l'unica cosa e che vorrei più eleganza
 

Star-Dust

Expert
Licensed User
Longtime User

ivanomonti

Expert
Licensed User
Longtime User
nei post datati ho omesso delle considerazioni importanti e poi non ho messo esempio che farò e metterò qui sotto. Ciò che importa e come passare gli argomenti al Jar che vogliamo lanciare e non solo, se vogliamo che i plugins siano nostri possiamo mettere delle key come valori da processare.

questo codice legge i file jar all'interno di una cartella predefinita da voi, in questo caso ho usato Dirapp\_plugins

costruzione del menu plugins:
Sub addPlugIns(Cb As ComboBox)

    If File.Exists(File.DirApp,"_PlugIns") = False Then
        Main.ToastMessage(Main.menusx,"Add-ons folder not found")
        Return
    End If
    
    Dim value As String = File.ListFiles(File.Combine(File.DirApp,"_PlugIns"))
    value = value.Replace("(ArrayList)","").Replace("[","").Replace("]","")
    Dim values() As String = Regex.Split(",",value)

    For i=0 To values.Length-1
        Dim m As Map
        m.Initialize
        Dim lbPlugins As Label
        lbPlugins.Initialize("plugins" )
        lbPlugins.Text=values(i).Replace(".jar","")
        m.Put("kay","plugins") '0 index non l'ho utilizzato al momento
        m.Put("name",values(i).Replace(".jar","")) '1 index nome del file senza estensione da pubblicare nel menù, combobox o ciò che desideriamo
        m.Put("file",values(i).Replace(" ",""))'2 index nome del file jar che dobbiamo eseguire
        m.Put("dir",File.Combine(File.DirApp,"_PlugIns"))'3 index folder dove si colloca il plugins da lanciare
        m.Put("db",File.Combine(File.DirApp,"lavagna.sqlite"))'4 index path del database in questione
        m.Put("idlogin",Main.idlogin)'5 index id di chi sta usando il software per la raccolta dati nel database multi utente
        m.Put("Key","+1234567890") '6 index key per la verifica se il plugins è nostro
        lbPlugins.Tag = m
        Cb.Items.Add(lbPlugins)
    Next
  
End Sub

qui richiamiamo una shell dove andremo a eseguire il nostro plugin (sempre nel software padre)


B4X:
Private Sub plugins_ValueChanged (Value As Object)
    
    Dim lb As Label = Value
    Dim shl As Shell
    Dim m As Map =  lb.Tag
    Dim Args() As String = Array As String("-cp", m.GetValueAt(2), "b4x.plugins.ivanomonti.main", m.GetValueAt(4), m.GetValueAt(5), m.GetValueAt(6)) ' argomenti che passo
    shl.Initialize("shl", "java", Args) comando linea
    shl.WorkingDirectory = m.GetValueAt(3) ' path del plugins
    shl.Run(-1) ' senza timeout 
    
End Sub

alla chiusura del plugins verra processata una riposta della shell lanciata precedentemente

B4X:
Sub shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success And ExitCode = 0 Then
        Log("Success")
        Log(StdOut)
    Else
        Log("Error: " & StdErr)
    End If
End Sub

Fino qui è semplice,,, come del resto anche sul plug ins


B4X:
Sub AppStart (Form1 As Form, Args() As String)
    
    
    
    MainForm = Form1
    MainForm.RootPane.LoadLayout("ChartLayout")
    MainForm.Title="Module Chart v 1.0.0"
    MainForm.Stylesheets.Add(File.GetUri(File.DirAssets,"css-33.css"))
    MainForm.Show
    
    DatePicker1.DateFormat="yyyy-MM-dd"
    DateTime.DateFormat="yyyy-MM-dd"
    
'    If debugMode= False Then
'        If Args.Length > 0 Then
'            If Args(0) <> "xxxxxx" Then 'key che valida il nostro plugins, in caso di assenza si chiude il jar,, avviamente non ho messo il codice perchè lascio libera la vostra fantasia
'                'fx.Msgbox(MainForm,"Module for Lavagna","Error system message")
'                'MainForm.close
'            Else
'                path=Args(1)
'                idlogin=Args(2)
'                'fx.Msgbox(MainForm, Args(0) & Chr(10) & Args(1) & Chr(10) & Args(2),"")
'            End If
'        End If
'    End if
        
End Sub

da qui in poi chiudete e compilate il figlio e lo distribuite come vi pare, se domani qualcuno mi chiede una aggiunta per la sua attività gli creo un modulo a se che poi puoi vendere nel settorre, dal bar ai centri estetici a servizio marketing e via discorrendo.

Nota interesante, se si fa una sorta di comunità in un softawe con questo concetto e si mettono le regole come fa wordpress ecc ecc si può creare un mercato di plug in su una base semplice e trarre grandi soddisfazioni.

Poi nel tempo la base può migliorare ma con una base clienti diversa da singolo individuo, la comunità da più garanzie cosa che il singolo non può.
 

LucaMs

Expert
Licensed User
Longtime User
nei post datati ho
Se te becca la Guardia di Finanza, che fai i "post-datati", so' cavoli tua ?

Ma la mi faccia hapire; quelli non saranno "veri e propri" plug-in, ma semplicemente sw a sé stanti che non potranno comunicare col loro "padre", al massimo potrai fare in modo che accedano a dati comuni (DB)... o sbaglio?
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Spero di poterti dare un paio di suggerimenti senza sembrare presuntuoso.

Ho visto tutto l'arzigogolamento che hai fatto per riempire la map, il che mi ha fatto pensare che sei molto abituato ad usare gli Array e forse ben poco le List.
Quest'ultime sono molto simili agli Array ma molto più "potenti" e comode da usare.

Altra cosa è che a volte è molto meglio usare delle costanti. Ad esempio questa parte del tuo sorgente:
B4X:
Dim Args() As String = Array As String("-cp", m.GetValueAt(2), "b4x.plugins.ivanomonti.main", m.GetValueAt(4), m.GetValueAt(5), m.GetValueAt(6)) ' argomenti che passo
shl.Initialize("shl", "java", Args) comando linea
shl.WorkingDirectory = m.GetValueAt(3) ' path del plugins
E che ne so, io che non ho sviluppato quel codice e tu stesso, tra un po' di tempo, a cosa corrisponderanno i valori della map nelle posizioni 2-3-4-5-6 che vedo scritte là (a parte che Erel ti direbbe che GetValutAt e GetKeyAt sono "deprecabili", sconsigliati)?

Se invece avessi preparato delle costanti:
Public Const PLUG_ARG_NAME As Int = 1
Public Const PLUG_ARG_FILE As Int = 2
Public Const PLUG_ARG_DIR As Int = 3
etc.
poi avresti scritto:
m.GetValueAt(PLUG_ARG_NAME)
m.GetValueAt(PLUG_ARG_FILE)
m.GetValueAt(PLUG_ARG_DIR)
etc.

In questo modo il codice risulta più leggibile (anche a te stesso tra un anno) e non devi ricordarti a memoria se nella posizione 2 hai il la dir o il file o il nome o...

(comunque andrebbero usate costanti stringa, con i valori "name", "dir", "file"...
e prelevati i valori dalla Map con:
m.Get(PLUG_ARG_NAME) ' <--- costante stringa con valore "name")
 

giannimaione

Well-Known Member
Licensed User
Longtime User
Ma la mi faccia hapire; quelli non saranno "veri e propri" plug-in, ma semplicemente sw a sé stanti che non potranno comunicare col loro "padre", al massimo potrai fare in modo che accedano a dati comuni (DB)... o sbaglio?
è così; quello che risulta lento è l'avvio della app/plug-in richiamata (circa 2 secondi) e NON è molto professionale.
 

LucaMs

Expert
Licensed User
Longtime User
Pensa te cosa vedo scrivere da un professionista (!):

Il linguaggio di programmazione Java è stato pensato e sviluppato per inserire applicazioni nei dispositivi mobili.

Ma famme ride! Java esisteva qualche decennio prima che nascessero i dispositivi mobili!
 

LucaMs

Expert
Licensed User
Longtime User
Pensa te cosa vedo scrivere da un professionista (!):
Va beh, invece in quel famoso sito:
Oltre ad essere uno dei più diffusi IDE, Eclipse può essere considerato un programma dotato di una piaffaroma facilmente estendibile, mediante lo sviluppo di plugin, cioè di componenti java che ne estendono le funzionalità base.
?

E comunque è una guida su come sviluppare plugin PER Eclipse, non USANDO Eclipse, come invece pensavo.
 
Last edited:
Cookies are required to use this site. You must accept them to continue using the site. Learn more…