cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008
-
13 mai 2006 à 02:46
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008
-
21 mai 2006 à 15:56
Bonjour,
voilà plusieurs mois que j'ai appris la programmation avec C# et je dois dire que je n'ai toujours pas les reflexes pour "programmer objet". Quand je crée un programme, je n'arrive pas à m'imaginer quelles seront les classes d'objets dont j'aurais besoin. J'ai beaucoup plus de facilité à résonner avec des procédures. Voici par exemple un petit programme que j'ai fait. Il compare des fichiers dans 2 dossiers et affiche les fichiers qui existent dans le dossier 1 mais pas dans le 2, les fichiers qui existent dans le 2 mais pas dans le 1, les fichiers qui existent dans les 2 mais dont les contenus sont différents, les fichiers identiques. J'aurais aimé savoir si une approche "objet" était possible pour traiter ce problème ? Voici de mon côté comment j'ai procédé :
namespace Compare
{
public partial class Form1 : Form
{
public ArrayList PasDans1 = new ArrayList();
public ArrayList PasDans2 = new ArrayList();
public ArrayList Differents = new ArrayList();
public ArrayList Identiques = new ArrayList();
foreach (FileInfo MyFileInfo in MyFileInfoList1)
{
if (Contains(MyFileInfoList2, MyFileInfo))
{
if (Read(textBox1.Text + "\" + MyFileInfo.Name) != Read(textBox2.Text + "\" + MyFileInfo.Name))
Differents.Add(MyFileInfo.Name);
else
Identiques.Add(MyFileInfo.Name);
}
else
{
PasDans2.Add(MyFileInfo.Name);
}
}
foreach (FileInfo MyFileInfo in MyFileInfoList2)
{
if (!Contains(MyFileInfoList1, MyFileInfo))
PasDans1.Add(MyFileInfo.Name);
}
string[] notin1 = new string[PasDans1.Count];
PasDans1.CopyTo(notin1);
string[] notin2 = new string[PasDans2.Count];
PasDans2.CopyTo(notin2);
string[] diff = new string[Differents.Count];
Differents.CopyTo(diff);
string[] id = new string[Identiques.Count];
Identiques.CopyTo(id);
textBox3.Text = "Fichiers non présents dans le dossier 1 :\r\n" +
System.String.Join("\r\n", notin1) + "\r\n\r\n" +
"Fichiers non présents dans le dossier 2 :\r\n" +
System.String.Join("\r\n", notin2) + "\r\n\r\n" +
"Fichiers différents :\r\n" +
System.String.Join("\r\n", diff) + "\r\n\r\n" +
"Fichiers Identiques :\r\n" +
System.String.Join("\r\n", id);
end: ;
}
private bool Contains(FileInfo[] List, FileInfo Elmt)
{
foreach (FileInfo MyFileInfo in List)
{
if (MyFileInfo.Name == Elmt.Name)
{
return true;
}
}
return false;
}
private string Read(string FileToRead)
{
FileStream OrigFile = new FileStream(FileToRead, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(OrigFile, System.Text.Encoding.Default);
string s = sr.ReadToEnd();
sr.Close();
OrigFile.Close();
return (s);
}
}
}
J'aurais aimé savoir ce que vous pensez de la façon de programmer et comment vous auriez traités ce problème. Quels classes, méthodes, propriétés,... auriez vous utilisés ?
TheSaib
Messages postés2367Date d'inscriptionmardi 17 avril 2001StatutMembreDernière intervention26 décembre 200723 17 mai 2006 à 11:06
Pas de variables publiques => variable privé + accesseur
public ArrayList PasDans1 = new ArrayList();
public ArrayList PasDans2 = new ArrayList();
public ArrayList Differents = new ArrayList();
public ArrayList Identiques = new ArrayList();
-------------------------------------
Pas de textBox3.Text = "";
mais du string.Empty si besoin.
-------------------------------------
Pas de try catch général, il faut catcher une exception spécifique.
Ex : catch (DirectoryNotFoundException dnfe)
try { Folder2 = new DirectoryInfo(textBox2.Text); }
catch
-------------------------------------
if (!Contains(MyFileInfoList1, MyFileInfo))
PasDans1.Add(MyFileInfo.Name);
Utilises une hastable pour ce genre de stockage.
-------------------------------------
goto end;
Forbidden words !!!!
Utilise un "Return" ou mieux throw une exception personnalisée.
-------------------------------------
button1_Click
nomme correctement tes variables pour qu'elles soient humainement compréhensible.
-------------------------------------
textBox3.Text = "Fichiers non présents dans le dossier 1 :\r\n" +
System.String.Join("\r\n", notin1) + "\r\n\r\n" +
"Fichiers non présents dans le dossier 2 :\r\n" +
System.String.Join("\r\n", notin2) + "\r\n\r\n" +
"Fichiers différents :\r\n" +
System.String.Join("\r\n", diff) + "\r\n\r\n" +
"Fichiers Identiques :\r\n" +
System.String.Join("\r\n", id);
Burk :
Utilise un System.Text.StringBuilder et les fonction Append / AppendFormat
Essaie de ne pas mettre de chaîne en dur, passe par des constantes ou des ressources si tu veux localiser.
Pas de \r\n mais Environment.NewLine.
---------------------------------------
string[] Catégories = {"Fichiers non présents dans le dossier 1 :",
"Fichiers non présents dans le dossier 2 :",
"Fichiers différents mais portant le même nom :",
"Fichiers identiques :"};
textBox3.Text = System.String.Join(Environment.NewLine + Environment.NewLine,Catégories);
}
private string Read(string FileToRead)
{
FileStream OrigFile = new FileStream(FileToRead, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(OrigFile, System.Text.Encoding.Default);
string s = sr.ReadToEnd();
sr.Close();
OrigFile.Close();
return (s);
}
}
}
Plusieurs questions concernant tes remarques :
j'ai essayé de catcher une exeption spécifique mais je n'ai pas trouvé celle qui convenait. catcher avec DirectoryNotFoundException ne marche pas, quand je débug le programme il me dit que le path n'est pas valide. Comment trouver le nom de l'exeption ?
pourquoi vaut-il mieux mettre string.empty que "" et Environment.NewLine que "\r\n" ?
je n'ai pas trop compris l'utilité d'utiliser un streambuilder (du moins dans mon nouveau code).
sinon peut-on dire que ce programme est correctement programmé objet ?
J'ai cependant encore du mal à voir ce qui différencie sur le fond la programmation objet de la programmation procédurale...
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 19 mai 2006 à 08:21
Salut,
En ce qui concerne l'exception, il s'agit sûrement d'une ArgumentException (si le path à des charactères invalides)
Sinon, il parle d'un StringBuilder et pas d'un StreamBuilder (qui je crois n'existe pas).
Un StringBuilder à le gros avantage d'être beaucoup plus rapide et de pouvoir directement formatter les données.
//propriétés
public Hashtable DicoFiles{
get { return _DicoFiles; }
set { _DicoFiles=value; }
}
public string path1{
get { return _path1; }
set { _path1=value; }
}
public string path2{
get { return _path2; }
set { _path2=value; }
}
public string PasDans1{
get { return _Catégories[0]; }
}
public string PasDans2{
get { return _Catégories[1]; }
}
public string Différents{
get { return _Catégories[2]; }
}
public string Identiques{
get { return _Catégories[3]; }
}
private string Read(string FileToRead)
{
FileStream OrigFile = new FileStream(FileToRead, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(OrigFile, System.Text.Encoding.Default);
string s = sr.ReadToEnd();
sr.Close();
OrigFile.Close();
return (s);
}
}
}
et le code du programme :
namespace Compare
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void radioButton1_Click(object sender, EventArgs e)
{
Comparaison ObjComparaison = new Comparaison(textBox1.Text, textBox2.Text);
textBox3.Text = ObjComparaison.PasDans1;
}
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 19 mai 2006 à 20:37
Salut,
Voilà quelques idées :
1) Spécifié l'accessiblité de la class : public (par exemple).
2) Initialisé les variables avant leur utilisation.
3) Oublier l'accentuation pour nommer les variables !!!!!!
4) Autre remarque : en .NET, la convention veut que les variables commence par une miniscule (donc plutôt "Pascal notation" que "Camel notation"), pas d'accentuation, en toute lettre juste pour les constantes, etc.
Pour vraiment comprendre ce que c'est qu'une classe, une interface, une classe abstraite, etc, il faut pas mal de pratique, surtout quand on vient d'un monde comme le C où toutes ces notions n'existent pas...
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008 19 mai 2006 à 21:05
Ok merci pour ces précisions. J'éspère que comme tu le dis la pratique me fera mieux comprendre quand il faut utiliser des classes et comment les construire. Sans vouloir insister, j'aurais juste encore une petite question : Y avait-il un avantage à utiliser une classe comparaison ici ou mon programme était plus propre sans cette classe ?
cs_Bidou
Messages postés5487Date d'inscriptiondimanche 4 août 2002StatutMembreDernière intervention20 juin 201361 19 mai 2006 à 21:47
Oui, il faut une Class, c'est évident ! (tu ne peux pas laisser des milliers de lignes code dans une Form : une Form devrait plutôt appeler la fonctionnalité que tu implémentes ailleurs).
Quand à dire si elle est bien construite... je te cacherai pas que je n'aurais pas fait comme ça!
Je ne peux pas t'expliquer en détail pourquoi, y'a certain truc qui vienne avec le feeling et l'expérience mais encore quelques conseils :
Le constructeur, dans la plupart des cas, ne fait rien si ce n'est initialiser des variables, appeler un constructeur du parent, ou des trucs basique comme ça. La raison à ceci est simple : quand tu vas construire ton object, tu vas passer dans le constructeur, puis tu vas appeler certaine méthode de ton object, mais généralement tu vas utiliser seulement une part de la fonctionnalité qu'il t'offre. Alors, à quoi ça sert de faire des milliers de calculs et je ne sais pas tout quoi, si c'est pour juste appeler une méthode ?
Une idée pour pouvoir poser l'architecture d'une class, c'est de se dire : "Comment je voudrais l'utiliser?", puis ensuite, créer la class en fonction de ceci (cette méthode à ses désavantage aussi). Petite exemple pour illustrer la méthode. Dans ton cas, ce qui serait bien c'est de faire (ceci est exemple) :
Donc ensuite tu constuis ta class en fonction de ceci (c'est un exemple extrement simple et peut-êtrs pas très réaliste, parce qu'il faut encore implémenté des autres fonctions).
Le meilleur conseil : pratiquer, pratiquer et pratiquer. Codes-sources te sera de grande aide pour poser des questions, et trouver des codes qui te permettront d'apprendre plus
cs_mathmax
Messages postés403Date d'inscriptionvendredi 28 octobre 2005StatutMembreDernière intervention31 août 2008 21 mai 2006 à 15:56
merci encore pour ces conseils Bidou. En fait j'avais fabriqué le dictionnaire Hashtable dans le constructeur parce que sinon j'aurais dû le reconstruire dans chaque propriété (pasdans1, pasdans2, différents, identiques). Ce qui fait que quand j'aurais construit un objet, à chaque fois que j'aurais utilisé une nouvelle propriété, un nouveau dictionnaire aurait été construit. J'ai donc préférer construire ce dictionnaire une bonne fois pour toute dès la construction de l'objet. J'en ai donc fais une propriété, que j'initialise avec le constructeur. Mais peut-être y avait-il une autre méthode ?