Sortes d'objets
Aux fins de notre discussion, séparons nos objets en trois types différents:
Ce sont les objets qui font le travail. Ils transfèrent de l'argent d'un compte courant à un autre, exécutent les commandes et toutes les autres actions que nous attendons des logiciels d'entreprise.
Les objets logiques de domaine ne nécessitent normalement pas d'accesseurs (getters et setters). Au lieu de cela, vous créez l'objet en lui passant des dépendances via un constructeur, puis vous manipulez l'objet à l'aide de méthodes (dites, ne demandez pas).
Les objets de transfert de données sont à l'état pur; ils ne contiennent aucune logique métier. Ils auront toujours des accesseurs. Ils peuvent ou non avoir des setters, selon que vous les écrivez de manière immuable ou non . Vous définirez vos champs dans le constructeur et leurs valeurs ne changeront pas pendant la durée de vie de l'objet, ou vos accesseurs seront en lecture / écriture. En pratique, ces objets sont généralement modifiables, de sorte qu'un utilisateur peut les modifier.
Les objets du modèle de vue contiennent une représentation de données affichable / modifiable. Ils peuvent contenir une logique métier, généralement limitée à la validation des données. Un exemple d'un objet View Model peut être un InvoiceViewModel, contenant un objet Customer, un objet En-tête de facture et des éléments de ligne de facture. Les objets View Model contiennent toujours des accesseurs.
Ainsi, le seul type d'objet qui sera "pur" dans le sens où il ne contient pas d'accesseurs de champ sera l'objet Logique de domaine. La sérialisation d'un tel objet enregistre son "état de calcul" actuel, de sorte qu'il peut être récupéré plus tard pour terminer le traitement. Les modèles de vue et les DTO peuvent être librement sérialisés, mais dans la pratique, leurs données sont normalement enregistrées dans une base de données.
Sérialisation, dépendances et couplage
S'il est vrai que la sérialisation crée des dépendances, dans le sens où vous devez désérialiser vers un objet compatible, il ne s'ensuit pas nécessairement que vous devez changer votre configuration de sérialisation. De bons mécanismes de sérialisation sont d'usage général; ils ne se soucient pas si vous changez le nom d'une propriété ou d'un membre, tant qu'il peut toujours mapper des valeurs aux membres. En pratique, cela signifie uniquement que vous devez re-sérialiser l'instance d'objet pour rendre la représentation de sérialisation (xml, json, peu importe) compatible avec votre nouvel objet; aucune modification de configuration du sérialiseur ne devrait être nécessaire.
Il est vrai que les objets ne doivent pas se préoccuper de la façon dont ils sont sérialisés. Vous avez déjà décrit une manière de dissocier ces préoccupations des classes de domaine: la réflexion. Mais le sérialiseur doit se préoccuper de la façon dont il sérialise et désérialise les objets; c'est, après tout, sa fonction. La façon dont vous gardez vos objets découplés de votre processus de sérialisation est de faire de la sérialisation une fonction polyvalente , capable de fonctionner sur tous les types d'objets.
Une des choses qui rend les gens confus, c'est que le découplage doit se produire dans les deux sens. Ce ne est pas; il ne doit fonctionner que dans une seule direction. En pratique, vous ne pouvez jamais découpler complètement; il y a toujours un couplage. Le but du couplage lâche est de faciliter la maintenance du code, et non de supprimer toutes les dépendances.
Le but sous-jacent de la sérialisation est de garantir que les données produites par un système peuvent être consommées par un ou plusieurs systèmes compatibles.
L'approche la plus simple et la plus robuste de la sérialisation consiste à traduire les données dans un format de type agnostique qui maintient la structure dans un format simple et facile à consommer. Par exemple, les formats de sérialisation les plus répandus (c'est-à-dire JSON, XML) utilisent un format texte bien défini. Le texte est simple à produire, à transmettre et à consommer.
Il y a 2 raisons pour lesquelles l'utilisation de l'un de ces formats peut ne pas être idéale.
Efficacité
Il y a un coût inhérent à la traduction de toutes les données en leurs équivalents textuels. Les types de données n'existeraient pas si le texte était le moyen le plus efficace d'exprimer toutes les différentes formes de données. De plus, la structure de ces formats n'est pas idéale pour récupérer des sous-ensembles de données de manière asynchrone ou partielle.
Par exemple, XML et JSON supposent que les données utilisées seront écrites et lues du début à la fin. Pour le traitement de très grands ensembles de données où la mémoire est rare, le système consommant les données peut nécessiter la capacité de traiter les données en plusieurs parties. Dans ce cas, une implémentation spéciale de sérialisation / désérialisation peut être nécessaire pour gérer les données.
Précision
Le casting requis pour sérialiser / désérialiser les données de leur type prévu en type agnostique de données entraîne une perte de précision.
On pourrait soutenir que produire une représentation binaire des objets et des données est clairement la solution la plus efficace et la plus précise. L'inconvénient majeur est que la mise en œuvre de tous les systèmes qui consomment et produisent des données doivent rester compatibles. C'est une simple contrainte en théorie mais c'est un cauchemar à maintenir dans la pratique car les systèmes de production ont tendance à changer / évoluer avec le temps.
Ceci étant dit. Le découplage de la sérialisation / désérialisation des détails spécifiques au domaine a du sens en règle générale, car les formats à usage général sont plus robustes, mieux pris en charge sur divers systèmes et nécessitent peu ou pas de surcharge de maintenance accrue à utiliser.
la source