Escribo mucho código que implica tres pasos básicos.
- Obtenga datos de alguna parte.
- Transforma esos datos.
- Ponga esos datos en alguna parte.
Normalmente termino usando tres tipos de clases, inspirados por sus respectivos patrones de diseño.
- Fábricas: para construir un objeto a partir de algún recurso.
- Mediadores: para usar la fábrica, realizar la transformación y luego usar el comandante.
- Comandantes: para poner esos datos en otro lugar.
Mis clases tienden a ser bastante pequeñas, a menudo un único método (público), por ejemplo, obtener datos, transformar datos, trabajar, guardar datos. Esto conduce a una proliferación de clases, pero en general funciona bien.
Cuando lucho es cuando vengo a las pruebas, termino con pruebas estrechamente acopladas. Por ejemplo;
- Fábrica: lee archivos del disco.
- Comandante: escribe archivos en el disco.
No puedo probar uno sin el otro. Podría escribir código de 'prueba' adicional para hacer lectura / escritura en disco también, pero luego me estoy repitiendo.
Mirando a .Net, la clase File adopta un enfoque diferente, combina las responsabilidades (de mi) fábrica y comandante juntos. Tiene funciones para Crear, Eliminar, Existe y Leer todo en un solo lugar.
¿Debería seguir el ejemplo de .Net y combinar, particularmente cuando se trata de recursos externos, mis clases juntas? El código aún se acopla, pero es más intencional: ocurre en la implementación original, en lugar de en las pruebas.
¿Es mi problema aquí que he aplicado el Principio de Responsabilidad Única de manera algo entusiasta? Tengo clases separadas responsables de leer y escribir. Cuando podría tener una clase combinada que es responsable de tratar con un recurso en particular, por ejemplo, el disco del sistema.
Looking at .Net, the File class takes a different approach, it combines the responsibilities (of my) factory and commander together. It has functions for Create, Delete, Exists, and Read all in one place.
- Tenga en cuenta que está combinando "responsabilidad" con "algo que hacer". Una responsabilidad es más como un "área de preocupación". La responsabilidad de la clase File es realizar operaciones de archivo.
File
biblioteca de C # es que, por lo que sabemos, la File
clase podría ser simplemente una fachada, colocando todas las operaciones de archivo en un solo lugar, dentro de la clase, pero podría estar usando internamente clases de lectura / escritura similares a las suyas, lo que en realidad contienen la lógica más complicada para el manejo de archivos. Dicha clase (the File
) aún se adheriría al SRP, porque el proceso de trabajar realmente con el sistema de archivos se abstraería detrás de otra capa, muy probablemente con una interfaz unificadora. No digo que sea el caso, pero podría serlo. :)