No se trata solo de POLA, sino también de prevenir un estado no válido como una posible fuente de errores.
Veamos cómo podemos proporcionar algunas restricciones a su ejemplo sin proporcionar una implementación concreta:
Primer paso: no permita que se llame a nada antes de abrir un archivo.
CreateDataFileInterface
+ OpenFile(filename : string) : DataFileInterface
DataFileInterface
+ SetHeaderString(header : string) : void
+ WriteDataLine(data : string) : void
+ SetTrailerString(trailer : string) : void
+ Close() : void
Ahora debería ser obvio que se CreateDataFileInterface.OpenFiledebe llamar para recuperar una DataFileInterfaceinstancia, donde se pueden escribir los datos reales.
Segundo paso: asegúrese de que los encabezados y trailers siempre estén configurados.
CreateDataFileInterface
+ OpenFile(filename : string, header: string, trailer : string) : DataFileInterface
DataFileInterface
+ WriteDataLine(data : string) : void
+ Close() : void
Ahora debe proporcionar todos los parámetros necesarios por adelantado para obtener un DataFileInterface: nombre de archivo, encabezado y avance. Si la cadena de avance no está disponible hasta que se escriben todas las líneas, también puede mover este parámetro aClose() (posiblemente renombrando el método a WriteTrailerAndClose()) para que el archivo al menos no pueda finalizar sin una cadena de avance.
Para responder al comentario:
Me gusta la separación de la interfaz. Pero me inclino a pensar que su sugerencia sobre la aplicación (por ejemplo, WriteTrailerAndClose ()) está al borde de una violación de SRP. (Esto es algo con lo que he luchado en varias ocasiones, pero su sugerencia parece ser un posible ejemplo). ¿Cómo respondería?
Cierto. No quería concentrarme más en el ejemplo de lo necesario para hacer mi punto, pero es una buena pregunta. En este caso, creo que lo llamaría Finalize(trailer)y argumentaría que no hace demasiado. Escribir el tráiler y cerrar son simples detalles de implementación. Pero si no está de acuerdo o tiene una situación similar en la que es diferente, aquí hay una posible solución:
CreateDataFileInterface
+ OpenFile(filename : string, header : string) : IncompleteDataFileInterface
IncompleteDataFileInterface
+ WriteDataLine(data : string) : void
+ FinalizeWithTrailer(trailer : string) : CompleteDataFileInterface
CompleteDataFileInterface
+ Close()
Realmente no lo haría para este ejemplo, pero muestra cómo llevar a cabo la técnica en consecuencia.
Por cierto, supuse que los métodos deben llamarse en este orden, por ejemplo, para escribir secuencialmente muchas líneas. Si esto no es necesario, siempre preferiría un constructor, como lo sugirió Ben Cottrel .