[Conception] Choix de l'interface publique d'une classe
Bonjour,
Je dois écrire une classe (sql::table) qui contient deux séquences d'éléments : une séquence d'instances de la classe sql::column et une séquence d'instances de la classe sql::row. L'utilisateur de la classe sql::table doit être à même d'ajouter, de supprimer et de parcourir les éléments des deux séquences.
La question que je me pose est au niveau de l'interface à offrir. Voici ce que j'ai pour l'instant :
Comme le cas le plus fréquent est celui où l'on veut parcourir les sql::row, les méthodes sql::table::begin() et sql::table::end() retourne respectivement l'itérateur de début et de fin de la séquence. Pour les sql::column, ce sont les méthodes sql::table::column_begin() et sql::table::column_end() qui s'en chargent.
Reste l'ajout/suppression, la surcharge des paramètre permet d'écrire une fonction sql::table::insert() qui ajoute dans la séquence de sql::row et une surcharge ajoutant dans la séquence de sql::column. Il serait aussi possible de faire de même pour la fonction sql::table::erase().
Voici un exemple de code :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <algorithm>
#include <vector>
namespace sql {
class column { };
class row { };
class table {
public:
std::vector<row>::iterator begin() { return std::begin(m_rows); }
std::vector<row>::iterator end() { return std::end(m_rows); }
std::vector<column>::iterator column_begin() { return std::begin(m_columns); }
std::vector<column>::iterator column_end() { return std::end(m_columns); }
std::vector<row>::iterator insert(std::vector<row>::iterator position, const row& x) { m_rows.insert(position, x); }
std::vector<column>::iterator insert(std::vector<column>::iterator position, const column& x) { m_columns.insert(position, x); }
void push_back(const row& x) { m_rows.push_back(x); }
void push_back(const column& x) { m_columns.push_back(x); }
private:
std::vector<column> m_columns;
std::vector<row> m_rows;
};
}
int main() {
sql::table t;
sql::column column1, column2, column3;
t.insert(t.column_begin(), column1);
t.push_back(column2);
t.push_back(column3);
sql::row row1, row2, row3;
t.insert(t.begin(), row1);
t.push_back(row2);
t.push_back(row3);
std::for_each(t.column_begin(), t.column_end(), [](sql::column& c) {
// Do something
});
for(sql::row& r : t) {
// Do something
}
} |
Est-ce que cette interface est viable et, si non, quelles modifications devraient y être apportées?
Je cherche une solution qui :
- Soit simple d'utilisation pour l'utilisateur;
- N'expose pas l'implémentation interne (remarquez que je n'ai jamais précisé comment sont stockées les séquences);
- Soit flexible (permet de faire toute manipulation souhaité);
- S'intègre bien à du code tel que la STL ou Boost.