Newsgroup: it.comp.lang.delphi
Titolo: Preve generali di OOP

Sempre in relazione all'argomento dei miei post precedenti (gestione di file
e cartelle in maniera "virtuale") sto cercando di creare una struttura OOP
adeguata e non vorrei commettere degli errori proprio in questa fase perchè
poi me li porterei dietro per tutto il progetto.
Per il momento (anche in base ad un suggerimento) ho scritto questa
struttura, ma fin da ora c'è qualcosa che non mi convince:
TTree = class
  Name: string;
  FileList: TObjectList;
  FolderList: TObjectList;
public
  constructor Create;
  function FindItemByCompletePathName(CompletePathName: string): TTreeItem;
end;
TTreeItem = class
  Name: string;
public
  constructor Create;
end;
TFolder = class(TTreeItem)
  FileList: TObjectList;
  FolderList: TObjectList;
public
  constructor Create;
end;
TFile = class(TTreeItem)
  Size: Integer;
public
  constructor Create;
end;
Inizialmente avevo solo le due classi TFolder e TFile e funzionava. Poi però
ho aggiunto le altre due (TTree e TTreeItem) perchè pensavo di mettere delle
procedure di utilità comune dell'albero (come la ricerca di un elemento).
La cosa che mi fa storcere il naso però è il fatto che TFolder è
praticamente uguale a TTree tranne per il fatto che non ha elementi comuni.
Qualche suggerimento o commento?
grazie
-- 
Lis
ICQ@Home #7317603sette     ICQ@Work #16285702tre
Mercatino: 
http://lis77.bravepages.com
 (aggiornato *con foto*: 16/06/03)


In effetti la somiglianza e' tanta (troppa).
Comunque l'utilita' dell'esistenza della classe TTree dipende da come 
hai intenzione di usare questa classe.
Ossia, se in TTree in futuro hai intenzione di aggiungere metodi e 
funzionalita' che lo differenziano da un TFolder, allora forse e' meglio 
mantenere la classe TTree. Oppure, se devi poter aggiungere nodi di tipo 
diverso da folder e file (es. "virtual folder", "Web site", "FTP 
server", "Printer", ...) il TTree sara' basilare per contenenre tutti 
questi oggetti.
Comunque ti suggerirei di documentarti sul design pattern "Composite", 
trovi una breve descrizione sul sito 
http://www.patterndigest.com/
, 
clicka su "composite". Nel diagramma, le classi disegnate hanno piu' o 
meno questa corrispondenza con le tue:
	Component = TTreeNode
	Composite = TFolder
	Leaf = TFile
Nota che nel caso del Composite Pattern, la classe base (Component) 
contiene un'unica lista dei componenti, cosa che potrebbe essere meglio 
anche nel tuo caso, in modo da lasciarti libera l'estensione a tipi 
diversi di nodi.
-- 
Roal Zanazzi

 diversi di nodi.
Ora provo a dargli una lettura, grazie


 trovi una breve descrizione sul sito 
http://www.patterndigest.com/
, 
Altri indirizzi che ho trovato che potrebbero essere utili anche ad altri: 
http://sern.ucalgary.ca/courses/SENG/443/W02/assignments/Composite/index.html
 
http://www.ugolandini.net/CompositePattern.html


Lis wrote:
<SNIP>
Cosě per scherzo ho provato a buttare giů due righe (anche perchč potrebbero 
servirmi in un progettino che ho in mente).
Le trovi qui: 
http://www.emmeit.net/andrea/fs.zip
Sono scritte con Kylix ma basta copia-incollare dai .pas...
Ciao :-)
-- 
Andrea /\/\agni
ICQ# 174108000

 Le trovi qui: 
http://www.emmeit.net/andrea/fs.zip
Che dire...grazie 1000, è uno spettacolo!! Ci sono tante di quelle finezze
nella scrittura del codice che io non mi immaginavo nemmeno, non mi resta
che inchinarmi, si vede proprio che sono un niubbo di delphi :-)
Ora sto cercando di capire tutte le classi fino in fondo, mi aspettavo
qualcosa di più semplice
ps. il tuo numero di icq è giusto? Mi viene fuori un cileno...


 
Altra nota: i cosiddetti "design pattern" sono piuttosto interessanti, 
fossi in te non mi fermerei al composite...
-- 
Roal Zanazzi

 
Bellino il codice :-)
Se permetti avrei qualche piccola critica/suggerimento:
0. qualche riga di commento, almeno per spiegare a cosa serve la unit, 
non sarebbe male ;-) No problem, visto che l'hai scritto velocemente...
1. I nomi delle classi TNode e TNodeList sono forse un po' generici e 
non richiamano immediatamente il concetto di "file system".
2. personalmente preferisco separare la "logica" dell'applicazione dalla 
sua rappresentazione per l'utente. In questo caso hai mischiato le due 
cose mettendo in TNode un metodo per mappare il nodo ad un nodo di 
treeview... e se poi volessi invece mapparlo a qualche altro controllo?
Io userei un sistema tipo il pattern MVC/MVP, per lo meno separando il 
dato (TNode = Model) dalla rappresentazione (TTreeView = View) 
disaccoppiandoli tramite una classe Controller o Presenter. In questo 
caso il Model e la View sono riutilizzabili, e puoi mappare il Model a 
diverse View cambiando solo il Presenter (es. puoi cominciare a scrivere 
un Presenter per mappare TNode alla TTreeView).
Ovviamente queste sono solo mie considerazioni personali, per il resto 
hai i miei complimenti (per quanto possano valere): ri rado si vede sui 
NGs codice cosi' pulito e scritto secondo i "crismi" del linguaggio ;-)
-- 
Roal Zanazzi

 linguaggio ;-)
Siete troppo buoni ... :-)
Ciao


 fossi in te non mi fermerei al composite...
Sì, ma in base a quanto ho detto sopra, non ho mai avuto la possibilità di
applicarli seriamente per cui, a parte il singleton, non ne conoscevo ancora
altri


 NGs codice cosi' pulito e scritto secondo i "crismi" del linguaggio ;-)
Su questo non posso che concordare, e ringraziare per il tempo dedicatomi
;-)


 il passo di portare TNode da classe ad interfaccia.
Mmmm...io invece al momento sto utilizzando principalmente (per esempio nei
parametri delle mie routines) la classe TNode in modo da poter utilizzare
qualunque oggetto che ne deriva e poi all'interno delle varie procedure,
dove serve, faccio la distinzione per i casi particolari. Mi sconsigliate
questa strada?


 Le trovi qui: 
http://www.emmeit.net/andrea/fs.zip
Sempre tenendo questa struttura come base (FsItem, FsItemList, FsFolder,
FsFile) sto cercando di espanderla per aggiungere un nuovo tipo di archivio
virtuale (FsArchive).
TFsArchive = class(TFsItem)
  private
    FFsItemList: TFsItemList;
  public
    constructor Create(AParent: TFsItem = nil); override;
    destructor Destroy; override;
    property FsItemList: TFsItemList read FFsItemList;
  end;
In sostanza FsArchive, a parte dei campi aggiunti, ha lo stesso
comportamento di FsFolder e puň quindi contenere file e cartelle. Dal mio
programma perň devo mostrare nel treeview sia i Folder che gli Archive e
quindi ho creato la nuova classe in modo che, quando poi disegno il
treeview, 'capisco' chi sto disegnando e comporarmi di conseguenza. Fino a
qui sarebbe tutto ok ma c'č un problema quando aggiungo file e cartelle ad
un oggetto FsArchive: come faccio a capire che sono figli di un FsArchive
oppure di un FsFolder? Devo creare due nuovi oggetti FsFileArchive e
FsFileFolder? A livello teorico non mi sembra la soluzione ideale...
Infine, visto che FsArchive e FsFolder sono simili, secondo voi puň aver
senso creare una classe FsContainer (esempio) da cui poi far derivare
FsArchive e FsFolder, in modo da raggrupparle?


 particolari. Mi sconsigliate questa strada?
No, va bene. Io intendevo che TNode č stata pensata (da me) come classe
astratta (come vedi io non istanzio mai un TNode sebbene sia possibile).


 FsFolder, in modo da raggrupparle?
A questa domanda puoi rispondere solo tu... (noi non conosciamo bene il
dominio applicativo) Se vale quello che hai scritto prima (cioè che Archive
è come un TFolder ma con qualcosa in più) io farei discendere Archive da
Folder...
Ciao :-)
Ps: scusa(te) il ritardo nei post ma sono stato qualche giorno sulle
Dolomiti :-)



Se Vi può essere utile Vi posto il codice che sto usando. Visualizza una
table con 4 campi indicizzati in sequenza (Prima ARE poi FON poi MAT e poi
SPE).
Si può aggiungere un bottone per cancellare un record in base ad
AbsoluteIndex di tTreeNode. E si può eseguire un normale Append.
Con append e delete si esegue l'edit del record.
Sono un centinaio di righe ma si possono ridurre specialmente se non si
usano le icone per definire i tipi di campi.
...
// _____________________
Procedure TForm1.Inizia ;
Var
    Are, Fon, Mat, Spe,
   pAre, pFon, pMat, pSpe : String ;
  tnAre, tnFon, tnMat, tnSpe, tnRoot : tTreeNode ;
Begin
  // tv = treeView
  pAre := '' ;
  pFon := '' ;
  pMat := '' ;
  pSpe := '' ;
  tv.Items.Clear ;
  With Table1 Do
    Begin
      Active := True ;
      First ;
      While Not Eof Do
        Begin
          Are := FieldByName ('Area').AsString ;
          Fon := FieldByName ('Fondamento').AsString ;
          Mat := FieldByName ('Materia').AsString ;
          Spe := FieldByName ('Specifica').AsString ;
          With tv.Items Do
            Begin
              If Are<>pAre Then
                Begin
                  If Are<>'' Then
                    Begin
                      tnAre := AddChild ( Nil, Are ) ;
                      tnAre.ImageIndex := 0 ;
                      tnAre.SelectedIndex := 0 ;
                    End ;
                  If Fon<>'' Then
                    Begin
                      tnFon := AddChild ( tnAre, Fon ) ;
                      tnFon.ImageIndex := 1 ;
                      tnFon.SelectedIndex := 1 ;
                    End ;
                  If Mat<>'' Then
                    Begin
                      tnMat := AddChild ( tnFon, Mat ) ;
                      tnMat.ImageIndex := 2 ;
                      tnMat.SelectedIndex := 2 ;
                    End ;
                 If Spe<>'' Then
                   Begin
                     tnSpe := AddChild ( tnMat, Spe ) ;
                     tnSpe.ImageIndex := 3 ;
                     tnSpe.SelectedIndex := 3 ;
                   End ;
                 End
              Else // Are
                If Fon<>pFon Then
                  Begin
                    If Fon<>'' Then
                      Begin
                      tnFon := AddChild ( tnAre, Fon ) ;
                      tnFon.ImageIndex := 1 ;
                      tnFon.SelectedIndex := 1 ;
                      End ;
                    If Mat<>'' Then
                      Begin
                      tnMat := AddChild ( tnFon, Mat ) ;
                    tnMat.ImageIndex := 2 ;
                    tnMat.SelectedIndex := 2 ;
                      End ;
                    If Spe<>'' Then
                      Begin
                      tnSpe := AddChild ( tnMat, Spe ) ;
                    tnSpe.ImageIndex := 3 ;
                    tnSpe.SelectedIndex := 3 ;
                      End ;
                  End
                Else // Fon
                  If Mat <> pMat Then
                    Begin
                      If Mat<>'' Then
                        Begin
                          tnMat := AddChild ( tnFon, Mat ) ;
                          tnMat.ImageIndex := 2 ;
                          tnMat.SelectedIndex := 2 ;
                        End ;
                      If Spe<>'' Then
                        Begin
                          tnSpe := AddChild ( tnMat, Spe ) ;
                          tnSpe.ImageIndex := 2 ;
                          tnSpe.SelectedIndex := 2 ;
                        End ;
                    End
                  Else // Mat
                    If Spe<>pSpe Then
                      If Spe<>'' Then
                        Begin
                        tnSpe := AddChild ( tnMat, Spe ) ;
                        tnSpe.ImageIndex := 3 ;
                        tnSpe.SelectedIndex := 3 ;
                        End ;
            End ; // With
          pAre := Are ;
          pFon := Fon ;
          pMat := Mat ;
          pSpe := Spe ;
          Next ;
        End ; // While
    End ; // With
End ;
--------------------------------
Inviato via 
http://usenet.libero.it

 astratta (come vedi io non istanzio mai un TNode sebbene sia possibile).
Anche io non istanzio mai un TNode (se non per chiarezza nel codice invece
che mettere cast ovunque), ma la uso per generalizzare i parametri nelle
procedure (essendo TFolder e TFile dei suoi derivati)


 Dolomiti :-)
Scusarti? E di che cosa, non sei mica mancato ad un appuntamento!! ;-)
Grazie per la 'consulenza' molto preziosa che mi stai fornendo


 Grazie per la 'consulenza' molto preziosa che mi stai fornendo
Non c'è di che, sapessi quante volte sono stato aiutato io sui ngs... :-)
