Le problème des boîtes imbriquées

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.

À titre d'exemple, le programme de test suivant :

#include "boite.h"
#include "combovertical.h"
#include "combohorizontal.h"
#include <string>
#include <iostream>

int main() {
   using namespace std;
   Boite b;
   cout << b << endl;
   string texte = R"(Man! Hey!!!
ceci est un test
multiligne)";
   string aut_texte = "Ceci\nitou, genre";
   Boite b0{texte};
   Boite b1{aut_texte};
   cout << b0 << endl << b1 << endl;
   ComboVertical cv{b0, b1};
   cout << Boite{cv} << endl;
   ComboHorizontal ch{b0, b1};
   cout << Boite{ch} << endl;
   ComboVertical cvplus{Boite{cv}, Boite{ch}};
   cout << Boite{cvplus} << endl;
   ComboHorizontal chplus{Boite{cv}, Boite{ch}};
   cout << Boite{chplus} << endl;
   ComboVertical cvv{Boite{chplus}, Boite{"coucou"}};
   cout << Boite{cvv} << endl;
   cout << Boite{
      ComboHorizontal{
         Boite{"a\nb\nc\nd\ne"},
         Boite{
            ComboVertical{
               Boite{"allo"}, Boite{"yo"}
            }
         }
      }
    } << endl;
   cout << Boite{
      ComboHorizontal{ Boite{"Yo"}, Boite{} }
   } << endl;
   cout << Boite{
      ComboHorizontal{ Boite{}, Boite{"Ya"} }
   } << endl;
   cout << Boite{
      ComboHorizontal{ Boite{}, Boite{} }
   } << endl;
   cout << Boite{
      ComboVertical{ Boite{}, Boite{} }
   } << endl;
   cout << Boite{
      ComboVertical{ Boite{"Yip"}, Boite{} }
   } << endl;
   cout << Boite{
      ComboVertical{ Boite{}, Boite{"Yap"} }
   } << endl;
}

...doit résulter en l'affichage suivant :

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

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 presque trois semaines 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.

Pour un équivalent C#, si cela vous intéresse, le code client serait :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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

... ce qui n'est pas nécessairement plus simple, mais c'est une question de point de vue je présume.

De même, pour un équivalent Java, on aurait :

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

... ce qui est aussi laborieux, mais voilà.

Si vous êtes curieuse/ curieux

Votre chic prof, quand il a résolu le problème, a refactorisé de manière relativement importante la solution existante jusque là. Vous n'avez absolument pas à faire comme lui. Pris d'un point de vue aérien, le schéma de sa solution est :

Quelques remarques :

Pris d'un peu plus près, nous avons :

Quelques remarques :

À titre d'exemple, pour mes fins, la classe ComboVertical::Enumerateur dérive d'IEnumerateur<IBoite::str_type> 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 ».


Valid XHTML 1.0 Transitional

CSS Valide !