begin process at 2008 08 22 04:24:15
1 229 775 membres
46 nouveaux aujourd'hui
14 267 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : Programmation objets intuitif ? [ Archives / Au secours ] (mathmax)

Programmation objets intuitif ? le 13/05/2006 02:46:06

mathmax
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();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            textBox3.Text = "";
            DirectoryInfo Folder1, Folder2;
            try { Folder1 = new DirectoryInfo(textBox1.Text); }
            catch
            {
                MessageBox.Show("Chemin 1 incorrect !", "ATTENTION !", MessageBoxButtons.OK);
                goto end;
            }
            try { Folder2 = new DirectoryInfo(textBox2.Text); }
            catch
            {
                MessageBox.Show("Chemin 2 incorrect !", "ATTENTION !", MessageBoxButtons.OK);
                goto end;
            }
            FileInfo[] MyFileInfoList1 = Folder1.GetFiles();
            FileInfo[] MyFileInfoList2 = Folder2.GetFiles();

            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 ?

merci d'avance pour vos conseils.

Mathmax


Re : Programmation objets intuitif ? le 17/05/2006 11:06:35

TheSaib
(Admin CS)
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.
---------------------------------------


...
::|The S@ib|:: MVP C#.NET

Re : Programmation objets intuitif ? le 19/05/2006 03:52:19

mathmax
Merci beaucoup pour tes conseils TheSaib. J'ai revu le code de mon programme. Celà donne :

namespace Compare
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void BtnStart_Click(object sender, EventArgs e)
        {
            textBox3.Text = string.Empty;
            DirectoryInfo Folder1, Folder2;
            int numero = 1;
            try
            {
                Folder1 = new DirectoryInfo(textBox1.Text);
                numero++;
                Folder2 = new DirectoryInfo(textBox2.Text);
            }
            catch
            {
                MessageBox.Show("Chemin " + numero + " incorrect !", "ATTENTION !", MessageBoxButtons.OK);
                return;
            }
            FileInfo[] MyFileInfoList1 = Folder1.GetFiles();
            FileInfo[] MyFileInfoList2 = Folder2.GetFiles();

            Hashtable DicoFiles = new Hashtable();

            foreach (FileInfo MyFileInfo in MyFileInfoList1)
                DicoFiles.Add(MyFileInfo.Name, 1);

            foreach (FileInfo MyFileInfo in MyFileInfoList2)
            {
                if (DicoFiles.ContainsKey(MyFileInfo.Name))
                    if (Read(textBox1.Text + "\\" + MyFileInfo.Name) == Read(textBox2.Text + "\\" + MyFileInfo.Name))
                        DicoFiles[MyFileInfo.Name] = 3;
                    else
                        DicoFiles[MyFileInfo.Name] = 2;
                else
                    DicoFiles.Add(MyFileInfo.Name, 0);
            }
           
            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 :"};

            IEnumerator clés = DicoFiles.Keys.GetEnumerator();

            while(clés.MoveNext())
                Catégories[(int)DicoFiles[clés.Current]] += Environment.NewLine + clés.Current;

            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...

Mathmax


Re : Programmation objets intuitif ? le 19/05/2006 08:21:09

Bidou
(Admin CS)
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.



VC# forever

Re : Programmation objets intuitif ? le 19/05/2006 17:16:10

mathmax
J'ai refais le programme en utilisant cette fois ci une classe. Crois-tu que c'était justifié ? Si oui, est elle bien conçue ?

Voici le code de la classe :

namespace Compare
{
    class Comparaison
    {
        //attributs
        private string _path1, _path2;
        private Hashtable _DicoFiles;
        private string[] _Catégories = new string[4];

        //constructeur
        public Comparaison(string P1, string P2)
        {
            DirectoryInfo Folder1, Folder2;
            int numero = 1;
            try
            {
                Folder1 = new DirectoryInfo(P1);
                numero++;
                Folder2 = new DirectoryInfo(P2);
            }
            catch
            {
                MessageBox.Show("Chemin " + numero + " incorrect !", "ATTENTION !", MessageBoxButtons.OK);
                return;
            }

            FileInfo[] MyFileInfoList1 = Folder1.GetFiles();
            FileInfo[] MyFileInfoList2 = Folder2.GetFiles();

            Hashtable DICOFILES = new Hashtable();
            foreach (FileInfo MyFileInfo in MyFileInfoList1)
                DICOFILES.Add(MyFileInfo.Name, 1);

            foreach (FileInfo MyFileInfo in MyFileInfoList2)
            {
                if (DICOFILES.ContainsKey(MyFileInfo.Name))
                    if (Read(P1 + "\\" + MyFileInfo.Name) == Read(P2 + "\\" + MyFileInfo.Name))
                        DICOFILES[MyFileInfo.Name] = 3;
                    else
                        DICOFILES[MyFileInfo.Name] = 2;
                else
                    DICOFILES.Add(MyFileInfo.Name, 0);
            }

            IEnumerator clés = DICOFILES.Keys.GetEnumerator();

            while (clés.MoveNext())
                this._Catégories[(int)DICOFILES[clés.Current]] += clés.Current + Environment.NewLine;

            this._DicoFiles = DICOFILES;
            this._path1 = P1;
            this._path2 = P2;
        }

        //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;
        }

        private void radioButton2_Click(object sender, EventArgs e)
        {
            Comparaison ObjComparaison = new Comparaison(textBox1.Text, textBox2.Text);
            textBox3.Text = ObjComparaison.PasDans2;
        }

        private void radioButton3_Click(object sender, EventArgs e)
        {
            Comparaison ObjComparaison = new Comparaison(textBox1.Text, textBox2.Text);
            textBox3.Text = ObjComparaison.Différents;
        }

        private void radioButton4_Click(object sender, EventArgs e)
        {
            Comparaison ObjComparaison = new Comparaison(textBox1.Text, textBox2.Text);
            textBox3.Text = ObjComparaison.Identiques;
        }
    }
}

Ce que je n'arrive pas encore trop à cerner c'est l'utilité d'utiliser une classe.

Peut être préfères tu avoir le projet entier sous les yeux ? Tu peux le télécharger ici : [ Lien ]

En éspèrant ne pas être trop dérangeant,

Mathmax


Re : Programmation objets intuitif ? le 19/05/2006 20:37:32

Bidou
(Admin CS)
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...



VC# forever

Re : Programmation objets intuitif ? le 19/05/2006 21:05:32

mathmax
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 ?

Mathmax


Re : Programmation objets intuitif ? le 19/05/2006 21:47:47

Bidou
(Admin CS)
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) :

FileComparer fComparer = new FileComparer(string path1, string path2);
bool isSame = fComparer.Comparer(bool caseSensitiv);

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



VC# forever

Re : Programmation objets intuitif ? le 21/05/2006 15:56:28

mathmax
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 ?


Mathmax



Classé sous : string, fichiers, arraylist, name, myfileinfo

Participer à cet échange

Pub



Appels d'offres

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

Téléchargements

Logiciels à télécharger sur le même thème :

Boutique

Boutique de goodies CodeS-SourceS