Qual projeto de API para armazenar dados genéricos em um formato mais específico?

8

for No projeto em que estou trabalhando, enviamos mensagens sobre widgets através de filas de mensagens, serializando-os nas filas como XML. O esquema XML contém tags para propriedades comuns a todos os tipos dessas mensagens de widget, como tipo de widget, nome do comando e destino. Também pode conter uma lista de pares de valores-chave de tamanho arbitrário para permitir o armazenamento de propriedades que são relevantes apenas para um tipo específico de mensagem do widget. A WidgetMessageclasse encapsula esses dados e as classes WidgetMessageXmlWritere WidgetMessageXmlReaderfornecem serialização de e para o XML.

Eu criei algumas classes que encapsulam mensagens específicas, por exemplo, FooPlaySoundMessagepara um widget 'Foo' ou BarSetLightPatternMessagepara um widget 'Bar'. Cada um deles tem um ToWidgetMessagemétodo de instância e um FromWidgetMessagemétodo estático para converter de e para a WidgetMessageclasse. Cada família de mensagens herda de uma classe abstrata para esse tipo de widget, por exemplo , FooMessagee BarMessage, que por sua vez herda da WidgetMessageMappingclasse; isso armazena as propriedades comuns da mensagem e os métodos protegidos usados ​​pelas subclasses para conversão. Nenhuma dessas classes é herdada WidgetMessagedesde que eu não quero que elas herdem sua propriedade de coleção de valor-chave e métodos associados , daí a necessidade de conversão em vez de simples conversão.

Eu gosto da simplicidade da minha API (por exemplo FooPlaySoundMessage msg = FooPlaySoundMessage.fromWidgetMessage(widgetMessage)), mas o fato de eu estar precisando usar métodos protegidos em uma classe base para compartilhar funcionalidades e métodos estáticos para expô-las me faz pensar se deveria haver uma ou duas classes separadas envolvidas aqui (semelhante a WidgetMessageXmlWritere WidgetMessageXmlReader). Por outro lado, pensei que parte do objetivo do POO é agrupar dados e métodos e assim evitar "objetos de dados burros" .

Então, eu tenho a idéia certa adicionando métodos de conversão aos meus objetos de dados ou essa funcionalidade deve ser extraída para outra classe?

Atualizar:

Penso que em todos os detalhes acima da minha tentativa atual de design não expliquei com clareza suficiente o problema que estou tentando resolver.

Em resumo, eu tenho uma classe DTO "genérica" ​​que possui algumas propriedades fortemente tipadas e uma coleção de pares de valores-chave para armazenar outros dados personalizados. Desejo ter algumas classes DTO especializadas para cada conjunto de dados personalizados que armazenam todos os mesmos dados que o DTO genérico, exceto com os pares de valores-chave substituídos por propriedades fortemente tipadas. Qual é o melhor design para converter entre esses dois tipos de DTO?

Robert Johnson
fonte
Soa como padrão Decorator? - en.wikipedia.org/wiki/Decorator_pattern
Stevo 27/02
Segundo isso. Eu acho que você está bem.
Stu
1
Além disso, como um aleatória de lado: se ele funciona para você, é no.
Stu
O que a mensagem faz em vez de apenas ser a mensagem?
Piotr Gwiazda
A responsabilidade exclusiva dessas classes é ser convertida para e da classe WidgetMessage. Existe um projeto 'Widget Comms' que consome WidgetMessages e conversa com os widgets; Não adicionei essa funcionalidade de comunicação a essas classes WidgetMessageMapping porque apenas o projeto Widget Comms deve saber falar com os widgets, enquanto as mensagens podem ser criadas em várias partes diferentes do aplicativo. Os WidgetMessageMappings estão lá simplesmente para evitar que o código de análise e criação de mensagens seja espalhado pelas camadas do aplicativo.
21813 Robert Johnson

Respostas:

1

Se o FooPlaySoundMessage souber tocar som e também como se mapear para um formato de fila de mensagens, você poderá dizer que a classe tem mais de uma responsabilidade. Se delegar diretamente o som real que está sendo reproduzido em uma classe diferente, o FooPlaySoundMessage será basicamente um objeto de transferência de dados. Colocar mapeamentos comuns em uma classe base compartilhada me parece bom nesse caso.

Eu provavelmente separaria isso embora. Os objetos de transferência de dados geralmente têm pouco ou nenhum código; você pode ver o FooPlaySoundMessage como um.

Em algum momento, talvez você precise transmitir os mesmos dados por outros meios ou por outro formato (json, talvez?). Você poderia YAGNI por agora e separá-lo então.

Eu provavelmente criaria uma classe de manipulador de mensagens que analisa as partes comuns, detecta o tipo de mensagem e, em seguida, delega para um analisador específico, por exemplo, FooPlaySoundXmlMessageParser. Em caso de dúvida, favorecer a composição sobre a herança.

Joppe
fonte
É apenas o WidgetMessage que é convertido para e de XML - os DTOs especializados serão convertidos apenas para e de WidgetMessages. No meu design atual, eles ainda são chamados de 'mensagens', mesmo que apenas o WidgetMessage seja colocado em uma fila, para que eu possa entender sua confusão. Atualizei minha pergunta para explicar melhor o problema que estou tentando resolver.
Robert Johnson