¿Cómo define una responsabilidad?

7

Aprendí los principios de SOLID en 2011 y trato de usarlos en mi trabajo diario.

Sin embargo, a menudo me encuentro vagando si estoy rompiendo el principio de Responsabilidad Única. Una clase puede tener varias responsabilidades:

  1. Presentación
  2. Repositorio
  3. servicio
  4. dominio
  5. infraestructura etc.

También veo quejas si una clase contiene un comportamiento que debería estar en otra, por ejemplo. Funcionalidad OrderItem en la clase de orden. Este es con el que lucho.

No mezclo presentación con acceso a datos. No mezclo el servicio con el dominio, etc. Sin embargo, veo preguntas aquí que me parecen bien y un contestador se queja de que el SRP no funciona. ¿Cómo decides que una clase tiene una sola responsabilidad? Me doy cuenta de que esto puede variar de un dominio a otro. Lo que busco es una metodología que me ayude a decidir si una clase tiene una responsabilidad única (quizás un conjunto de preguntas).

    
pregunta w0051977 27.06.2017 - 21:15

5 respuestas

15

Cuando algo tiene solo una responsabilidad, solo debe tener una razón para cambiar.

De hecho, esta es una razón importante por la que nos preocupamos por otorgar a las cosas una sola responsabilidad. Contiene el impacto de los cambios.

Ahora, esto no significa que dentro de cada clase encuentre solo un método o una variable miembro. Significa que los métodos internos deben aislar los cambios entre sí teniendo sus propias responsabilidades. Y la clase en su conjunto debe tener una responsabilidad que los abarque, y solo a ellos. Ah, y la clase debe tener un nombre que haga que los métodos que encuentres en el interior no sean ninguna sorpresa.

Así que sí, si quisiera, podría organizar una sola clase que tuviera un método responsable de la presentación, uno para el repositorio, uno para proporcionar un servicio, uno que proporcionara alguna funcionalidad de dominio y otro que existiera para satisfacer algún requisito de infraestructura . Eso sería raro. Pero mientras la clase en general exista para cumplir con una sola responsabilidad, como por ejemplo, CatVideo , entonces es mejor que todos esos métodos traten de hacer todas esas cosas por un CatVideo .

En resumen, las responsabilidades pueden anidar. Está bien mirar dentro de algo con una sola responsabilidad y encontrar otras cosas que tengan responsabilidades individuales.

Lo que no está bien es una clase que intenta hacer el trabajo de dos clases. O una función tratando de hacer el trabajo de dos funciones. O un paquete tratando de hacer el trabajo de dos paquetes. Cualquiera que sea la cosa del momento, decirme de qué es responsable no debe incluir la palabra "y".

Ahora, si algunos de los métodos en CatVideo son sobre Cat y sobre Video, puede ser que, en lugar de una sola responsabilidad, hay dos responsabilidades juntas que realmente necesitan dos objetos: Cat y Video . Si estas responsabilidades pueden separarse, deberían serlo. Pero si un CatVideo es realmente una sola idea en este dominio, entonces está bien como está.

Cuando las responsabilidades se anidan bien, puedes arrancar una sin afectar a otras. Si su clase CatVideo ha cambiado su repositorio, eso no significa que la presentación deba cambiar. Si lo hace, la presentación estaba asumiendo algunas de las responsabilidades de los repositorios.

SRP no es solo sobre clases. Se aplica a cada abstracción que tienes en tu idioma.

    
respondido por el candied_orange 27.06.2017 - 21:45
7

El Principio de Responsabilidad Única (SRP) es ampliamente mal entendido, posiblemente debido a un nombre engañoso.

El principio es sobre cómo cambia el código. No en el sentido de cambios de estado durante la ejecución, sino sobre cómo se edita el código fuente a lo largo del tiempo en respuesta a los requisitos cambiantes.

El peor tipo de sistema es aquel en el que un pequeño cambio de requisitos requiere que modifiques el código en muchos lugares diferentes de la fuente, y donde cada cambio hace que aparezcan errores y comportamientos inesperados en partes del código aparentemente no relacionadas.

Es fácil escribir código desde cero. El principal desafío del diseño de software es escribir código que pueda cambiar y adaptarse con el tiempo. Si observa algún código y decide que debe volver a escribirlo desde cero para admitir alguna nueva funcionalidad, entonces el código no fue diseñado de acuerdo con el SRP.

El SRP le dice que piense qué puede hacer que el código cambie con el tiempo. Por ejemplo, ¿por qué la presentación está separada del dominio? Debido a que es probable que la IU de una aplicación cambie independientemente de la lógica del dominio. Pasa todo el tiempo. Entonces, divide el código en unidades y clases según lo que puede cambiar de forma independiente.

Así que olvídate de las "responsabilidades", la palabra es demasiado nebulosa por sí misma. Piense en qué cambios en los requisitos podrían hacer que sea necesario cambiar un objeto.

    
respondido por el JacquesB 28.06.2017 - 10:15
4

Esta es una buena pregunta.

Si se me permite opinar, diría que el lenguaje es clave para el modelado. La metodología que está buscando está oculta en su comprensión de lectura.

Si se pretende que el POO sea un paradigma para modelar el mundo real, una buena pregunta sería: ¿Qué es el mundo real?

El mundo real no es otra cosa que nuestra percepción de esto. ¿Y adivina qué? Nuestra percepción está formada por nuestro lenguaje. En consecuencia, para modelar, debemos centrarnos en la comprensión de lectura y tener cuidado con el lenguaje que usamos para describir el problema (el dominio).

Al prestar atención al lenguaje, podemos suponer las diferentes abstracciones que entran en juego y cómo colaboran entre sí. No estoy diciendo nada nuevo, supongo que está al tanto del famoso Lenguaje Ubicuo de Eric Evans.

Para mí, las abstracciones y las responsabilidades están relacionadas.

En este punto, podría estar interesado en GRASP .

Podemos repetir el análisis del lenguaje para cada una de las abstracciones, ya que cada una de ellas puede descomponerse en diferentes niveles de abstracciones . La cantidad de niveles que necesitamos varía de un proyecto a otro, pero generalmente, una regla de oro es KISS.

  

En resumen, las responsabilidades pueden anidar. Está bien mirar dentro de algo   Con una sola responsabilidad y encontrar otras cosas que tienen solo.   responsabilidades.

     

respuesta de CandiedOrange

Con respecto a este proceso (composición / descomposición) puede interesarle top-down y bottom -up estrategias de diseño.

Tomemos como ejemplo una cadena de suministro , donde suministrar es el nivel más alto de abstracción, mientras que los diferentes trabajos a lo largo de la cadena son niveles más bajos de abstracción.

  

Nivel superior : Suministro

     

Nivel medio : Asamblea - > Embalaje - > Envío - > Entrega

     

...

Si necesitamos mejorar nuestra cadena con un proceso más rápido de entrega , podemos abordar la solución cambiando solo esta responsabilidad sin tener que cambiar toda la cadena. Pero podemos hacerlo porque entendemos que entregar y enviar son responsabilidades diferentes.

  

Cuando algo tiene una sola responsabilidad, solo debería tener una.   razón para cambiar.

     

respuesta de CandiedOrange

¿Necesita una evidencia más de la importancia del idioma?

  

Ah, y la clase debe tener un nombre que haga que los métodos que encuentres   dentro de ninguna sorpresa

     

respuesta de CandiedOrange

Si puede proporcionar sus abstracciones con nombres coherentes o si los nombres de sus abstracciones pueden describir de manera coherente lo que cada uno de ellos debe hacer, es probable que haya modelado correctamente las responsabilidades.

    
respondido por el Laiv 28.06.2017 - 00:53
0

Para seguir con su ejemplo de pedido, una vez que reconozca que su orden agrupa un montón de artículos, significa que la parte de agrupación es su responsabilidad y debe tener cuidado al agregar características que no están relacionadas con la agrupación de artículos.

Por lo tanto, no querrá que su orden ofrezca un precio total. Esto no está relacionado con el mantenimiento de la colección de artículos del pedido, es un problema de facturación. Tampoco desea que la orden determine si todos los artículos están en stock, se trata de una emisión de stock. Desea que ofrezca una forma de enumerar elementos para que otras clases puedan recorrerlos y recuperar la información relevante para ellos. Y desea limitar el número máximo de artículos que debería permitir para un solo pedido, si eso fuera limitado. Agregar elementos, eliminar elementos, esas son responsabilidades principales. Lo ideal es que el pedido no sepa qué es un artículo de pedido o lo que tiene que ofrecer.

Entonces, ¿qué hace que el pedido sea más que una lista? Está relacionado con un cliente. Tiene fecha y hora de colocación y cancelación. Estas son propiedades nativas, pertenecen directamente al orden en sí. No tenga la tentación de poner todo tipo de información de elementos de pedido consolidados en la interfaz de pedido.

Entonces, ¿cómo calcularías ese precio total? Podría tener una clase de factura que lleve un pedido como argumento a su constructor. La cantidad a pagar por el pedido sería un valor apropiado para la factura porque se trata del dinero que debe pagar el cliente.

Para la disponibilidad de artículos, puede tener una clase de stock que tenga un método GetItemAvailabily, que tome un artículo de pedido como un argumento. Una clase de OrderInformationProducer puede tomar un pedido, alimentar sus artículos a Stock.GetA Availability y producir un objeto de información de pedido que le diga al cliente lo que puede esperar.

El ejemplo anterior es solo para ilustrar una separación estricta de preocupaciones. Nunca hice un sistema de manejo de pedidos, por lo que puede ser demasiado simple o poco práctico. Espero que transmita la idea de SRP.

    
respondido por el Martin Maat 27.06.2017 - 22:49
-3

Los principios SÓLIDOS son un buen punto de partida para considerar cómo diseñar la arquitectura de un sistema, pero contiene un conjunto completo de todos los principios que debe evaluar un arquitecto de software.

A modo de ejemplo, SOLID no incluye el principio de Separación de Preocupaciones (SoC), que es un principio de diseño bastante importante, y el principio de SRP en SOLID no contiene ni reemplaza al principio de SoC.

El principio de SoC nos da mucha información sobre cómo organizar el código en diferentes capas de software y qué tipos de responsabilidades deben agruparse en qué capa.

Como tal, es solo en la capa de lógica de negocios donde debe residir el código de lógica de negocios: esta es la única capa donde los objetos de negocios u objetos de dominio realmente existen y tienen sentido.

En la capa de presentación, solo debe residir la lógica de presentación.

En la capa de acceso a datos, solo debe residir la lógica básica de acceso a datos: aquí es donde debe ocurrir la asignación entre el modelo de objetos y el modelo de datos.

Pero necesitamos tener un medio para transferir el estado de los objetos comerciales entre las capas: ¡eso es lo que hacen los Objetos de Transferencia de Datos (DTO)!

En cierto sentido, las DTO son como una preocupación transversal, porque están presentes en todas las capas: las DTO no son objetos de negocios u objetos de dominio, ya que su única responsabilidad es transferir el estado de los objetos de dominio a resto de las capas.

Con respecto a sus dudas sobre la clase Order y la clase OrderItem, debe darse cuenta de cómo funcionan los objetos compuestos: cualquier instancia dada de la clase OrderItem no tiene ninguna razón para existir fuera de una instancia de la clase Order, que es una clase compuesta, y de la misma manera, cualquier instancia dada de la clase Order no podría existir sin una propiedad de colección de OrderItems, así que, en realidad, no hay espacio para la confusión: solo existen como clases separadas solo en el código fuente, pero tienen sin significado real como clases separadas en tiempo de ejecución.

Espero que esta pequeña introducción sea lo suficientemente útil para responder tus preguntas y dudas.

Saludos cordiales, GEN

    
respondido por el GEN 27.06.2017 - 21:51

Lea otras preguntas en las etiquetas