Je pense que ce que vous décrivez est que les objets doivent prendre en charge les opérations qui ne nécessitent que leur propre comportement, ce qui est généralement une bonne règle à suivre. Il n'y a rien de mal avec une classe "processeur", à condition qu'elle "traite" quelques choses différentes (mais liées).Mais si vous avez une classe qui ne traite qu'une seule chose (comme un parseur CSV ne traite que des CSV), alors il n'y a vraiment aucune raison pour que le processeur ne fasse pas le traitement sur lui-même. Cependant, il y a une raison courante pour enfreindre cette règle: habituellement vous ne voulez pas faire des choses que vous n'avez pas à faire. Par exemple, avec votre classe CSV, si tout ce que vous voulez est de trouver la ligne dans le CSV où la première cellule est "Bob" et obtenir la troisième colonne dans cette rangée (qui est, disons, la date de naissance de Bob) alors vous ne Je veux lire tout le fichier, l'analyser, puis chercher dans la structure de données que vous venez de créer: c'est inefficace, surtout si votre CSV a 100K lignes et l'entrée de Bob sur la ligne 5.
Classe CSV pour faire des opérations à petite échelle sur CSV, comme sauter à la ligne suivante et obtenir la première cellule. Mais maintenant vous mettez en œuvre des méthodes dont vous ne parleriez pas vraiment d'un fichier CSV. Les CSV ne lisent pas les lignes, ils les stockent. Ils ne trouvent pas de cellules, ils les ont juste. En outre, si vous souhaitez effectuer une opération à grande échelle, telle que la lecture dans l'intégralité du fichier CSV et le tri des lignes par la première cellule, vous souhaiterez avoir votre ancienne méthode de lecture dans le fichier entier, l'analyser et la parcourir toute la structure de données que vous avez créée. Vous pouvez faire les deux dans la même classe, mais maintenant votre classe est vraiment deux classes à deux fins différentes. Votre classe a perdu la cohésion et toute instance de la classe que vous créez aura deux fois plus de bagages, alors que vous n'en utiliserez probablement que la moitié.
Dans ce cas, il est logique d'avoir une abstraction de haut niveau de la classe CSV (pour les opérations à grande échelle) et une classe «processeur» pour les opérations de bas niveau. (Ce qui suit est écrit en Java depuis que je sais mieux que je sais C#):
public class CSV
{
final private String filename;
private String[][] data;
private boolean loaded;
public CSV(String filename) { ... }
public boolean isLoaded() { ... }
public void load() { ... }
public void saveChanges() { ... }
public void insertRowAt(int rowIndex, String[] row) { ... }
public void sortRowsByColumn(int columnIndex) { ... }
...
}
public class CSVReader
{
/*
* This kind of thing is reasonably implemented as a subclassable singleton
* because it doesn't hold state but you might want to subclass it, perhaps with
* a processor class for another tabular file format.
*/
protected CSVReader();
protected static class SingletonHolder
{
final public static CSVReader instance = new CSVReader();
}
public static CSVReader getInstance()
{
return SingletonHolder.instance;
}
public String getCell(String filename, int row, int column) { ... }
public String searchRelative(String filename,
String searchValue,
int searchColumn,
int returnColumn)
{ ... }
...
}
Un exemple bien connu de ce même est SAX et DOM. SAX est l'accès de bas niveau, à granularité fine, tandis que DOM est l'abstraction de haut niveau.
Est-ce que ça ne devrait pas être un wiki de ma communauté? (Je ne peux pas croire que je suis devenu l'une des personnes qui posent cette question.) – Imagist