Lors de la conception d'une classe, la cohérence des comportements doit-elle être privilégiée par rapport aux pratiques de programmation courantes? Pour donner un exemple précis:
Une convention courante est la suivante: si une classe possède un objet (par exemple, il l'a créé), elle est responsable de le nettoyer une fois qu'il est terminé. Un exemple spécifique serait dans .NET que si votre classe possède un IDisposable
objet, elle devrait le disposer à la fin de sa vie. Et si vous ne le possédez pas, ne le touchez pas.
Maintenant, si nous regardons la StreamWriter
classe dans .NET, nous pouvons trouver dans la documentation qu'elle ferme le flux sous-jacent lorsqu'elle est fermée / supprimée. Cela est nécessaire dans les cas où l' StreamWriter
instanciation en passant dans un nom de fichier en tant que scénariste crée le flux de fichiers sous - jacent et doit donc fermer. Cependant, on peut également passer dans un flux externe que l'écrivain ferme également.
Cela m'a énervé des tas de fois (oui, je sais que vous pouvez créer un wrapper non fermant, mais ce n'est pas le sujet), mais apparemment, Microsoft a décidé qu'il est plus cohérent de toujours fermer le flux, peu importe d'où il vient.
Lorsque je rencontre un tel modèle dans l'une de mes classes, je crée généralement un ownsFooBar
indicateur qui est défini sur false dans les cas où il FooBar
est injecté via le constructeur et sur true dans le cas contraire. De cette façon, la responsabilité de le nettoyer est transférée à l'appelant lorsqu'il passe explicitement l'instance.
Maintenant, je me demande si peut-être la cohérence devrait être en faveur des meilleures pratiques (ou peut-être que mes meilleures pratiques ne sont pas si bonnes)? Des arguments pour / contre?
Modifier pour clarification
Par «cohérence», je veux dire: le comportement cohérent de la classe prenant toujours la propriété (et fermant le flux) par rapport aux «meilleures pratiques» pour ne s'approprier un objet que si vous l'avez créé ou transféré explicitement la propriété.
Quant à un exemple où c'est énervant:
Supposons que vous ayez deux classes données (provenant d'une bibliothèque tierce) qui acceptent un flux pour en faire quelque chose, comme créer et traiter des données:
public class DataProcessor
{
public Result ProcessData(Stream input)
{
using (var reader = new StreamReader(input))
{
...
}
}
}
public class DataSource
{
public void GetData(Stream output)
{
using (var writer = new StreamWriter(output))
{
....
}
}
}
Maintenant, je veux l'utiliser comme ceci:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Cela échouera avec une exception Cannot access a closed stream
dans le processeur de données. C'est un peu construit mais devrait illustrer le point. Il existe différentes façons de le réparer, mais j'ai néanmoins l'impression de contourner quelque chose que je ne devrais pas avoir à faire.