Tengo base dos clases, Operation
y Trigger
. Cada uno tiene una serie de subclases que se especializan en ciertos tipos de operaciones o disparadores. A Trigger
puede desencadenar un específico Operation
. Mientras que un Operation
puede ser activado por un específico Trigger
.
Necesito escribir el código que asigna un dado Operation
a un dado Trigger
(o viceversa), pero no estoy seguro de dónde ponerlo.
En este caso, el código no pertenece claramente a una clase u otra clase. Entonces, en términos de un principio de responsabilidad única, no estoy seguro de dónde debe pertenecer el código.
Puedo ver tres opciones que funcionarían. Mientras que 1 y 2 parecen ser solo una elección de semántica, 3 representa un enfoque completamente diferente.
- En el gatillo, por ejemplo
bool Triggers(Operation o)
. - En la operación, por ejemplo
bool TriggeredBy(Trigger t)
. - En una clase completamente nueva que gestiona la asignación, por ejemplo
bool MappingExists(Trigger t, Operation o)
.
¿Cómo debo decidir dónde colocar el código de mapeo compartido con respecto a un principio de responsabilidad única?
¿Cómo gestionar la responsabilidad individual cuando la responsabilidad se comparte?
Editar 1.
Entonces el código real se ve así. Todas las propiedades, son o bien un string
, Guid
, collection<string>
, o enum
. Básicamente, solo representan pequeños datos.
Editar 2.
La razón del tipo de retorno de bool. Otra clase va a consumir una colección de Trigger
y una colección de Operation
. Necesita saber dónde existe un mapeo entre a Trigger
y an Operation
. Utilizará esa información para crear un informe.
fuente
Respuestas:
Lo pensaría de esta manera: cómo se determina qué Operación causa qué Trigger se dispara. Tiene que ser un algoritmo que pueda cambiar con el tiempo o evolucionar en múltiples algoritmos. Ponerlo en las clases Trigger u Operation implica que esas clases podrán manejar tales escenarios en el futuro. Tenga en cuenta que no lo veo tan simple como una asignación, ya que puede haber más.
Mi elección sería crear una clase con los métodos adecuados, como GetOperationForTrigger (Trigger t). Esto permite que el código evolucione en un conjunto de tales clases cuya elección puede depender en tiempo de ejecución u otras variables (por ejemplo, patrón de estrategia).
Tenga en cuenta que la suposición principal en esta línea de pensamiento es escribir un código mínimo (es decir, tres clases hoy) pero evitar una refactorización importante si la funcionalidad necesita ser extendida en el futuro al no suponer que siempre habrá exactamente una forma de determinar qué disparador causa qué operación.
Espero que esto ayude. Aunque la respuesta es similar a la del usuario 61852, el razonamiento es diferente. Como resultado, la implementación será diferente (es decir, tener métodos explícitos en lugar de anular iguales, por lo que la cantidad de métodos puede evolucionar con el tiempo según las necesidades).
fuente
He estado allí, hecho eso.
Opción # 3.
No sé qué idioma utilizará, pero utilizaré un pseudocódigo que es muy similar a Java. Si su lenguaje es C #, probablemente tenga interfaces y estructuras similares.
Tener una clase o interfaz de mapeo:
equals()
métodoMapping
para queMapping
se puedan consultar las colecciones de si contienen una asignación determinada.equals()
métodos adecuados .Comparable
, para que pueda ordenar los informes.Ellos simplemente pueden poner un mapeo en una colección
Más tarde puedes preguntar:
fuente
Actualmente tiene la clase A que sabe acerca de la clase B y la clase B que sabe acerca de la clase A. Eso es mucho acoplamiento.
Por definición, A está haciendo al menos su propia operación Y comprobando si B debe ejecutarse. Lo contrario es cierto con B. Cualquiera que sea la clase llamada primero, debería poder ver el resultado y ver si es necesario ejecutar más cosas.
Intenta romper ese acoplamiento dividiendo tus clases en componentes más pequeños. Me gusta poner un comentario en la parte superior de cada clase explicando en inglés lo que hace. Si necesita usar palabras como AND o va sobre una o dos oraciones, entonces debe considerar desglosarlas. Como regla general, cualquier cosa después de un "y" debe estar en su propia clase
Vea también si puede definir una interfaz que cubra la funcionalidad de Trigger and Operation. Si no puede, eso es otra indicación de que su clase se está volviendo demasiado grande. También romperá el acoplamiento entre tus clases.
fuente
Trigger
estaría acoplado a aOperation
. Pero así es como se ven los datos del mundo real. Están acoplados, porque hay un mapeo, por ejemplo, tienen que saber unos de otros para tener significado.