bonjour
ne pas tenir compte de ma question pr�c�dente
Version imprimable
bonjour
ne pas tenir compte de ma question pr�c�dente
D�sol� mais pour moi ce n'est pas un tutoriel et encore moins un cours car au final on apprend peu de choses tellement le code est incompr�hensible.
Il aurait m�rit� plus d'explications et de d�tails...pour que ce soit un minimum ludique. :weird:
Joli le d�terrage, alors que la derni�re intervention datais de ... trois ans.
Ceci dit, nous sommes en face d'un article, qui explique parfaitement le point de vue de l'auteur. Il n'a jamais �t� question d'en faire un tutoriel ;)
Si le code t'a sembl� obscure, je pencherais volontiers d'avantage pour le fait qu'il te manque quelques concepts de base ou quelque notions de C++ que pour autre chose.
Bien sur, �tant particuli�rement � l'aise avec le langage, je ne suis sans doute pas le mieux plac� pour parler de la difficult� du code, mais je n'ai rien trouv� de bien compliqu� dans les explications ;)
Enfin, il n'y a rien � faire: la programmation oscille entre la science exacte et l'art, ce qui fait que, au del� d'un certain niveau, la ludicit� n'a plus vraiment sa place: elle doit la c�der � l'exactitude. Et c'est le cas de cet article ;)
En relisant l'article, je vois que l'auteur demande � l'utilisateur de lui passer des callbacks pour d�cider quoi faire � chaque �tape de lecture du fichier CSV :
Cette conception ne m'avait pas choqu� � l'�poque, mais elle me g�ne aujourd'hui. En fait, je trouve cette conception tout � fait justifi�e pour l'�poque o� a �t� �crit cet article, en 2015, donc � l'�poque du C++14. Mais je me dis qu'elle est surtout justifi�e par les limitations du C++ de l'�poque et de la biblioth�que standard de l'�poque et qu'il faudra privil�gier une autre approche en C++20.Code:
1
2
3
4
5 std::function<bool(string_type const &)> comment_handler; std::function<bool(string_type const &)> field_handler; std::function<bool()> end_line_handler; std::function<bool()> end_file_handler; std::function<void(csv_error,int,int)> error_handler;
Je vais prendre un exemple basique et faire un parall�le avec le langage Python. Admettons qu'un fichier CSV repr�sente une liste d'utilisateurs, sous la forme d'un utilisateur par ligne. Parmi les champs, l'un d'eux contient le nom de l'utilisateur et un autre vaut 0 ou 1 selon que l'utilisateur soit actif ou inactif. On veut afficher la liste des noms des utilisateurs actifs.
En Python, on peut facilement d�couper le code en plusieurs niveaux d'abstractions.
On peut partir de csv.reader qui retourne un it�rable de listes de cha�nes (une liste = une ligne ; une cha�ne = une cellule). Appelons my_reader cet it�rable.
Ensuite, si on d�finit une fonction fn convert_row_to_user(row: List[str]) -> User qui prend en param�tre une liste de cha�nes et retourne un objet de type User, alors users = map(convert_row_to_user, my_reader) cr�e un it�rable d'objets de type User � partir de l'it�rable de d�part.
Admettons que la classe User contienne une propri�t� active. On peut alors �crire active_users = filter(lambda user: user.active, users) pour cr�er un it�rable d'objets de type User qui ne contient que les utilisateurs actifs.
Admettons que la classe User contienne une propri�t� name. On peut alors �crire active_user_names = map(lambda user: user.name, active_users) pour cr�er un it�rable de cha�nes qui correspond aux noms des utilisateurs actifs.
Pr�cisons que l'�valuation est paresseuse : c'est en parcourant les �l�ments de l'it�rable active_user_names qu'on lit les lignes du fichier CSV. Tant qu'on n'a pas encore atteint la fin de l'it�rable, on n'a pas encore lu en entier le fichier CSV.
L'un des avantages est que l'on peut facilement d�couper le code en sous-fonctions r�utilisables. Par exemple, on peut avoir une fonction get_active_user_names qui appelle une sous-fonction get_active_users qui appelle une fonction get_users.
Mais, si on remplace l'it�rable de d�part par un syst�me de callbacks comme dans l'article, �a casse tout dans le code qui utilise le parseur de fichier CSV : au lieu d'�crire du beau code avec des fonctions d�compos�es en sous-fonctions comme on veut, de la propagation d'erreur lisible, des �ventuelles boucles, etc., on se retrouve � coder une machine � �tats en partie monolithique dont la maintenabilit� d�cro�t avec la complexit� du code qui est ex�cut� avant la fin de la lecture du fichier CSV.
En C++17, on pourrait concevoir le parseur de fichier CSV sous la forme d'un range dont les �l�ments auraient un type du genre std::variant<comment, field, end_line, error> (la fin du fichier se traduirait par la fin du range).
Par dessus, l'utilisateur pourrait cr�er un range dont chaque �l�ment repr�sente une ligne de fichier CSV. En cas d'erreur de lecture, on lance une exception. Ce type de code devrait �tre facilit� en C++20 avec les coroutines.
Ensuite, pour que l'utilisateur puisse, comme dans l'exemple en Python, g�n�rer facilement un range d'utilisateurs par dessus le range de lignes puis g�n�rer facilement un range d'utilisateurs actifs par dessus le range d'utilisateurs, on devrait aussi avoir les �quivalents de filter et map en C++20 (std::views::filter et std::views::transform). Il faudra faire attention � la gestion de la m�moire, mais le code devrait rester lisible.
Mais l'article pr�sent date de 2015 o� il n'y avait ni std::variant du C++17, ni les fonctionnalit�s sympathiques qui arriveront en C++20, donc c'est tout � fait normal que l'auteur ait choisi une conception avec un syst�me de callbacks. Les limitations du langage conditionnent la mani�re � laquelle on con�oit les interfaces.