Le problème des boîtes imbriquées (v. 0)

Quelques raccourcis :

Ce petit travail pratique a été pensé pour vous faire réfléchir, et pour vous divertir. De par sa structure, il fait en sorte qu'on puisse "tricher" en résolvant les versions les plus simples du problème, mais qu'il faille faire un effort de conception pour résoudre le problème dans son acception générale – surtout si vous souhaitez le petit bonus.

Si vous avez un design propre et élégant, vous aurez du plaisir. Si vous trichez, ce sera... une expérience de vie. 🙂

Vous devez développer un ensemble de classes permettant de construire des boîtes et de les imbriquer. Nous avons abordé en classe une solution à ce problème, développée de manière incrémentale de manière à aborder le problème de la refactorisation du code, mais cette fois, c'est à un problème de design que vous êtes conviés.

C'est un problème a priori facile à résoudre. Dans une acception C#, l'idée est que si le programme suivant :

using System;

Console.WriteLine("J'aime mon prof");

... devrait afficher cela :

J'aime mon prof

... alors le programme suivant :

using System;

Console.WriteLine(new Boite("J'aime mon prof"));

... devrait afficher cela :

+---------------+
|J'aime mon prof|
+---------------+

...et que si le programme suivant :

using System;

Console.WriteLine("J'aime\nmon \"prof\"");
Console.WriteLine(@"Moi
""aussi""");

... devrait afficher cela :

J'aime
mon "prof"
Moi
"aussi"

... alors le programme suivant :

using System;

Console.WriteLine(new Boite("J'aime\nmon \"prof\""));
Console.WriteLine(new Boite(@"Moi
""aussi"""));

... devrait afficher cela :

+----------+
|J'aime    |
|mon "prof"|
+----------+
+-------+
|Moi    |
|"aussi"|
+-------+

Facile non?

Le plaisir commence...

Évidemment, ça devient plus intéressant si on inclut les combos verticaux et horizontaux. Par exemple, ceci :

using System;

Console.WriteLine(
   new Boite(new ComboVertical(new Boite("J'aime"), new Boite("mon \"prof\"")))
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite ("Moi"), new Boite("\"aussi\"")))
);

... doit afficher cela :

+----------+
|J'aime    |
|----------|
|mon "prof"|
+----------+
+-----------+
|Moi|"aussi"|
+-----------+

Plus en détail :

Il s'agit d'un problème un peu plus costaud qu'il n'y paraît, ce qui explique que je vous laisse du temps pour le faire. Profitez de ce temps, et cherchez à obtenir un design qui vous semble de qualité : concis, modifiable, esthétique, clair. Si votre design est complexe, ou si vous codez sans réfléchir, ceci peut être casse-gueule. Si vous y allez avec délicatesse, votre solution pourrait être fort élégante.

Notez que nous avons vu plusieurs techniques au cours de votre formation qui sont susceptibles de vous être utiles pour résoudre ce problème. Profitez-en pour expérimenter!

Exemples de programmes clients

Vous pouvez écrire ce programme en C# ou en Java, à votre convenance. Deux exemples de code client suivent, un par langage, puis l'affichage attendu sera présenté.

Code client en C#

Pour C#, le code client serait :

using System;
using Boites; // pas obligé; dans mon cas, c'était utile

Boite b = new ();
Console.WriteLine(b);
Console.WriteLine(new Boite("yo"));
string texte = @"Man! Hey!!!
ceci est un test
multiligne";
string autTexte = "Ceci\nitou, genre";
Boite b0 = new (texte);
Boite b1 = new (autTexte);
Console.WriteLine(b0);
Console.WriteLine(b1);
ComboVertical cv = new (b0, b1);
Console.WriteLine(new Boite(cv));
ComboHorizontal ch = new (b0, b1);
Console.WriteLine(new Boite(ch));
ComboVertical cvplus = new (new Boite(cv), new Boite(ch));
Console.WriteLine(new Boite(cvplus));
ComboHorizontal chplus = new (new Boite(cv), new Boite(ch));
Console.WriteLine(new Boite(chplus));
ComboVertical cvv = new (new Boite(chplus), new Boite("coucou"));
Console.WriteLine(new Boite(cvv));
Console.WriteLine(new Boite(
   new ComboHorizontal(
      new Boite("a\nb\nc\nd\ne"),
         new Boite(
            new ComboVertical(
               new Boite("allo"), new Boite("yo")
            )
         )
      )
   )
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite("Yo"), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite(), new Boite("Ya")))
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite(), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite(), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite("Yip"), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite(), new Boite("Yap")))
);

Code client en Java

Pour Java, le code client serait :

public class Program {
   public static void main(String[] args) {
      Boite b = new Boite();
      System.out.println(b);
      System.out.println(new Boite("yo"));
      String texte = "Man! Hey!!!\nceci est un test\nmultiligne";
      String autTexte = "Ceci\nitou, genre";
      Boite b0 = new Boite(texte);
      Boite b1 = new Boite(autTexte);
      System.out.println(b0);
      System.out.println(b1);
      ComboVertical cv = new ComboVertical(b0, b1);
      System.out.println(new Boite(cv));
      ComboHorizontal ch = new ComboHorizontal(b0, b1);
      System.out.println(new Boite(ch));
      ComboVertical cvplus = new ComboVertical( new Boite(cv), new Boite(ch));
      System.out.println(new Boite(cvplus));
      ComboHorizontal chplus = new ComboHorizontal(new Boite(cv), new Boite(ch));
      System.out.println(new Boite(chplus));
      ComboVertical cvv = new ComboVertical(new Boite(chplus), new Boite("coucou"));
      System.out.println(new Boite(cvv));
      System.out.println(new Boite(
         new ComboHorizontal(
            new Boite("a\nb\nc\nd\ne"),
               new Boite(
                  new ComboVertical(
                     new Boite("allo"), new Boite("yo")
                  )
               )
            )
         )
      );
      System.out.println(
         new Boite(new ComboHorizontal(new Boite("Yo"), new Boite()))
      );
      System.out.println(
         new Boite(new ComboHorizontal(new Boite(), new Boite("Ya")))
      );
      System.out.println(
         new Boite(new ComboHorizontal(new Boite(), new Boite()))
      );
      System.out.println(
         new Boite(new ComboVertical(new Boite(), new Boite()))
      );
      System.out.println(
         new Boite(new ComboVertical(new Boite("Yip"), new Boite()))
      );
      System.out.println(
         new Boite(new ComboVertical(new Boite(), new Boite("Yap")))
      );
   }
}

Affichage attendu

Que vous ayez choisi l'un ou l'autre de ces langages, l'affichage attendu pour le code de test proposé va comme suit :

++
++
+--+
|yo|
+--+
+----------------+
|Man! Hey!!!     |
|ceci est un test|
|multiligne      |
+----------------+
+-----------+
|Ceci       |
|itou, genre|
+-----------+
+----------------+
|Man! Hey!!!     |
|ceci est un test|
|multiligne      |
|----------------|
|Ceci            |
|itou, genre     |
+----------------+
+----------------------------+
|Man! Hey!!!     |Ceci       |
|ceci est un test|itou, genre|
|multiligne      |           |
+----------------------------+
+----------------------------+
|Man! Hey!!!                 |
|ceci est un test            |
|multiligne                  |
|----------------------------|
|Ceci                        |
|itou, genre                 |
|----------------------------|
|Man! Hey!!!     |Ceci       |
|ceci est un test|itou, genre|
|multiligne      |           |
+----------------------------+
+---------------------------------------------+
|Man! Hey!!!     |Man! Hey!!!     |Ceci       |
|ceci est un test|ceci est un test|itou, genre|
|multiligne      |multiligne      |           |
|----------------|                |           |
|Ceci            |                |           |
|itou, genre     |                |           |
+---------------------------------------------+
+---------------------------------------------+
|Man! Hey!!!     |Man! Hey!!!     |Ceci       |
|ceci est un test|ceci est un test|itou, genre|
|multiligne      |multiligne      |           |
|----------------|                |           |
|Ceci            |                |           |
|itou, genre     |                |           |
|---------------------------------------------|
|coucou                                       |
+---------------------------------------------+
+------+
|a|allo|
|b|----|
|c|yo  |
|d|    |
|e|    |
+------+
+---+
|Yo||
+---+
+---+
||Ya|
+---+
+-+
+-+
++
||
++
+---+
|Yip|
|---|
+---+
+---+
|---|
|Yap|
+---+

Que vous abordiez ce problème en Java ou en C#, faites attention au partage des ressources. Je vous invite à prendre soin de dupliquer les objets que vous manipulez pour éviter qu'une redimension fortuite n'endommage un objet manipulé indirectement.

Exemple de design possible

Votre chic prof, quand il a résolu le problème, en est arrivé au design suivant. Vous n'avez absolument pas à faire comme lui. Pris d'un point de vue aérien, le schéma de sa solution est :

Boites v0

Quelques remarques :

Plus en détail :

À titre d'exemple, pour mes fins, la classe ComboVertical.Énumérateur implémente IÉnumérateur<string> et fait en sorte que j'itère d'abord sur la section du haut, puis (brièvement) sur la « section » du centre, puis sur la section du bas, ce qui cache à la Boite englobante les détails d'implémentation de ce qu'elle « contient ».

Si vous souhaitez un petit bonus

Étant donné que ce travail pratique a été proposé par le passé et a acquis, semble-t-il, une certaine... réputation, j'ai pris sur moi de propose une option vous permettant d'aller chercher un petit bonus si tel est votre souhait.

Ce bonus prend la forme d'un MonoCombo, représentant une boîte encadrée dans une Boite. Évidemment, un MonoCombo peut être placé dans n'importe quelle Boite, et peut contenir n'importe quelle Boite.

Un exemple de programme C# utilisant aussi des MonoCombo suit. Vous pouvez extrapoler à partir del'exemple Java plus haut pour en arriver au même résultat avec ce langage :

using System;
using Boites; // pas obligé; dans mon cas, c'était utile

Boite b = new ();
Console.WriteLine(b);
Console.WriteLine(new Boite("yo"));
string texte = @"Man! Hey!!!
ceci est un test
multiligne";
string autTexte = "Ceci\nitou, genre";
Boite b0 = new (texte);
Boite b1 = new (autTexte);
Console.WriteLine(b0);
Console.WriteLine(b1);
ComboVertical cv = new (b0, b1);
Console.WriteLine(new Boite(cv));
ComboHorizontal ch = new (b0, b1);
Console.WriteLine(new Boite(ch));
ComboVertical cvplus = new (new Boite(cv), new Boite(ch));
Console.WriteLine(new Boite(cvplus));
ComboHorizontal chplus = new (new Boite(cv), new Boite(ch));
Console.WriteLine(new Boite(chplus));
ComboVertical cvv = new (new Boite(chplus), new Boite("coucou"));
Console.WriteLine(new Boite(cvv));
Console.WriteLine(new Boite(
   new ComboHorizontal(
      new Boite("a\nb\nc\nd\ne"),
         new Boite(
            new ComboVertical(
               new Boite("allo"), new Boite("yo")
            )
         )
      )
   )
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite("Yo"), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite(), new Boite("Ya")))
);
Console.WriteLine(
   new Boite(new ComboHorizontal(new Boite(), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite(), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite("Yip"), new Boite()))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite(), new Boite("Yap")))
);
Console.WriteLine(
   new Boite(new ComboVertical(new Boite(), new Boite()))
);
Console.WriteLine(new Boite(new MonoCombo(new Boite("allo"))));
Console.WriteLine(new Boite(new MonoCombo(new Boite(new MonoCombo(new Boite("allo"))))));
Console.WriteLine(new Boite(
   new ComboVertical(
      new Boite (new MonoCombo(new Boite(new MonoCombo(new Boite("allo"))))),
      new Boite("Eh ben")
   )
));
Console.WriteLine(new Boite(
   new ComboHorizontal(new Boite("a\nb\nc\nd"),
                       new Boite(new MonoCombo(new Boite())))
));
Console.WriteLine(new Boite(
   new ComboHorizontal(
      new Boite(new MonoCombo(new Boite(new MonoCombo(new Boite("allo"))))),
      new Boite(new ComboVertical(
         new Boite("Eh ben"),
         new Boite(new MonoCombo(new Boite(
            new ComboHorizontal(new Boite("yo"), new Boite("hey"))
         )))
      ))
   )
));

L'affichage attendu serait alors :

++
++
+----------------+
|Man! Hey!!!     |
|ceci est un test|
|multiligne      |
+----------------+
+-----------+
|Ceci       |
|itou, genre|
+-----------+
+----------------+
|Man! Hey!!!     |
|ceci est un test|
|multiligne      |
|----------------|
|Ceci            |
|itou, genre     |
+----------------+
+----------------------------+
|Man! Hey!!!     |Ceci       |
|ceci est un test|itou, genre|
|multiligne      |           |
+----------------------------+
+----------------------------+
|Man! Hey!!!                 |
|ceci est un test            |
|multiligne                  |
|----------------------------|
|Ceci                        |
|itou, genre                 |
|----------------------------|
|Man! Hey!!!     |Ceci       |
|ceci est un test|itou, genre|
|multiligne      |           |
+----------------------------+
+---------------------------------------------+
|Man! Hey!!!     |Man! Hey!!!     |Ceci       |
|ceci est un test|ceci est un test|itou, genre|
|multiligne      |multiligne      |           |
|----------------|                |           |
|Ceci            |                |           |
|itou, genre     |                |           |
+---------------------------------------------+
+---------------------------------------------+
|Man! Hey!!!     |Man! Hey!!!     |Ceci       |
|ceci est un test|ceci est un test|itou, genre|
|multiligne      |multiligne      |           |
|----------------|                |           |
|Ceci            |                |           |
|itou, genre     |                |           |
|---------------------------------------------|
|coucou                                       |
+---------------------------------------------+
+------+
|a|allo|
|b|----|
|c|yo  |
|d|    |
|e|    |
+------+
+---+
|Yo||
+---+
+---+
||Ya|
+---+
+-+
+-+
+---+
|Yip|
|---|
+---+
+---+
|---|
|Yap|
+---+
++
||
++
+------+
|+----+|
||allo||
|+----+|
+------+
+--------+
|+------+|
||+----+||
|||allo|||
||+----+||
|+------+|
+--------+
+--------+
|+------+|
||+----+||
|||allo|||
||+----+||
|+------+|
|--------|
|Eh ben  |
+--------+
+----+
|a|++|
|b||||
|c||||
|d|++|
+----+
+-----------------+
|+------+|Eh ben  |
||+----+||--------|
|||allo|||+------+|
||+----+|||yo|hey||
|+------+|+------+|
+-----------------+

Vous constaterez que les avertissements d'usage s'appliquent encore ici : si votre design est propre, ce sera un ajout relativement simple. Si vous essayez d'y aller par force brute et de tricher, ce sera... douloureux.

Prenez le temps de réfléchir à votre design. C'est un travail pratique amusant, et instructif.


Valid XHTML 1.0 Transitional

CSS Valide !