Newsgroup: it.comp.lang.delphi
Titolo: Quale approccio?

L'applicazione alla quale sto lavorando ha la seguente struttura: Un 
Mainform, tramite pulsanti o menu, richiama tanti altri Form, ciascuno parte 
di una funzionalit� dell'applicazione, che a loro volta possono richiamare 
ove necessario altri form e funzionalit�. Alcuni form sono richiamati in 
Showmodal e altri no.
Molti tra questi condividono l'uso di oggetti (stringList,  classi e liste 
di classi).
Riguardo a questi oggetti, mi sono sempre posto il problema di quale 
approccio fosse meglio adottare e cio�:
1) Crearli quando servono e mantenerli poi in memoria sempre disponibili per 
il caso che altre funzionalit� che ne fanno uso vengano utilizzate. (in 
questo caso dichiarando le variabili di riferimento come globali, per poter 
vedere da un form quello che � stato creato da un altro..);
2) Crearli e distruggerli in ogni unit� dove vengono usati, potenzialmente 
creandoli e distruggendoli enne volte.
Alcuni di questi oggetti sono liste di qualche dozzina di singoli oggetti 
con una ventina di campi, per la cui inizializzazione vengono usate delle 
query su vari dataset.
 
Mi domando:
- quali elementi pesano per una decisione o l'altra?
- c'� un approccio migliore?
- esistono altri approcci? 
 

 - esistono altri approcci?
 
Non � importante considerare gli elementi per la struttura che li ospita 
(sia essa lista, classe, o records) ma per la funzionalit� che hanno, 
cio� per cosa servono.
 
Tipicamente questi dati condivisi nell'applicazione vengono incapsulati 
in una classe gestore, un manager, che si occupa di tutti gli aspetti 
relativi al recupero e trattamento di questi dati.
Un esempio banale sono i settings dell'applicazione: un manager che li 
carica all'inizio e li condivide tra tutte le finestre in modo singleton.
 
Nei miei widgets (forms) quando ho bisogno di dati condivisi, istanzio 
il manager, gli passo me stesso (il widget) come owner, e poi chiamo i 
metodi di mio interesse:
 
wi_composer_config * _config_mgr;
...
_config_mgr = new wi_composer_config(this); 
_config_mgr->restore_widget_geometry((QWidget*)this,str_wi_rotazioni_widget);
 
-- 
morde
Android
QT 4.7
Delphi (5,6,7.. expired)
Firebird Database
 

 carica all'inizio e li condivide tra tutte le finestre in modo singleton.
 
A me sta storia di caricare cose all'avvio e basta piace molto poco.
Ovviamente, ma non per tutti, ci sono dei dati di configurazione che devi caricare all'avvio e tali devono restare fino alla chiusura.
Ma questo non vale per tutti i dati di configurazione.
 
Un classico caso da ulcera è questo:
 
1) un parametro viene caricato solo all'avvio
 
2) l'utente lo cambia  e di dimentica di riavviare
 
3) le cose funzionano in modo strano e l'utente apre un ticket ma non gli sfugge di segnalare che ha cambiato il valore di quel particolare parametro
 
4) tu sei li a sbatterti e non capisci il xche del comportamento anomalo....
 
Non sempre il riavvio è praticabile.
Basti solo pensare ad ambienti eterogenei dove uno o piu' client sono connessi via vpn...Qua l'avvio (ed il riavvio) possono essere lenti.
Certo, ci sono quelli che posso aspettare ma c'è anche chi NON PUO'.
 
A.


 2) l'utente lo cambia  e di dimentica di riavviare
 
Se deve esistere un parametro che, una volta cambiato, occorre riavviare 
l'applicativo, allora � un tuo dovere forzare il riavvio, altrimenti 
finisci tu stesso col favorire il verificarsi dei problemi da te descritti.


 finisci tu stesso col favorire il verificarsi dei problemi da te descritti.
 
 
Giusto ma non applicabile.
Quello che dici tu compoeterebbe un sistema di nodifica che mandasse un broadcast a tutti i client....
 
Imho, è molto piu' semplice, quando puoi,  NON CARICARE I PARAMETRI ALL'AVVIO ma leggerli ogni volta che ti servono. :-D
 
 
A. 
 

 morde
Non ho ben capito questo manager, anche se l'idea mi stuzzica. Sarebbe una 
unit dove crei questi oggetti e queste liste e li istanzi anche ?
Supponi per esempio che uno dei tanti oggetti sia una lista di conti 
contabili (una ObjectList di Account) usato da un form per farne un 
combobox, da un altro per estrarre l'info che gli serve, etc.
Cosa fai nel manager e cosa nelle form ? Puoi descriverlo in parole ? 
Grazie. 
 

 Ma questo non vale per tutti i dati di configurazione.
 
Sono d'accordo. Ad esempio, per un progetto leggo dei parametri di 
configurazione da file (soprattutto quelli relativi alla connessione al 
database) e, successivamente, leggo gli altri parametri su database. Fare in 
maniera differente significherebbe che per ogni modifica di parametro 
(modifica che comunque sarebbe fatta da altri sistemi e comunque riportata 
su database) richiederebbe un riavvio dell'applicativo, cosa inaccettabile 
visti i suoi scopi (leggere cicilicamente dei dati ad un intervallo di tempo 
stabilito)
 
Enrico

 Grazie.
 
Pensa ad una classe che, una volta istanziata, si carica nella pancia 
tutti i dati ad uso condiviso dalle form. Poi questa classe la puoi 
passare alla form che deve essere mostrata, e la form al suo interno ne 
fa l'uso che vuoi.
 
Prendiamo pi� un dettaglio il tuo esempio: io mi immaginerei che la tua 
form, una volta aperta, chiami un gestore di conti attraverso un oggetto 
comune che gli � stato passato, facciamo finta che sia l'oggetto "azienda".
Immagino che nel costruttore od un metodo di inizializzazione tu 
scriverai una cosa del genere:
 
tuoComboConti.setModel(Azienda.GetConti)
(ho inventato un setModel per indicare che gli passi il modello dei tuoi 
dati all'oggetto)
 
Il concetto � che tu fai girare il riferimento ai tuoi dati 
centralizzati attraverso tutti i form: ovviamente cos� risparmi memoria, 
il codice resta pi� pulito e facilmente manutenibile.
Immagino che lavori su un gestionale o similare, e che all'inizio 
l'utente decide su quale azienda lavorare. Questa azienda avr� i dati di 
dominio che sono unici e andranno utilizzati pi� volte, baster� 
caricarli all'inizio.
Azienda.GetConti ritorna la collezione dei conti
Azienda.Info.GetIndirizzo
Azienda.Info.GetPIVA
ecc. per farti dare i dati anagrafici
 
Se vuoi evitare il collo di bottiglia dei caricamenti, ti basta adottare 
una strategia di "lazy loading", ossia caricare i dati alla prima 
richiesta e poi tenerteli caricati (ovviamente solo di quei dati che non 
cambiano ad ogni fattura che emetti e se non tocchi le anagrafiche..). 
In questo modo i tempi di accesso vengono distribuiti in funzione 
dell'uso che far� l'utente del programma, dando l'impressione di 
performare di pi�.


 unit dove crei questi oggetti e queste liste e li istanzi anche ?
 
Il primo passo per evolvere consiste nel passare dai concetto di unit e funzioni a quelli di classe e metodi.
 
A.

 morde
Cos� mi � molto piu' chiaro. Ma quando dici "questa classe la puoi passare 
alla form", io immagino che questa classe istanziata nella Form principale 
abbia un nome che, definito nella sez interface, sia conosciuto a tutti i 
form. Immagino male ? Come "si passa" una classe ad un'altra form altrimenti 
? 
 

 form. Immagino male ? 
 
Decisamente si!
 
TMyBaseForm = class(TForm)
protected
    function DoSetup: integer; virtual;
public
  property SomeManager: TManager read FSomeManager write SetSomeManager;
  function Setup: integer;
end;
 
 
TMySpecificForm = class(TMyBaseForm)
protected
    function DoSetup: integer; override;
end;
 
 
procedure TMainForm.SomeButtonClick(Sender: TObject)
begin
   if (Not Assigned(FMySpecificForm)) then
   begin
      FMySpecificForm := TMYSpecificForm.Create(Nil);
   end;
 
   FMySpecifiForm.SomeManager := Self.SomeManager;
   FMySpecifiForm.Setup;
   FMySpecifiForm.ShowModal;
end;
 
 
Notare: nessun uso di robaccia globale.....
 
A.

Lo sapevo! Ma l'esempio finalmente mi ha chiarito e indirizzato sulla strada 
giusta. Grazie