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.