OVH Cloud OVH Cloud

Objets

17 réponses
Avatar
cppnews
Bonjour,
- Pour construire la list des repertoires ainsi que les fichiers que
contient chacun, avec l'hypothese que chaque repertoire ne peut
contenir que des fichiers, l'implementation la plus simple que j'ai pu
trouver est:

+ Un objet repertoire : Attributs vector <string> *listOfFiles, et le
nom du repertoire
+ Un Objet catalog : Atributs vector <reportoire> *listOfDirs.

c'est basic, simple est =E7a fonctionne :)
Les choses deviennent plus compliqu=E9s si un repertoire peut contenir
d'autre repertoires, et la soit je change mon design (je seche) ou il
faut que mon objet repertoire doit contenir d'autres objets du m=EAme
type (la je seche aussi)
Y'a t il des patterns dans ce sens ?
J'espere avoir bien defini mon probleme.
Merci.

--
puff

7 réponses

1 2
Avatar
Laurent Deniau
Loïc Joly wrote:
Pourquoi compliquer les choses? Un type File d'un cote et un type
Directory qui contient un vector de Directory et un vector de File.
Directory fourni deux iterateurs, l'un sur les directories et l'autre
sur les files. L'interface en sera plus simple comme ceci il me semble.

Je ne vois pas pourquoi ici on devrait faire une hierarchie ou
melanger les deux types.


Parce qu'il peut y avoir des opération que l'on souhaite faire à tous
les éléments, comme par exemple effacer, modifier des droits d'accès,
obtenir un nom... Ca peut me sembler légitime.


D'accord, mais je ne vois pas en quoi cela doit faire parti de la classe
elle-meme. Rien n'empeche d'utiliser des fonctions avec un namespace
commun et des overload qui ont le merite d'etre ouvert pour de futurs
ajouts de fonctionnalite. La force du C++, c'est la multiplicite des
paradigmes alors je me mefie des apparences qui veulent toujours tout
mettre dans une hierarchie OO. Je prefere une interface non-OO pour sa
flexibilite et son extensibilite (et aussi le fait qu'aucun argument
n'est prioritaire) et des structures sous-jacentes OO pour le
polymorphisme et l'encapsulation.

Au final, l'utilisateur d'un File et d'un Directory devra utiliser des
algorithmes differents pour les parcourir, l'un '1D' (un iterateur) et
l'autre '2D' (deux iterateurs). Alors plutot que de mettre dans la
boucle interieur un test du style if (f.isDirectory()) je prefere avoir
deux iterateurs. Il y a certes des cas ou on pourrait applatir l'arbre
et le voir comme une liste uniforme d'objets, mais rien n'empeche a
Directory de fournir un tel iterateur - c'est a dire un iterateur qui
descendrait automatiquement dans les repertoires ou passerait aux
fichiers automatiquement une fois que les repertoires seraient tous
parcourus. Note qu'un tel iterateur serait passablement complique
puisqu'il doit avoir une pile en interne.

a+, ld.


Avatar
Michael DOUBEZ
Loïc Joly wrote:
Pourquoi compliquer les choses? Un type File d'un cote et un type
Directory qui contient un vector de Directory et un vector de File.
Directory fourni deux iterateurs, l'un sur les directories et l'autre
sur les files. L'interface en sera plus simple comme ceci il me semble.

Je ne vois pas pourquoi ici on devrait faire une hierarchie ou
melanger les deux types.


Parce qu'il peut y avoir des opération que l'on souhaite faire à tous
les éléments, comme par exemple effacer, modifier des droits d'accès,
obtenir un nom... Ca peut me sembler légitime.


D'accord, mais je ne vois pas en quoi cela doit faire parti de la classe
elle-meme. Rien n'empeche d'utiliser des fonctions avec un namespace
commun et des overload qui ont le merite d'etre ouvert pour de futurs
ajouts de fonctionnalite.


Rien ne l'empêche si ce n'est une duplication ce code pour chaque
overload. Les templates peuvent soulager cette partie là mais je ne vois
pas l'avantage d'avoir des objets découplés si ils partagent une même
interface.
Ca permet aussi d'avoir un système simple de composition pour les autres
types de fichiers (device, pipe, liens symboliques). Avec un directory
comme tu le décrit, il faudrais ajouter un vector pour chaque type de
fichier géré.

La force du C++, c'est la multiplicite des
paradigmes alors je me mefie des apparences qui veulent toujours tout
mettre dans une hierarchie OO. Je prefere une interface non-OO pour sa
flexibilite et son extensibilite (et aussi le fait qu'aucun argument
n'est prioritaire) et des structures sous-jacentes OO pour le
polymorphisme et l'encapsulation.


Tu veux dire qu'une interface 00 n'est pas flexible ou extensible ?
Je ne comprends pas. Je trouve la composition très puissante surtout
quand elle est utilisée avec un système de prototypage qui permet à
l'utilisateur de définir des objets composés gérés comme des objets simples.

Au final, l'utilisateur d'un File et d'un Directory devra utiliser des
algorithmes differents pour les parcourir, l'un '1D' (un iterateur) et
l'autre '2D' (deux iterateurs). Alors plutot que de mettre dans la
boucle interieur un test du style if (f.isDirectory()) je prefere avoir
deux iterateurs.


Une hiérarchie comme cela supporte typiquement le Visitor pattern car
elle n'a pas tendance à bouger alors que qu'il est probable que des
applications auront tendance à être ajoutée régulièrement.

Il y a certes des cas ou on pourrait applatir l'arbre
et le voir comme une liste uniforme d'objets, mais rien n'empeche a
Directory de fournir un tel iterateur - c'est a dire un iterateur qui
descendrait automatiquement dans les repertoires ou passerait aux
fichiers automatiquement une fois que les repertoires seraient tous
parcourus. Note qu'un tel iterateur serait passablement complique
puisqu'il doit avoir une pile en interne.


Je n'aimerais pas ne pas savoir la profondeur de l'itérateur ou savoir
comment il gère les liens symboliques (risque de boucle) et autres
joyeusetés.

Michael



Avatar
Laurent Deniau
Michael DOUBEZ wrote:
Loïc Joly wrote:
Pourquoi compliquer les choses? Un type File d'un cote et un type
Directory qui contient un vector de Directory et un vector de File.
Directory fourni deux iterateurs, l'un sur les directories et
l'autre sur les files. L'interface en sera plus simple comme ceci il
me semble.

Je ne vois pas pourquoi ici on devrait faire une hierarchie ou
melanger les deux types.


Parce qu'il peut y avoir des opération que l'on souhaite faire à tous
les éléments, comme par exemple effacer, modifier des droits d'accès,
obtenir un nom... Ca peut me sembler légitime.


D'accord, mais je ne vois pas en quoi cela doit faire parti de la
classe elle-meme. Rien n'empeche d'utiliser des fonctions avec un
namespace commun et des overload qui ont le merite d'etre ouvert pour
de futurs ajouts de fonctionnalite.


Rien ne l'empêche si ce n'est une duplication ce code pour chaque
overload. Les templates peuvent soulager cette partie là mais je ne vois
pas l'avantage d'avoir des objets découplés si ils partagent une même
interface.


Mais l'interface est alors fermee donc non extensible sans retoucher a
toutes les classes qui en derivent. Je prefere dedoubler qque fonctions
et ne pas etre bloque. Je suis peut-etre influence par mon domaine qui
demande enormement de flexibilite dans le code.

Ca permet aussi d'avoir un système simple de composition pour les autres
types de fichiers (device, pipe, liens symboliques). Avec un directory
comme tu le décrit, il faudrais ajouter un vector pour chaque type de
fichier géré.


Non, parce que la on parle effectivement de decliner des variantes
d'etats, donc le polymorphisme est l'outils adequat: device, pipe et
liens deriveront de File tandis que les repertoires montes deriveront de
Directory.

La force du C++, c'est la multiplicite des paradigmes alors je me
mefie des apparences qui veulent toujours tout mettre dans une
hierarchie OO. Je prefere une interface non-OO pour sa flexibilite et
son extensibilite (et aussi le fait qu'aucun argument n'est
prioritaire) et des structures sous-jacentes OO pour le polymorphisme
et l'encapsulation.


Tu veux dire qu'une interface 00 n'est pas flexible ou extensible ?


Oui, enfin pas dans un langage a typage statique ou la notion
d'interface joue un role essentiel. C'est ce que l'on appel une
architecture fermee. Les namespaces en revanche sont ouvert.

Je ne comprends pas. Je trouve la composition très puissante surtout
quand elle est utilisée avec un système de prototypage qui permet à
l'utilisateur de définir des objets composés gérés comme des objets
simples.


La composition n'est pas l'heritage. La composition est effectivement un
concept ouvert extrement flexible. Mais il est bride par les interfaces
qui elle, sont fermees. A moins d'avoir la delegation generique comme
dans COS ;-)

Au final, l'utilisateur d'un File et d'un Directory devra utiliser des
algorithmes differents pour les parcourir, l'un '1D' (un iterateur) et
l'autre '2D' (deux iterateurs). Alors plutot que de mettre dans la
boucle interieur un test du style if (f.isDirectory()) je prefere
avoir deux iterateurs.


Une hiérarchie comme cela supporte typiquement le Visitor pattern car
elle n'a pas tendance à bouger


Meme Common Lisp pensait (en 1995) avoir pense a tout sur ce point.
Rate, son systeme bien que tres flexible (et donc complique) n'est pas
portable et demande a l'utilisateur des precautions ou d'ecrire sa
propre interface/wrappers. Tout ca pour dire que meme si cela parrait
immuable en apparence, ca ne l'est peut-etre pas. Donc je favorise
toujours un design ouvert a l'ajout d'une couche de pattern.

alors que qu'il est probable que des
applications auront tendance à être ajoutée régulièrement.

Il y a certes des cas ou on pourrait applatir l'arbre et le voir comme
une liste uniforme d'objets, mais rien n'empeche a Directory de
fournir un tel iterateur - c'est a dire un iterateur qui descendrait
automatiquement dans les repertoires ou passerait aux fichiers
automatiquement une fois que les repertoires seraient tous parcourus.
Note qu'un tel iterateur serait passablement complique puisqu'il doit
avoir une pile en interne.


Je n'aimerais pas ne pas savoir la profondeur de l'itérateur ou savoir
comment il gère les liens symboliques (risque de boucle) et autres
joyeusetés.


Le mieux est de partir avec un design et d'ecrire quelques algos pour
voir si effectivement ils sont generalisables sans distinction
File-Directory et sans compliquer inutilement l'ensemble. Ensuite on
choisi l'un ou l'autre des deux design.

a+, ld.




Avatar
Michael DOUBEZ
Michael DOUBEZ wrote:
Loïc Joly wrote:
Pourquoi compliquer les choses? Un type File d'un cote et un type
Directory qui contient un vector de Directory et un vector de File.
Directory fourni deux iterateurs, l'un sur les directories et
l'autre sur les files. L'interface en sera plus simple comme ceci
il me semble.

Je ne vois pas pourquoi ici on devrait faire une hierarchie ou
melanger les deux types.


Parce qu'il peut y avoir des opération que l'on souhaite faire à
tous les éléments, comme par exemple effacer, modifier des droits
d'accès, obtenir un nom... Ca peut me sembler légitime.


D'accord, mais je ne vois pas en quoi cela doit faire parti de la
classe elle-meme. Rien n'empeche d'utiliser des fonctions avec un
namespace commun et des overload qui ont le merite d'etre ouvert pour
de futurs ajouts de fonctionnalite.


Rien ne l'empêche si ce n'est une duplication ce code pour chaque
overload. Les templates peuvent soulager cette partie là mais je ne
vois pas l'avantage d'avoir des objets découplés si ils partagent une
même interface.


Mais l'interface est alors fermee donc non extensible sans retoucher a
toutes les classes qui en derivent. Je prefere dedoubler qque fonctions
et ne pas etre bloque. Je suis peut-etre influence par mon domaine qui
demande enormement de flexibilite dans le code.

Ca permet aussi d'avoir un système simple de composition pour les
autres types de fichiers (device, pipe, liens symboliques). Avec un
directory comme tu le décrit, il faudrais ajouter un vector pour
chaque type de fichier géré.


Non, parce que la on parle effectivement de decliner des variantes
d'etats, donc le polymorphisme est l'outils adequat: device, pipe et
liens deriveront de File tandis que les repertoires montes deriveront de
Directory.



Si j'ai bien compris le sujet ne concerne (ici) que la distinction entre
les Directory et les Files au niveau de la composition (pas le design
général) car tu veux pouvoir accèder simplement aux fonctionnalités d'un
directory ou d'un fichier (sans tester isDirectory() ou un Visitor
Pattern à 2 entrées Directory/File).

La force du C++, c'est la multiplicite des paradigmes alors je me
mefie des apparences qui veulent toujours tout mettre dans une
hierarchie OO. Je prefere une interface non-OO pour sa flexibilite et
son extensibilite (et aussi le fait qu'aucun argument n'est
prioritaire) et des structures sous-jacentes OO pour le polymorphisme
et l'encapsulation.


Tu veux dire qu'une interface 00 n'est pas flexible ou extensible ?


Oui, enfin pas dans un langage a typage statique ou la notion
d'interface joue un role essentiel. C'est ce que l'on appel une
architecture fermee. Les namespaces en revanche sont ouvert.

Je ne comprends pas. Je trouve la composition très puissante surtout
quand elle est utilisée avec un système de prototypage qui permet à
l'utilisateur de définir des objets composés gérés comme des objets
simples.


La composition n'est pas l'heritage. La composition est effectivement un
concept ouvert extrement flexible. Mais il est bride par les interfaces
qui elle, sont fermees. A moins d'avoir la delegation generique comme
dans COS ;-)


ok. Je vois ce que tu veux dire.


Au final, l'utilisateur d'un File et d'un Directory devra utiliser
des algorithmes differents pour les parcourir, l'un '1D' (un
iterateur) et l'autre '2D' (deux iterateurs). Alors plutot que de
mettre dans la boucle interieur un test du style if (f.isDirectory())
je prefere avoir deux iterateurs.


Une hiérarchie comme cela supporte typiquement le Visitor pattern car
elle n'a pas tendance à bouger


Meme Common Lisp pensait (en 1995) avoir pense a tout sur ce point.
Rate, son systeme bien que tres flexible (et donc complique) n'est pas
portable et demande a l'utilisateur des precautions ou d'ecrire sa
propre interface/wrappers. Tout ca pour dire que meme si cela parrait
immuable en apparence, ca ne l'est peut-etre pas. Donc je favorise
toujours un design ouvert a l'ajout d'une couche de pattern.


Si les fichiers spéciaux/étendus héritent de File, tu te retrouve a ton
point de départ. Non ?

alors que qu'il est probable que des applications auront tendance à
être ajoutée régulièrement.

Il y a certes des cas ou on pourrait applatir l'arbre et le voir
comme une liste uniforme d'objets, mais rien n'empeche a Directory de
fournir un tel iterateur - c'est a dire un iterateur qui descendrait
automatiquement dans les repertoires ou passerait aux fichiers
automatiquement une fois que les repertoires seraient tous parcourus.
Note qu'un tel iterateur serait passablement complique puisqu'il doit
avoir une pile en interne.


Je n'aimerais pas ne pas savoir la profondeur de l'itérateur ou savoir
comment il gère les liens symboliques (risque de boucle) et autres
joyeusetés.


Le mieux est de partir avec un design et d'ecrire quelques algos pour
voir si effectivement ils sont generalisables sans distinction
File-Directory et sans compliquer inutilement l'ensemble. Ensuite on
choisi l'un ou l'autre des deux design.


Je suis d'accord qu'on ne discute pas de règle absolue et qu'en fonction
des besoins et des cas d'utilisation un design ou l'autre pourra être
choisi.

En particulier si il y a des liens symboliques. Tu ne sais pas à priori
si il pointe sur un fichier ou un répertoire. Avoir une fonction
générique qui permette de gèrer cela de façon élégante ce sera pas triviale.
A moins de distinguer de façon pénible les liens symboliques vers les
fichier et les liens symboliques vers les répertoires.

Michael





Avatar
Laurent Deniau
Michael DOUBEZ wrote:
Michael DOUBEZ wrote:
Loïc Joly wrote:
Pourquoi compliquer les choses? Un type File d'un cote et un type
Directory qui contient un vector de Directory et un vector de
File. Directory fourni deux iterateurs, l'un sur les directories
et l'autre sur les files. L'interface en sera plus simple comme
ceci il me semble.

Je ne vois pas pourquoi ici on devrait faire une hierarchie ou
melanger les deux types.


Parce qu'il peut y avoir des opération que l'on souhaite faire à
tous les éléments, comme par exemple effacer, modifier des droits
d'accès, obtenir un nom... Ca peut me sembler légitime.


D'accord, mais je ne vois pas en quoi cela doit faire parti de la
classe elle-meme. Rien n'empeche d'utiliser des fonctions avec un
namespace commun et des overload qui ont le merite d'etre ouvert
pour de futurs ajouts de fonctionnalite.


Rien ne l'empêche si ce n'est une duplication ce code pour chaque
overload. Les templates peuvent soulager cette partie là mais je ne
vois pas l'avantage d'avoir des objets découplés si ils partagent une
même interface.


Mais l'interface est alors fermee donc non extensible sans retoucher a
toutes les classes qui en derivent. Je prefere dedoubler qque
fonctions et ne pas etre bloque. Je suis peut-etre influence par mon
domaine qui demande enormement de flexibilite dans le code.

Ca permet aussi d'avoir un système simple de composition pour les
autres types de fichiers (device, pipe, liens symboliques). Avec un
directory comme tu le décrit, il faudrais ajouter un vector pour
chaque type de fichier géré.


Non, parce que la on parle effectivement de decliner des variantes
d'etats, donc le polymorphisme est l'outils adequat: device, pipe et
liens deriveront de File tandis que les repertoires montes deriveront
de Directory.



Si j'ai bien compris le sujet ne concerne (ici) que la distinction entre
les Directory et les Files au niveau de la composition (pas le design
général) car tu veux pouvoir accèder simplement aux fonctionnalités d'un
directory ou d'un fichier (sans tester isDirectory() ou un Visitor
Pattern à 2 entrées Directory/File).

La force du C++, c'est la multiplicite des paradigmes alors je me
mefie des apparences qui veulent toujours tout mettre dans une
hierarchie OO. Je prefere une interface non-OO pour sa flexibilite
et son extensibilite (et aussi le fait qu'aucun argument n'est
prioritaire) et des structures sous-jacentes OO pour le
polymorphisme et l'encapsulation.


Tu veux dire qu'une interface 00 n'est pas flexible ou extensible ?


Oui, enfin pas dans un langage a typage statique ou la notion
d'interface joue un role essentiel. C'est ce que l'on appel une
architecture fermee. Les namespaces en revanche sont ouvert.

Je ne comprends pas. Je trouve la composition très puissante surtout
quand elle est utilisée avec un système de prototypage qui permet à
l'utilisateur de définir des objets composés gérés comme des objets
simples.


La composition n'est pas l'heritage. La composition est effectivement
un concept ouvert extrement flexible. Mais il est bride par les
interfaces qui elle, sont fermees. A moins d'avoir la delegation
generique comme dans COS ;-)


ok. Je vois ce que tu veux dire.


Au final, l'utilisateur d'un File et d'un Directory devra utiliser
des algorithmes differents pour les parcourir, l'un '1D' (un
iterateur) et l'autre '2D' (deux iterateurs). Alors plutot que de
mettre dans la boucle interieur un test du style if
(f.isDirectory()) je prefere avoir deux iterateurs.


Une hiérarchie comme cela supporte typiquement le Visitor pattern car
elle n'a pas tendance à bouger


Meme Common Lisp pensait (en 1995) avoir pense a tout sur ce point.
Rate, son systeme bien que tres flexible (et donc complique) n'est pas
portable et demande a l'utilisateur des precautions ou d'ecrire sa
propre interface/wrappers. Tout ca pour dire que meme si cela parrait
immuable en apparence, ca ne l'est peut-etre pas. Donc je favorise
toujours un design ouvert a l'ajout d'une couche de pattern.


Si les fichiers spéciaux/étendus héritent de File, tu te retrouve a ton
point de départ. Non ?


Pourquoi? Si l'etat evolu mais l'interface est similaire, alors je
derive et j'override. Si l'etat est similaire (ou inexistant) et
l'interface evolue alors j'overload et je namespace. Si j'ai les deux
qui evoluent, je prends l'un ou l'autre suivant lequel domine les
changements et je template pour accomoder l'autre. La regle est assez
simple non? (Bon, les templates c'est l'artillierie lourde plutot
reservee pour d'autres trucs plus sofistiques).

Les fichiers speciaux sont dans le premiers cas. La dualite
Directory/File est dans le deuxieme cas.

alors que qu'il est probable que des applications auront tendance à
être ajoutée régulièrement.

Il y a certes des cas ou on pourrait applatir l'arbre et le voir
comme une liste uniforme d'objets, mais rien n'empeche a Directory
de fournir un tel iterateur - c'est a dire un iterateur qui
descendrait automatiquement dans les repertoires ou passerait aux
fichiers automatiquement une fois que les repertoires seraient tous
parcourus. Note qu'un tel iterateur serait passablement complique
puisqu'il doit avoir une pile en interne.


Je n'aimerais pas ne pas savoir la profondeur de l'itérateur ou
savoir comment il gère les liens symboliques (risque de boucle) et
autres joyeusetés.


Le mieux est de partir avec un design et d'ecrire quelques algos pour
voir si effectivement ils sont generalisables sans distinction
File-Directory et sans compliquer inutilement l'ensemble. Ensuite on
choisi l'un ou l'autre des deux design.


Je suis d'accord qu'on ne discute pas de règle absolue et qu'en fonction
des besoins et des cas d'utilisation un design ou l'autre pourra être
choisi.


Excatement. Cela vaut mieux que de perdre un max de temps sur un design
obsolete au premier changement des specs.

En particulier si il y a des liens symboliques. Tu ne sais pas à priori
si il pointe sur un fichier ou un répertoire. Avoir une fonction
générique qui permette de gèrer cela de façon élégante ce sera pas
triviale.


Pour ce point il est possible qu'il faille un nouveau type SymLink et un
peu d'heritage multiple SymLink+File et SymLink+Directory sans danger
ici puisque File et Directory sont deux concepts ortogonaux (pas de
risque d'heritage en diamant un jour). Mais avant de partir la dedans je
regarderais si une utilisation astucieuse des iterateurs (ou un nouvel
iterateur) ne permettrait pas d'obtenir l'abstraction cherchee. A ce
titre, je considere souvent les iterateurs comme des delegues,
eventuellement sur un seul objet.

A moins de distinguer de façon pénible les liens symboliques vers les
fichier et les liens symboliques vers les répertoires.


Ca devra etre le cas a un niveau ou a un autre tout comme la distinction
File/Directory. Ce sera l'usage et la possible generalisation des algos
qui nous dira si on peut unifier et a quel niveau (la sa sent plutot le
template).

a+, ld.






Avatar
Sylvain
Laurent Deniau wrote on 08/03/2007 14:28:

Pour ce point il est possible qu'il faille un nouveau type SymLink et un
peu d'heritage multiple SymLink+File et SymLink+Directory sans danger
ici puisque File et Directory sont deux concepts ortogonaux (pas de
risque d'heritage en diamant un jour).


est-ce certain ? si un éventuel accès aux données du fichier existe (une
notion de "documemt" débordant du simple élément nommée, daté, ...) un
comportement type directory d'énumération de childs peut apparaitre
(pour lister les noeuds d'un fichier XML, les élements d'un fichier
taggé ...).

Sylvain.

Avatar
Laurent Deniau
Sylvain wrote:
Laurent Deniau wrote on 08/03/2007 14:28:

Pour ce point il est possible qu'il faille un nouveau type SymLink et
un peu d'heritage multiple SymLink+File et SymLink+Directory sans
danger ici puisque File et Directory sont deux concepts ortogonaux
(pas de risque d'heritage en diamant un jour).


est-ce certain ? si un éventuel accès aux données du fichier existe (une
notion de "documemt" débordant du simple élément nommée, daté, ...) un
comportement type directory d'énumération de childs peut apparaitre
(pour lister les noeuds d'un fichier XML, les élements d'un fichier
taggé ...).


Je ne crois pas que l'heritage soit la solution et que la composition
correspond mieux a ce type de probleme (flexibilite). Avant de
construire des graphes d'heritage a tout va, je commencerais par voir si
c'est necessaire.

a+, ld.


1 2