¿Cuando se diseña una clase, se debería favorecer la coherencia en el comportamiento sobre la práctica de programación común? Para dar un ejemplo específico:
Una convención común es esta: si una clase posee un objeto (por ejemplo, lo creó), es responsable de limpiarlo una vez que esté listo. Un ejemplo específico sería en .NET que si su clase posee un objeto IDisposable
debería eliminarlo al final de su vida útil. Y si no lo tienes, entonces no lo toques.
Ahora, si observamos la clase StreamWriter
en .NET, podemos encontrar en la documentación que cierra el flujo subyacente cuando se está cerrando / eliminando. Esto es necesario en los casos en que StreamWriter
se crea una instancia al pasar un nombre de archivo, ya que el escritor crea la secuencia de archivos subyacente y, por lo tanto, necesita cerrarlo. Sin embargo, también se puede pasar en una secuencia externa que el escritor también cierra.
Esto me ha molestado muchas veces (sí, sé que puedes hacer una envoltura que no cierra, pero ese no es el punto), pero al parecer Microsoft ha tomado la decisión de que es más coherente siempre cerrar el flujo, sin importar de dónde venga. .
Cuando me cruzo con un patrón de este tipo en una de mis clases, normalmente creo un indicador ownsFooBar
que se establece en falso en los casos en que se inyecta FooBar
a través del constructor y, de lo contrario, se cumple. De esta manera, la responsabilidad de limpiarlo se pasa al que llama cuando pasa la instancia explícitamente.
Ahora me pregunto si tal vez la coherencia debería estar a favor de la mejor práctica (o tal vez mi mejor práctica no sea tan buena). ¿Algún argumento a favor o en contra?
Editar para aclarar
Con "coherencia" quiero decir: el comportamiento coherente de la clase que siempre toma posesión (y cierra el flujo) frente a la "mejor práctica" para tomar posesión de un objeto solo si lo creó o transfirió explícitamente la propiedad.
En cuanto a un ejemplo donde es enoying:
Suponga que tiene dos clases (de una biblioteca de terceros) que aceptan una secuencia para hacer algo con ella, como crear y procesar algunos datos:
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))
{
....
}
}
}
Ahora quiero usarlo así:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Esto fallará con una excepción Cannot access a closed stream
en el procesador de datos. Está un poco construido pero debería ilustrar el punto. Hay varias formas de solucionarlo pero, sin embargo, siento que trabajo en torno a algo que no debería tener que hacer.