Newsgroup: it.comp.lang.delphi
Titolo: progettazione componente

Buongiorno a tutti,
mi sto incartando sulla progettazione di un componente e vorrei una 
dritta.
 
Il componente si occupa di visualizzare a video e permettere la 
modifica di una Tcollection.
Chiaramente al componente passerò delle sottoclassi di TCollection, ma 
attraverso RTTI riesco a gestire bene tutto.
L'unica cosa che a questo punto mi rimane ostica è, qualora per 
modificare un item, avessi la necessità di fare un lookup, è più 
corretto che sia il componente, il client del componente, o la 
collection stessa a sapere come deve essere fatto il lookup?
 
ovviamente sono ben accette tutte le critiche e le idee, tanto sono in 
fase di refactoring, quindi se c'è da stravolgere il componente è il 
momento buono per farlo! :-[
 
-- 
Emanuele Desideri
 
 

 collection stessa a sapere come deve essere fatto il lookup?
 
La collection deve esporre dei metodi di lookup, poihcè è la collection 
specifica di quell'oggetto, lo conosce e deve avere l'intelligenza 
necessaria per organizzarsi l'elenco di oggetti al suo interno, 
trovarli, cancellarli.
 
Se necessario, fornisci anche più metodi per un lookup specifico 
(findByName, findByCode,findByID), dove la ricerca ritorna NIL se 
l'oggetto non è stato trovato, o il reference dell'oggetto trovato.
 
Per quanto riguarda i tempi di ricerca: in che modo eseguiresti il 
lookup? Scorrendo sequenzialmente la collezione finchè non trovi 
l'elemento cercato, o costruendo internamente delle strutture 
ottimizzate per la ricerca?
 
-- 
morde
Android
QT 4.7
Delphi (5,6,7.. expired)
Firebird Database
 

 ArrayList, LinkedList, Vector, HashMap, HashSet, ArraySet,
 > Queue and Stack structures to Delphi/Kylix.
 > It also provides algorithms like in STL (Apply, Found, CountObject, 
Copy, Generate, Fill, Reverse, Sort...).
 
Personalmente parlando, io userei per ogni lookup una mappa: le mappe 
funzionano tramite chiavi di ricerca, per cui ad ogni item che aggiungi 
devi fornire la chiave di ricerca corrispondente.
Una volta popolata, la map offre tempi di ricerca ottimali.
Per farti un esempio, se usi una mappa con 1 milione di elementi, e ne 
cerchi uno qualsiasi, il tempo massimo di ricerca sarà, sempre, 
logaritmico, che è il più basso possibile (computazionalmente parlando).


 o costruendo internamente delle strutture ottimizzate per la ricerca?
 
ciao morde,
entro un po più nel dettaglio con un esempio.
//esempio di Item della collezione
TCondomino = class (TCollectionItem)
   private
    FPersona: TPersona;
    FMillesimi: Integer;
    //procedure setPersona(const Value: TSQLPersona);
   published
    property Persona: TPersona read FPersona write FPersona;
    property Millesimi: Integer read FMillesimi write FMillesimi;
 end;
//esempio di collezione
 TCondomini = class (TCollection);
.
.
.
//la collezione, viene instanziata così quando necessario
aColl := TCondomini.Create(TCondomino);
 
Ora, passo questa collezione ad un componente (un TFrame specializzato)
che si occupa di visualizzare le informazioni della collection.
si occupa inoltre di gestire l'interazione dell'utente modificando la 
collection. il tutto con l'uso della rtti così da non dover "conoscere"
nè chi gli passa la collection, nè la collection stessa.
 
Prendendo in esame l'esempio però, è facile intuire che se volessi 
assegnare un oggetto TPersona alla collection, dovrò sceglierla da un 
elenco di oggetti TPesona, da qui l'esigenza di fare il lookup.
 
Per suddetto lookup avrei un'altro componente che passato un elenco, è 
in grado di restituirmi l'oggetto o gli oggetti selezionati.
 
detto questo, mi confermi è la via giusta è che la collection sappia 
fare il lookup del campo Persona?
 
grazie!
 
-- 
Emanuele Desideri
 
 

 aColl := TCondomini.Create(TCondomino);
 
questo ï¿œ concettualmente sbagliato: un owner ideale potrebbe essere il 
form di gestione della collezione.


 di gestione della collezione.
 
No, ALT! TCondomini ï¿œ la collection e TCondomino ï¿œ l'item.
Facendo TCondomini.Create(TCondomino) instanzio una collezione di item 
di tipo TCondomino, o sto sbarellando??
 
-- 
Emanuele Desideri
 
 

 di gestione della collezione.
 
Per un attimo mi hai gettato nel panico. :'( Così ho cercato conforto 
nell'help.
 
constructor Create(ItemClass: TCollectionItemClass);
 
Call Create to instantiate a TCollection object at run time. Typically, 
TCollection descendants are created by a component that uses the 
collection to implement a property.
 
ItemClass identifies the TCollectionItem descendants that must be used 
to represent the items in the collection. The Add method uses this 
class to create items of the appropriate type.
 
B-)
 
-- 
Emanuele Desideri
 
 

 to create items of the appropriate type.
 
Perfetto, così si risponde ;)
Avevo confuso l'uso che viene fatto del costruttore della TCollection 
con l'uso di un normale costruttore dove di solito gli passi l'owner.
 
grazie!


 Si è corretto.
 
Mi è venuta un'idea ma necessito di qualche dritta.
La premessa è che pur avendo dato un'occhiata proprio ultimamente 
all'uso delle interfacce, non le ho mai usate.
detto ciò ti espongo la mia idea.
 
se creassi un'interfaccia ILookupable che espone i metodi necessari al 
lookup, la implementassi in una classe che derivi da TInterfaceObject e 
da ILookupable (es. TLookupable).
A questo punto potrei dichiarare (negli oggetti per cui è necessario, 
anzi volendo direttamente nella classe base da cui i miei oggetti 
derivano) una property di tipo ILookupable.
qualcosa tipo questo:
 
TMiaClasseBaseOggetto = class (TSuperClasseOggetti, IInterface, 
ILookupable)
...
property Lookup: ILookupable read Lookup implements ILookupable;
...
 
può funzionare?
è una buona idea?
è vantaggiosa?
 
-- 
Emanuele Desideri
 
 

 è vantaggiosa?
 
Dal punto di vista del software design, dovresti prima descrivere 
l'interfaccia ILookupable: che cosa fa?
Un oggetto, di suo, è già "cercabile" dal momento in cui espone delle 
proprietà: sta alla collection che lo contiene di esporre un metodo che 
ne permetta la ricerca.
 
Faccio un piccolo esempio: tu istanzi molti oggetti TPersona.
Ogni Tpersona espone una proprietà ID, che rappresenta una PK.
Aggiungi tutte queste istanze ad una collezione (generica o tipizzata) 
TPersone. La collezione ha il metodo cercaID(var ID:string) che ritorna 
un reference all'istanza corretta di TPersona se l'ha trovata, o NIL se 
non l'ha trovata.
 
In questo caso, come vedi, la collezione ti permette di cercare una 
persona dato uno specifico ID. Non è necessario che TPersona implementi 
l'interfaccia ILookupable (per come la vedo io, ma non è vangelo quello 
che dico).


Morde ha detto questo mercoledì :

si questo si, ma stiamo parlando di due cose diverse credo. provo a 
spiegarmi meglio.
prendiamo la mia collezione di tcondomino.
tcondomino aggrega tpersona ad altre proprietà come abbiamo visto 
prima.
ad un certo punto la mia collezione viene mostrata a video e l'utente 
deve poterci interagire.
nel momento in cui l'utente vuole assegnare una persona all'item 
tcondomino, dovrà sceglierla da un elenco.
al momento ho un oggetto che si occupa di questo, al quale passo un 
elenco ed è in grado di tornarmi l'id, gli id, la riga, le righe, 
l'oggetto o gli oggetti selezionati.
ora io dico, il saper usare questo componente a chi spetta?
non può essere utile "aggregarlo" agli oggetti che possono essere 
soggetti a lookup?
spero di essermi spiegato meglio!
e comunque grazie di tutte le dritte!
 
-- 
Emanuele Desideri
 
 

 soggetti a lookup?
 
IMHO,  come la collection ed i suoi item non hanno motivo di conoscere
come saranno mostrati (immagino non ci sia un reference per il frame),
cosi' un elenco non ha motivo di conoscere chi lo dovrà rappresentare
(il componente); tantomeno, dovrà conoscerlo la collection che il
componente dovrebbe andare a modificare.
 
Potresti vedere i pattern MVC e Observer.
 
Saluti
Paolo Arosio

 componente dovrebbe andare a modificare.
Quello che sto cercando di fare è proprio generalizzare e disaccoppiare 
alcuni componenti che invece ora sono accoppiati.
 
grazie della dritta!
 
-- 
Emanuele Desideri