Tipos de objetos
Para os propósitos de nossa discussão, vamos separar nossos objetos em três tipos diferentes:
Esses são os objetos que realizam o trabalho. Eles transferem dinheiro de uma conta corrente para outra, cumprem pedidos e todas as outras ações que esperamos que o software comercial execute.
Objetos lógicos de domínio normalmente não precisam de acessadores (getters e setters). Em vez disso, você cria o objeto entregando dependências a ele por meio de um construtor e, em seguida, manipula o objeto por meio de métodos (diga, não pergunte).
Objetos de transferência de dados são estado puro; eles não contêm nenhuma lógica comercial. Eles sempre terão acessadores. Eles podem ter ou não setters, dependendo de você estar ou não gravá-los de maneira imutável . Você definirá seus campos no construtor e seus valores não serão alterados durante a vida útil do objeto, ou seus acessadores serão de leitura / gravação. Na prática, esses objetos geralmente são mutáveis, para que um usuário possa editá-los.
Os objetos View Model contêm uma representação de dados exibível / editável. Eles podem conter lógica de negócios, geralmente confinada à validação de dados. Um exemplo de um objeto View Model pode ser um InvoiceViewModel, contendo um objeto Customer, um objeto Header Invoice e itens de linha da fatura. Os objetos View Model sempre contêm acessadores.
Portanto, o único tipo de objeto que será "puro" no sentido de que não contém acessadores de campo será o objeto de lógica de domínio. A serialização de um objeto salva seu "estado computacional" atual, para que possa ser recuperado posteriormente para concluir o processamento. Os modelos de exibição e DTOs podem ser serializados livremente, mas, na prática, seus dados são normalmente salvos em um banco de dados.
Serialização, dependências e acoplamento
Embora seja verdade que a serialização crie dependências, no sentido de que você precisa desserializar para um objeto compatível, isso não significa necessariamente que você precise alterar sua configuração de serialização. Bons mecanismos de serialização são de uso geral; eles não se importam se você altera o nome de uma propriedade ou membro, desde que ele ainda possa mapear valores para os membros. Na prática, isso significa apenas que você deve serializar novamente a instância do objeto para tornar a representação de serialização (xml, json, qualquer que seja) compatível com seu novo objeto; nenhuma alteração na configuração do serializador deve ser necessária.
É verdade que os objetos não devem se preocupar com a maneira como são serializados. Você já descreveu uma maneira de dissociar essas preocupações das classes de domínio: reflexão. Mas o serializador deve se preocupar em como serializar e desserializar objetos; afinal, essa é a sua função. A maneira como você mantém seus objetos separados do processo de serialização é tornar a serialização uma função de uso geral , capaz de funcionar em todos os tipos de objetos.
Uma das coisas sobre as quais as pessoas ficam confusas é que a dissociação deve ocorrer nas duas direções. Isso não; só tem que trabalhar em uma direção. Na prática, você nunca pode se separar completamente; sempre há algum acoplamento. O objetivo do acoplamento flexível é facilitar a manutenção do código, não remover todas as dependências.
O objetivo subjacente da serialização é garantir que os dados produzidos por um sistema possam ser consumidos por um ou mais sistemas compatíveis.
A abordagem mais fácil e robusta à serialização é converter os dados em um formato independente de tipo que mantém a estrutura em um formato simples e fácil de consumir. Por exemplo, os formatos de serialização mais onipresentes (ie JSON, XML) usam um formato baseado em texto bem definido. O texto é simples de produzir, transmitir e consumir.
Existem 2 razões pelas quais o uso de um desses formatos pode não ser o ideal.
Eficiência
Há um custo inerente envolvido na conversão de todos os dados em seus equivalentes baseados em texto. Os tipos de dados não existiriam se o texto fosse a maneira mais eficiente de expressar todas as diferentes formas de dados. Além disso, a estrutura desses formatos não é ideal para recuperar subconjuntos de dados de forma assíncrona ou em partes.
Por exemplo, XML e JSON assumem que os dados usados serão gravados e lidos do início ao fim. Para processar conjuntos de dados muito grandes em que a memória é escassa, o sistema que consome os dados pode exigir a capacidade de processar os dados em partes. Nesse caso, uma implementação de serialização / desserialização de finalidade especial pode ser necessária para manipular os dados.
Precisão
A conversão necessária para serializar / desserializar os dados do tipo pretendido para o tipo agnóstico dos dados resulta em perda de precisão.
Alguém poderia argumentar que produzir uma representação binária dos objetos e dados é claramente a solução mais eficiente e precisa. A principal desvantagem é que a implementação de todos os sistemas que consomem e produzem dados precisa permanecer compatível. É uma restrição simples na teoria, mas é um pesadelo para manter na prática, pois os sistemas de produção tendem a mudar / evoluir ao longo do tempo.
Com isso dito. A dissociação da serialização / desserialização dos detalhes específicos do domínio faz sentido como regra geral, porque os formatos de uso geral são mais robustos, têm melhor suporte em diversos sistemas e exigem pouca sobrecarga de manutenção para usar.
fonte