En el proyecto en el que estoy trabajando, enviamos mensajes sobre widgets a través de colas de mensajes, serializándolos en las colas como XML. El esquema XML contiene etiquetas para propiedades que son comunes a todos los tipos de estos mensajes de widget, como el tipo de widget, el nombre del comando y el destino. También puede contener una lista de pares de valores clave de tamaño arbitrario para permitir el almacenamiento de propiedades que solo son relevantes para un tipo específico de mensaje de widget. La WidgetMessage
clase encapsula estos datos y las clases WidgetMessageXmlWriter
y WidgetMessageXmlReader
proporcionan serialización hacia y desde el XML.
He realizado algunas clases que encapsulan mensajes específicos, por ejemplo, un FooPlaySoundMessage
widget 'Foo' o un widget BarSetLightPatternMessage
'Bar'. Cada uno tiene un ToWidgetMessage
método de instancia y un FromWidgetMessage
método estático para convertir ay desde la WidgetMessage
clase. Cada familia de mensajes hereda de una clase abstracta para ese tipo de widget, por ejemplo , FooMessage
y BarMessage
, que a su vez hereda de la WidgetMessageMapping
clase; Esto almacena las propiedades comunes de los mensajes y los métodos protegidos utilizados por las subclases para la conversión. Ninguna de estas clases hereda WidgetMessage
ya que no quiero que hereden su propiedad de colección de valores clave y los métodos asociados , de ahí la necesidad de conversión en lugar de simple conversión.
Me gusta la simplicidad de mi API (por ejemplo FooPlaySoundMessage msg = FooPlaySoundMessage.fromWidgetMessage(widgetMessage)
), pero el hecho de que tenga que usar métodos protegidos en una clase base para compartir funcionalidad y métodos estáticos para exponerla, me hace preguntarme si debería haber una o dos clases separadas involucradas aquí (similar a WidgetMessageXmlWriter
y WidgetMessageXmlReader
). Por otro lado, pensé que parte del objetivo de OOP es agrupar datos y métodos juntos y así evitar "objetos de datos tontos" .
Entonces, ¿tengo la idea correcta al agregar métodos de conversión a mis objetos de datos, o esa funcionalidad debería extraerse en otra clase?
Actualizar:
Creo que en todos los detalles anteriores de mi intento actual de diseño no expliqué con suficiente claridad el problema que estoy tratando de resolver.
En resumen, tengo una clase DTO "genérica" que tiene algunas propiedades fuertemente tipadas y una colección de pares clave-valor para almacenar otros datos personalizados. Quiero tener algunas clases de DTO especializadas para cada conjunto de datos personalizados que almacenen todos los mismos datos que el DTO genérico, excepto con los pares clave-valor reemplazados por propiedades fuertemente tipadas. ¿Cuál es el mejor diseño para convertir entre estos dos tipos de DTO?
fuente
Respuestas:
Si FooPlaySoundMessage sabe cómo reproducir sonido y también cómo mapearse a sí mismo en un formato de cola de mensajes, podría decir que la clase tiene más de una responsabilidad. Si delega directamente el sonido real que se reproduce en una clase diferente, su FooPlaySoundMessage es básicamente un objeto de transferencia de datos. Poner asignaciones comunes en una clase base compartida me parece bien en ese caso.
Sin embargo, probablemente lo separaría. Los objetos de transferencia de datos generalmente tienen poco o ningún código, puede ver FooPlaySoundMessage como uno.
En algún momento, es posible que tenga que transmitir los mismos datos por algún otro medio u otro formato (¿quizás Json?). Podrías YAGNI por ahora y separarlo entonces.
Probablemente haría una clase de controlador de mensajes que analice las partes comunes, detecte el tipo de mensaje y luego delegue a un analizador específico, por ejemplo, FooPlaySoundXmlMessageParser. En caso de duda, favorezca la composición sobre la herencia.
fuente