Quando si progetta una classe, dovrebbe essere favorita la coerenza del comportamento rispetto alla pratica di programmazione comune? Per dare un esempio specifico:
Una convenzione comune è questa: se una classe possiede un oggetto (ad es. lo ha creato) è responsabile di ripulirlo una volta fatto. Un esempio specifico potrebbe essere in .NET che se la tua classe possiede un oggetto IDisposable
dovrebbe eliminarlo alla fine della sua vita. E se non lo possiedi, non toccarlo.
Ora, se osserviamo la classe StreamWriter
in .NET, possiamo trovare nella documentazione che chiude il flusso sottostante quando viene chiuso / eliminato. Ciò è necessario nei casi in cui il StreamWriter
viene istanziato passando un nome file mentre il writer crea il flusso di file sottostante e pertanto deve chiuderlo. Tuttavia si può anche passare in un flusso esterno che lo scrittore chiude anche.
Questo mi ha infastidito un sacco di volte (sì, so che puoi creare un involucro non chiudibile ma non è questo il punto) ma a quanto pare Microsoft ha preso la decisione che è più coerente chiudere sempre il flusso, non importa da dove provenga .
Quando mi imbatto in un modello di questo tipo in una delle mie classi di solito creo un flag ownsFooBar
che viene impostato su false nei casi in cui FooBar
viene iniettato tramite il costruttore e vero altrimenti. In questo modo la responsabilità di pulirlo viene passata al chiamante quando passa esplicitamente l'istanza.
Ora mi chiedo se forse la coerenza dovrebbe essere a favore delle migliori pratiche (o forse la mia migliore pratica non è così buona)? Qualsiasi argomento per / contro di esso?
Modifica per chiarimenti
Con "coerenza" intendo: il comportamento coerente della classe che acquisisce sempre la proprietà (e chiude il flusso) rispetto alla "best practice" per assumere solo la proprietà di un oggetto se lo hai creato o se ne è stata esplicitamente trasferita la proprietà.
Come per un esempio in cui è entusiasmante:
Supponi di avere due classi date (da una libreria di terze parti) che accettano uno stream per fare qualcosa con esso, come la creazione e l'elaborazione di alcuni dati:
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))
{
....
}
}
}
Ora voglio usarlo in questo modo:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Questo fallirà con un'eccezione Cannot access a closed stream
nell'elaboratore di dati. È un po 'costruito ma dovrebbe illustrare il punto. Ci sono vari modi per risolverlo, ma tuttavia ritengo di aggirare qualcosa che non dovrei avere.