Newsgroup: it.comp.lang.delphi
Titolo: Scusate il problema banale

Questa è una cosa semplice, ma nella quale è un'ora che mi sono impigliato. 
Magari voi me la risolvete in quattro e quattr'otto.
In un form sistemo una frame che ha diversi componenti tipo ListBox, 
comboBox etc.
In una unit separata volevo mettere alcune proc che riempiono gli items di 
questi componenti e anche che, una volta che l'utente ha fatto le sue 
scelte, ritornano al main form le scelte fatte (in forma di stringa per una 
sql).
 
Ma quando in queste proc referenzio, ad esempio ListBoxAnni, questo risulta 
'Undeclared identifier'.
Negli uses della proc avevo messo la unit della frame, ma dà errore.
Come faccio a far conoscere a questa unit separata i componenti della frame 
? 
 

 ?
 
Finchè non salirai lo scalino DIMENTICANDO l'approccio strutturato e abbracciando una buona e sacrosanta volta OOP, avrai sempre problemi di questo tipo con le conseguenti, per tua stessa ammissione, perdite di tempo.
Come tanti, troppi, pur di risparmiare non badi a spese.
 
 
Il frame DEVE ESPORRE un metodo che accetta come parametro una TStrings/TStringList. 
Avrai un metodo per ogni listbox.
Questo metodo non fa altro che cliclare sugli items della listbox di turno e aggiungere alla lista passata come parametro quelli selezionati.
Quindi, se hai 3 listbox:
 
TTUoFrame = class...
public
  ...
  procedure ReadSelectedModels(AList: TSTringList);
  procedure ReadSelectedSexPositions(AList: TSTringList);
  procedure ReadSelectedWines(AList: TSTringList);
  ...
end;
 
...
 
procedure TTUoFrame.InternalReadSelection(
  AListBox: TListBox; 
  AList: TSTringList);
var
  i: integer;
 
begin
  Assert( Assigned(AList));
  Assert( Assigned(AListBox));
  AList.Clear;
  for i := 0 to Pred(AListBox.Count) do begin
    if AListBox.Selected[i] then 
      AList.Add(AListBox[i])
  end;
end;
 
procedure TTUoFrame.ReadSelectedModels(AList: TSTringList);
begin
  InternalReadSelection(lbxModels, AList);
end;
 
procedure TTUoFrame.ReadSelectedSexpositions(AList: TSTringList);
begin
  InternalReadSelection(lbxSexPositions, AList);
end;
 
etc etc etc
 
A.

"Alberto Salvati"  ha scritto nel messaggio 
news:fe4424dc-426b-471c...@googlegroups.com...
Finchè non salirai lo scalino DIMENTICANDO l'approccio strutturato e 
abbracciando una buona e sacrosanta volta OOP, avrai sempre problemi di 
questo tipo con le conseguenti, per tua stessa ammissione, perdite di tempo.
Come tanti, troppi, pur di risparmiare non badi a spese.
A.
--
Prima scrivo queste due righe, poi mi vado a studiare il tuo 'insegnamento'. 
A te sembrerà triviale, ma io ricordo quello che mi disse un istruttore ad 
un corso di OOP a cui partecipai vent'anni fa senza alcun profitto. Mi disse 
che avendo seguito fino ad allora un approccio strutturato, non avrei mai 
imparato l' OOP. Purtroppo aveva ragione! E pensare che sono affascinato 
dall'OOP e ne capisco tutte le potenzialità e vantaggi.. 
 

Ah, grazie intanto !


sono daccordo, l'OOP è una cagata pazzesca ingiustificata nella normale 
programmazione gestionale.
Molto meglio una raccolta di librerie.....funzionano sempre!
 
-- 
Ripristinare il trattato di Vienna è imperativo!
W IL LOMBARDO-VENETO.
W LA LIBERTA'.
ONORE E GLORIA A S.M. CARLO D'ASBURGO-LORENA!!!

Ma che cazzo dici?
 
A.

Non è triviale: è una cazzata.
Ti stai autolimitando nascondendoti dietro un dito.
 
In questo lavoro, ma credo in tanti, l'inizio della fine è smettere di imparare. 
 
Io sto mollando delphi per passare a jee e TOZZO; intanto sto sviluppando su android studio e sto tozzando; inoltre, sto guardando aws, pentaho e forse farò un cosrso su scrum.
Aggiungo che ho 48 anni e non sono quindi un moccioso.
Capisco bene che non è facile, ovvio, ma la vita non è facile e non sta scritto da nessuna parte che deve esserlo.
 
Dici di capire potenzialità e vantaggi della OOP.
Allora che aspetti?
Fai un favore a te stesso: cresci, impara, sbattiti, tozza.
 
A.
 
 

"Alberto Salvati"  ha scritto nel messaggio 
news:fe4424dc-426b-471c...@googlegroups.com...
TTUoFrame = class...
public
  ...
  procedure ReadSelectedModels(AList: TSTringList);
  procedure ReadSelectedSexPositions(AList: TSTringList);
  procedure ReadSelectedWines(AList: TSTringList);
  ...
end;
procedure TTUoFrame.InternalReadSelection(
  AListBox: TListBox;
  AList: TSTringList);
var
  i: integer;
begin
  Assert( Assigned(AList));
  Assert( Assigned(AListBox));
  AList.Clear;
  for i := 0 to Pred(AListBox.Count) do begin
    if AListBox.Selected[i] then
      AList.Add(AListBox[i])
  end;
end;
procedure TTUoFrame.ReadSelectedModels(AList: TSTringList);
begin
  InternalReadSelection(lbxModels, AList);
end;
etc etc etc
A.
--
Ho letto bene il tuo suggerimento e vorrei porti qualche domanda. Tu non lo 
dici, ma immagino che la proc InternalReadSelection sia private.
Inoltre, perchè hai una proc per ogni ListBox ? Non poteva essere una sola 
proc con due parametri, dove uno era la specifica ListBox e l'altra la 
StringList?
Infine, volendo fare qualcosa di simile per caricare le ListBox ( da 
Dataset), è meglio per esempio eseguire una query nella main form e passare 
1) il risultato come result set, 2) come stringList, 3) passare alla frame 
il nome del dataset e fare tutto lì ? 
 

> Io sto mollando delphi per passare a jee e TOZZO; intanto sto sviluppando su android studio e sto tozzando; inoltre, sto guardando aws, pentaho e forse farò un cosrso su scrum.
mia curiostia' : cosa ti ha fatto preferire Android Studio (Java) a 
Xamarin (C#) integrabile anche con Visual Studio ?
 

 il nome del dataset e fare tutto lì ?
Perchè il nome? Poi come lo usi?
 
 
 
A.

 il nome del dataset e fare tutto lì ?
Perchè il nome? Poi come lo usi?
==> Non potrebbe essere una proc interna al frame che autonomamente esegue 
una query sul nome di dataset passato? Oppure è meglio farlo fare al form e 
passare un'altra StringList ..?
 
Scusami, ma come vedi una cosa che posso fare in due minuti, l'approccio OOP 
me la fa sentire complicata. Ma voglio farla xchè capisco che dovrebbe 
essere anche più semplice.
 
 

 essere anche più semplice.
 
Ecco: questa è la via.
 
A.

 con la quale caricare la listBox
Aridaglie..ok... faccio la domanda col cucchiaino:
procedure TTuoFrame.BeccatiRisultatoQuery(Qualcosa: <...>)
Cosa scriveresti al posto di <...>?
==> StringList ?
 
Quindi suggeriresti da eseguire le query per caricare le listBox nel form e 
usare il metodo sopra (beccati..) per passarle alla frame ?
Ma se la frame la uso da più di un form, non devo rifare questo più volte ?
 
Scusami, approfitto perchè tu mi fai capire le cose. Non ti incoraggio, ma 
puoi mandarmi a far benedire .. 
 

 Ma se la frame la uso da più di un form, non devo rifare questo più volte ?
 
Ci sono 2 punti di vista..
 
1) il frame è totalmente passivo e mostra i dati che che chi usa il frame stesso gli passa
 
2) il frame è autonomo e fa da se le query che gli servono.
 
Adesso un altro piccolo passo: descrivi pro e contro di questi 2 approcci.
 
A.


 ?
Ci sono 2 punti di vista..
1) il frame è totalmente passivo e mostra i dati che che chi usa il frame 
stesso gli passa
2) il frame è autonomo e fa da se le query che gli servono.
A.
--
Nel 1o caso, il frame ha meno responsabilità di suo, però potrebbe essere 
più flessibile nel caso cambiasse la logica con cui ricavo i dati che gli 
passo. Però tutte le unit che lo utilizzano si devono smazzare la logica del 
reperimento dei dati.
Nel 2o caso, il frame mi sembrerebbe più autonomo, anche se più rigido. Ma 
d'altronde xchè la logica dovrebbe cambare ? E sgrava gli utilizzatori. Però 
deve vedere un dataset esterno, oggi TTable o TQuery, domani spero qualcosa 
di diverso..
 
Secondo te ? 
 

 di diverso..
 
Vedi sopra.
 
A.
 

 Ma d'altronde xchè la logica dovrebbe cambare ?
Io non lo so. Tu lo sai? Sai PER CERTO che la logica non cambierà MAI o 
magari cambierà tra 10 anni o IERI?
A.
==>
Caro Alberto, non credo di dovermi preoccupare tra 10 anni ..
 
Beh, credo che mi metterò a pensare a questo loader 
 

 imparato l' OOP.
 
Ti ha detto una gran cazzata. Da quale approccio credi venissero coloro che, come me, ad un certo punto hanno imparato il paradigma oo? Piuttosto credo ti abbia detto che se continuerai a guardare ai problemi in termini procedurali, non apprenderai mai la programmazione orientata agli oggetti.

"4ndre4"  ha scritto nel messaggio 
news:6a525aab-5284-4f35...@googlegroups.com...
Ti ha detto una gran cazzata. Da quale approccio credi venissero coloro che, 
come me, ad un certo punto hanno imparato il paradigma oo? Piuttosto credo 
ti abbia detto che se continuerai a guardare ai problemi in termini 
procedurali, non apprenderai mai la programmazione orientata agli oggetti.
--
è possibile che quello intendesse, si.. 
 

Torno sull'argomento perchè, avendo risolto il problema di fare il load dei 
dati necessari alle listbox con una classe così:
 
TObjList = class(TObjectList)
private
  function   GetItems (const Index: integer): TTitolo;
  procedure SetItems (const Index: integer; value: TTitolo);
public
  property  Items[const Index: integer]: TTitolo read GetItems write 
SetItems; default;
  constructor Create; virtual;
  function LoadObjList (aDataset: TDataset): TObjList;
  function LoadObj (aRecord: TDataset): TTitolo;
end;
 
adesso volevo rendere la classe utilizzabile ogni volta che devo caricare 
dei dati, anche di vario genere. In effetti, i metodo della classe suddetta 
fanno riferimento allo specifico oggetto TTitolo, e in particolare 
'LoadObjList' usa LoadObj che restituisce un oggetto TTitolo.
 
Vorrei per esempio fare la stessa cosa con oggetti di tipo TBudget, ma non 
ho trovato il modo. C'è ?
 

 TObjList = class(TObjectList)
 
Ti stai facendo del male. Non si deve derivare una classe TObjList da TObjectList. Se proprio vuoi fare una cosa del genere (e sono sicuro che esistano soluzioni migliori al tuo problema), devi avere una classe TTuoLoader che accetti un dataset ed una objectlist e contenga la logica di popolamento.

"4ndre4"  ha scritto nel messaggio 
news:64b63fec-7a3d-4d82...@googlegroups.com...
Ti stai facendo del male. Non si deve derivare una classe TObjList da 
TObjectList. Se proprio vuoi fare una cosa del genere (e sono sicuro che 
esistano soluzioni migliori al tuo problema), devi avere una classe 
TTuoLoader che accetti un dataset ed una objectlist e contenga la logica di 
popolamento.
...
Avrai ragione, ma non mi puoi spiegare perchè non si fa? E come invece si fa 
?
 

 ?
 
Ma tu le leggi le risposte che ti vengono scritte o scrivi tanto per farlo? "Come invece si fa" e` scritto precisamente nel mio messaggio a cui stai rispondendo. Ti ho detto che devi crearti un TTuoLoader. A te sembra normale che, se esiste una classe TObjectList, tu debba crearne un'altra chiamata "TObjList" (?) che semplicemente la estenda per fare qualcosa in piu` che serve a te, nello specifico? E` un chiaro design smell, ma non e` che posso farti qui un intero corso di OO. Comincia a studiare: 
 
https://en.wikipedia.org/wiki/Composition_over_inheritance
 
 

"4ndre4"  ha scritto nel messaggio 
news:f9bb9bda-702d-40f7...@googlegroups.com...
Ma tu le leggi le risposte che ti vengono scritte o scrivi tanto per farlo? 
"Come invece si fa" e` scritto precisamente nel mio messaggio a cui stai 
rispondendo. Ti ho detto che devi crearti un TTuoLoader. A te sembra normale 
che, se esiste una classe TObjectList, tu debba crearne un'altra chiamata 
"TObjList" (?) che semplicemente la estenda per fare qualcosa in piu` che 
serve a te, nello specifico? E` un chiaro design smell, ma non e` che posso 
farti qui un intero corso di OO. Comincia a studiare:
---
Le leggo, ma io con quella classe pensavo proprio di aver fatta quello che 
tu suggerisci come TTuoLoader. Per quello avevo derivato la classe da 
TObjectList: per dargli un metodo LoadObjList che accede alla fonte dei dati 
(un dataset) e carica nella objectList tanti oggetti TTitolo, che sono poi i 
records di una tabella Titoli.
E sto proprio studiando, è per quello che faccio qualche tentativo di object 
orientation, sbagliando vedo ... 
 

 TObjectList: per dargli un metodo LoadObjList
 
E io ti ho spiegato che non bisogna derivare, ma costruire un TTuoLoader che abbia un metodo che accetti un dataset e una tobjectlist e carichi i dati. Ce la fai a capire, detta cosi`, o hai bisogno che ti si scriva il codice?

Questa classe è SBAGLIATA.
 
A.

"4ndre4"  ha scritto nel messaggio 
news:276331f3-ad3c-4fc7...@googlegroups.com...
E non hai neanche letto l'articolo che ti ho linkato. Tu non vuoi imparare a 
risolvere i tuoi problemi, tu vuoi qualcuno che ti dia la pappa pronta.
--
Ma perchè siete ossessionati dalla paura che uno voglia la pappa fatta ? 
Capisco che ti devo ringraziare per il solo fatto che interagisci con me, ma
non è vero che voglio la pappa fatta, magari solo un esempio! L'ho letto 
l'articolo, non ho difficoltà con l'inglese, ma quando leggo la teoria tutto 
mi sembra chiaro, poi non riesco a mettere in pratica. Provo ad interpretare 
quello che mi hai detto e riparto dalla classe che avevo fatto io e che è, 
ok, sbagliata. Dovrebbe essere rifatta sul tipo di quanto segue ?
TLoader = class
private
  MyObjects: TObjectList;
public
  function LoadObjList (aDataset: TDataset): TObjectList;
end; 
 

 non è vero che voglio la pappa fatta, magari solo un esempio! 
 
L'esempio e` nel periodo che ho scritto nel messaggio precedente. Non ha senso che mostri il tuo loader perche` manca tutto il resto della logica della tua applicazione per capire se vada bene o meno. Devi prendere spunto da quel che ti si consiglia ed applicarlo al tuo caso.
 

 end;
 
Un bel respiro prfondo, rileggi questo frammento di codice e rifletti.
E mo scrivi perchè, scusami ma devo dirtelo, hai scritto un altra cazzata.
 
A.
 

 end;
Un bel respiro prfondo, rileggi questo frammento di codice e rifletti.
E mo scrivi perchè, scusami ma devo dirtelo, hai scritto un altra cazzata.
A.
----
Scusa, ma non vedo niente. Salvo forse che MyObjects è una proprietà inutile 
messa così... Mi basterebbe LoadObjList. 
 

 messa così... Mi basterebbe LoadObjList.
 
Che vuol dire "forse"?
 
A.
 
 

 messa così... Mi basterebbe LoadObjList.
Che vuol dire "forse"?
A.
=> forse xchè potrebbe farmi comodo che la lista degli oggetti 'Titolo' di 
cui farei il load con LoadObjList potesse essere una property della classe, 
così mi rimane lì a disposizione per altro.. Solo una ipotesi accademica, 
altrimenti toglierei il forse e dire che non serve.
E' giusto? 
 

 
Ancora ipotesi e ancora "forse".
 
Allontanati dal pc, prendi un foglio e una matita ed elenca i casi nei quali sta cosa ti serve, e per ogni caso, scrivi se è meglio avere una lista passata da fuori o una property fissa della tua classe popolata di volta in volta.
La tua classe, così come l'hai descritta, crea una lista che sarà usata da altri che dovranno ricordarsi di distruggerla quando non servirà piu'.
Per contro, in c# e java (che hanno il garbage collector) una sintassi del genere ci sta.
 
Infine, torniamo a quello che ho scritto: la tua classe è sbagliata.
Spiega perchè.
 
A.
 
 
 

 Delphi ha il garbage collector?
 
Cosa c'entri la presenza di un GC o meno, lo sai solo tu.

 La tua classe, così come l'hai descritta, crea una lista che sarà usata da altri che dovranno ricordarsi di distruggerla quando non servirà piu'.
 
Basterebbe aggiungere un costruttore a cui passare la lista di oggetti. La classe non deve necessariamente instanziare la lista, puo` semplicemente gestire una lista passata dal di fuori.
 

"Alberto Salvati"  ha scritto nel messaggio 
news:717d8bc2-b83c-495e...@googlegroups.com...

---
Ho cercato di ragionarci, ma sono ancora confuso. Cominciamo dall'obiettivo: 
disporre di una lista di 'oggetti' (ad esempio titoli di un portafoglio di 
investimento), prelevati pari pari da un dataset (gli oggetti servono, 
singolarmente e insieme, alla logica operativa di vari programmi).
Faccio due ipotesi:
1-la classe ha solo il metodo di Load e restituisce una ObjectList al 
chiamante ogni volta che la istanzio (potrei eseguire il Load al Create)
In questo caso la lista è posseduta dal programma che usa il metodo. 
Qualsiasi altro programma dovrebbe dichiarare una Lista simile e creare una 
istanza della classe (ripetendo il load) per avere gli oggetti nella lista.
2-la classe ha un metodo load e una property Lista. Avevo pensato a questa 
ipotesi per avere la lista disponibile a tutti, ma credo di ricadere nei 
vantaggi e svantaggi della ipotesi 1..
Perchè è sbagliata ?
 

 singolarmente e insieme, alla logica operativa di vari programmi).
 
Supponendo TStock rappresenti il tuo titolo di investimento.
Laddove ti serva una lista di titoli, avrai la tua TObjectList<TStock> 
Come ottieni la lista di titoli a partire dal dataset? Con una classe loader.
In pseudocodice:
 
TStocksLoader:
    procedure LoadStocks(ADataSet: TTuoDataset; AStockList: TObjectList<TStock>);
 
o, in alternativa:
 
TStocksLoader:
    function LoadStocks(ADataSet: TTuoDataset): TObjectList<TStock>;
 
La prima opzione lavora su una lista inizializzata dal chiamante; la seconda su una lista inizializzata dal loader stesso. La prima puo` ritornarti utile se vuoi riutilizzarla sulla stessa lista, senza necessariamente doverne creare una nuova se vuoi ricaricare i dati - ma e` un vantaggio irrilevante. 
 
In entrambi i casi, e` responsabilita` del chiamante distruggere la lista, ovviamente.