Estoy tratando de entender el principio de Responsabilidad Única, pero tengo dificultades para comprender el concepto. Estoy leyendo el libro "Patrones de diseño y mejores prácticas en Java de Lucian-Paul Torje; Adrian Ianculescu; Kamalmeet Singh".

En este libro, estoy leyendo el capítulo del principio de responsabilidad única, donde tienen una clase de automóvil como se muestra a continuación:

enter image description here

Dijeron que Car tiene operaciones de base de datos y lógica de Car. En el futuro, si queremos cambiar la base de datos, entonces necesitamos cambiar la lógica de la base de datos y es posible que también necesitemos cambiar la lógica del automóvil. Y viceversa...

La solución sería crear dos clases como se muestra a continuación:

enter image description here

Mi pregunta es incluso si creamos dos clases, consideremos que estamos agregando una nueva propiedad llamada 'precio' a la clase CAR [O cambiando la propiedad 'modelo' a 'carModel'], entonces, ¿no cree que también necesitamos actualizar CarDAO clase como cambiar el SQL, etc.

Entonces, ¿cuál es el uso de SRP aquí?

4
vicky 9 sep. 2018 a las 21:12

3 respuestas

La mejor respuesta

Gran pregunta

Primero, tenga en cuenta que este es un ejemplo simplista en el libro. Depende del lector expandir esto un poco e imaginar escenarios más complejos. En todos estos escenarios, imagine además que no es el único desarrollador del equipo; en cambio, está trabajando en un gran equipo, y la comunicación entre desarrolladores a menudo toma la forma de negociación de interfaces de clase es decir API, métodos públicos, atributos públicos, esquemas de bases de datos. Además, a menudo tendrá que preocuparse por los retrocesos, la compatibilidad con versiones anteriores y la sincronización de lanzamientos e implementaciones.

Supongamos, por ejemplo, que desea intercambiar la base de datos, por ejemplo, de MySQL a PostgreSQL. Con SRP, volverá a implementar CarDAO, cambiará el SQL específico del dialecto que se haya utilizado y dejará intacta la lógica Car. Sin embargo, es posible que tenga que hacer un pequeño cambio, posiblemente en la configuración, para indicarle a Car que use el nuevo DAO PostgreSQL. Un marco DI razonable haría esto simple.

Supongamos, en otro ejemplo, que desea delegar CarDAO a otro desarrollador para que se integre con memcached, de modo que las lecturas, aunque finalmente sean consistentes, sean rápidas. Nuevamente, este desarrollador no necesitaría saber nada sobre la lógica de negocios en Car. En cambio, solo necesitan operar detrás de los métodos CRUD de CarDAO, y posiblemente declarar algunos métodos más en la API CarDAO con diferentes garantías de consistencia.

Supongamos, en otro ejemplo, que su equipo contrata a un ingeniero de bases de datos especializado en leyes de cumplimiento. En preparación para la próxima salida a bolsa, el ingeniero de la base de datos tiene la tarea de mantener un registro de auditoría de todos los cambios en todas las tablas en las 35 bases de datos de la compañía. Con SRP, nuestro intrépido DBA no tendría que preocuparse por ninguna de las lógica de negocios utilizando ninguna de nuestras tablas; en cambio, su magia de seguimiento de mutaciones se puede inyectar hábilmente en DAO por todas partes, utilizando decoradores u otras técnicas de programación de aspectos. (Por cierto, esto también podría hacerse desde el otro lado de la interfaz SQL).

Bien, una última: supongamos que ahora se incorpora un ingeniero de sistemas al equipo y se le asigna la tarea de dividir estos datos en varias regiones (centros de datos) en AWS. Este ingeniero podría llevar a SRP aún más lejos y agregar un componente cuyo único rol sea decirnos, para cada ID, la región de origen de cada entidad. Cada vez que hacemos una lectura entre regiones, el nuevo componente golpea un contador; Cada semana, una herramienta automatizada migra los datos que se leen con frecuencia a través de regiones a una nueva región de origen para reducir la latencia.

Ahora, llevemos nuestra imaginación aún más lejos, y supongamos que el negocio está en auge: de repente, está trabajando para una compañía Fortune 500 con múltiples departamentos que abarcan varios países. Los analistas de negocios del Departamento de Finanzas quieren usar su tabla para trazar el crecimiento trimestral de las ventas de automóviles en sus informes de inversionistas posteriores a la OPV. En lugar de darles acceso a Car (debido a que la lógica utilizada para generar informes puede ser diferente de la lógica utilizada para preparar los datos para la representación en una interfaz de usuario web), podría crear una interfaz de solo lectura para {{ X1}} con una breve lista de atributos públicos cuidadosamente seleccionados que ahora debe mantener a través de los límites del departamento. Dios no quiera que tengas que cambiar el nombre de uno de estos atributos: prepárate para un plan de puesta de sol de 3 meses y muchos muchos tableros tristes y escaladas nocturnas. (Y no les dé acceso directo a la tabla SQL real, porque la suposición implícita será que toda la tabla es la interfaz pública). Vaya, mis cicatrices pueden estar mostrando.

Un corolario es que, si necesita cambiar la lógica de negocios en Car (por ejemplo, agregue un método que calcule el precio de venta más bajo de cada Tesla después de un retiro vergonzoso), no t toque CarDAO, ya que if car.brand == 'Tesla; price = price * 0.6 no tiene nada que ver con el acceso a datos.

Lectura adicional: CQRS

7
James Lim 9 sep. 2018 a las 19:18

Principio de responsabilidad única según lo establecido por Robert C. Martin significa que

Una clase debe tener solo una razón para cambiar.

Tener en cuenta este principio generalmente conducirá a clases más pequeñas y altamente cohesivas, lo que a su vez significa que menos personas necesitan trabajar en estas clases simultáneamente, y el código se vuelve más robusto.

En su ejemplo, mantener la acceso a datos y la lógica de negocios (cálculo de precios) separadas significa que es menos probable que rompa el otro al hacer cambios.

2
Mick Mnemonic 9 sep. 2018 a las 18:52

Para agregar una nueva propiedad, debe cambiar ambas clases solo si esa propiedad debe guardarse en la base de datos. Si se trata de una propiedad utilizada en la lógica empresarial, no es necesario cambiar el DAO. Además, si cambia su base de datos de un proveedor a otro o de SQL a NoSQL, tendrá que hacer cambios solo en la clase DAO. Y si necesita cambiar algo de lógica de negocios, entonces necesita cambiar solo la clase Car.

2
Ivan 9 sep. 2018 a las 18:20