Comment réduire le couplage étroit entre deux sources de données

10

J'ai du mal à trouver une solution appropriée au problème d'architecture suivant.

Dans notre cadre (esquissé ci-dessous), nous avons 2 sources de données, où la source de données A est la source principale pour les éléments de type Foo. Il existe une source de données secondaire qui peut être utilisée pour récupérer des informations supplémentaires sur un Foo; cependant, ces informations n'existent pas toujours.

De plus, la source de données A peut être utilisée pour récupérer des éléments de type Bar. Cependant, chaque barre fait référence à un Foo. La difficulté ici est que chaque barre doit faire référence à un Foo qui, s'il est disponible, contient également les informations augmentées par la source de données B.

Ma question est: comment supprimer le couplage étroit entre SubsystemA.1 et DataSourceB?

http://i.stack.imgur.com/Xi4aA.png

fstuijt
la source
10
Voilà un beau croquis. Quel programme avez-vous utilisé pour le dessiner?
Marcelo MD
Je veux aussi savoir quel programme avez-vous utilisé pour le dessiner. S'il vous plaît.
Tulains Córdova
2
yuml.me est le site qu'il a plus que probablement utilisé pour créer le diagramme.
Jason Turner
1
N'est-ce pas DataSourceAet DataSourceBdéjà découplé? DataSourceAa une dépendance à la fois sur SubSystemA.1et SubSystemA.2, mais pas sur DataSourceB.
Tulains Córdova
1
@fstuijt Non, ce n'est pas le cas. Si vous modifiez SubsystemA.1pour utiliser autre chose que DataSourceB, DataSourceAje ne sais pas. DataSourceAne se soucie que SubsystemA.1d'une getFoo(id)méthode. Il y a une abstraction entre DataSourceAet DataSourceB.
Tulains Córdova

Réponses:

3

J'ai créé une application avec à peu près la même architecture de données; nous avons une base de données SQL sur site contenant la plupart des informations quotidiennes d'automatisation et internes, puis un service cloud tiers utilisé pour les ventes, la gestion des comptes, le personnel sur le terrain, etc. et de l'équipement, et je l'avais obtenu de deux applications différentes jusqu'à ce que j'intervienne.

Le long et le court est qu'une source de données doit avoir une référence aux enregistrements de l'autre. Dans notre cas, les données cloud tierces contiennent des références aux données sur site car c'est l'arrangement sur lequel nous avions le plus de contrôle. Maintenant, avec un ID pour un enregistrement de l'une ou l'autre source de données, nous pouvons obtenir des données des deux; avec un identifiant cloud, nous extrayons l'enregistrement du cloud, obtenons l'ID sur site et récupérons les données sur site. Avec un ID sur site, nous interrogeons les deux sources de données en fonction de cet ID.

Dans mon système, je n'ai pas fait de l'un des objets un enfant de l'autre dans la couche domaine; toute utilisation des données des deux magasins doit conserver deux instances d'objet. Aucun des deux n'est garanti d'exister, c'est pourquoi je l'ai fait de cette façon; l'application ne peut fonctionner qu'avec des données cloud, ou avec des données sur site, ou les deux, avec plus de limitations, moins elle dispose de données.

Cependant, ce n'est pas difficile à changer, surtout si vous êtes sûr qu'un côté existera toujours; il suffit d'inclure une propriété dans l'objet représentant le côté pour lequel les données existeront toujours, c'est-à-dire du type d'objet représentant l'enregistrement de l'autre magasin de données. Une "fusion" plus avancée des deux graphiques en un seul est possible.

Ce type d'arrangement doit nécessairement être couplé à un certain niveau. Vous pouvez avoir un DAL qui peut s'interfacer avec les deux magasins de données, ou vous pouvez segmenter les DAL, un par magasin de données, et avoir une couche supérieure telle qu'un contrôleur obtenir les données de chacun et les attacher ensemble. Mais, à un certain niveau, votre programme doit avoir l'intelligence de rassembler les données de ces deux sources de données disparates.

Vous pouvez réduire le couplage requis dans la plupart des cas en faisant abstraction des détails sur la provenance exacte des données. Si vous obtenez des données d'un service Web, qui vous sont fournies en tant qu'instances de classes générées, mettez un convertisseur en place pour créer une copie complète de la classe de service dans quelque chose que vous contrôlez, qui n'aura pas à changer si les données la source le fait (uniquement si le schéma le fait).

Maintenant, cela peut être une entreprise énorme; le cloud que nous utilisons a des dizaines de classes de domaine, dont certaines ont des centaines de champs de données, et - voici le kicker - vous pourriez très facilement devoir apporter de grandes modifications au type de données abstrait pour s'adapter à un déplacement vers un autre cloud ou une autre télécommande la source de données. Pour cette raison, je n'ai pas pris la peine; J'utilise directement le domaine de service Web généré, et maintenant qu'un changement du cloud vers un magasin de données hors site (mais sous notre contrôle) se profile, dont je ne sais toujours pas les détails, je prévois simplement de changer les formulaires et codebehinds de l'application, qui est l'endroit où les données sont «combinées», pour refléter le nouveau schéma et / ou les objets de données. C'est un gros travail, quelle que soit la façon dont vous le découpez.

KeithS
la source
Cette réponse couvre le mieux le problème que j'ai rencontré et, à mon avis, offre également la meilleure réponse jusqu'à présent. Cependant, je pense que la combinaison de données provenant de plusieurs sources est un problème courant. Des modèles de conception qui pourraient vous aider?
fstuijt
1
Certaines variations sur un modèle d'usine pourraient être utiles. Si vous avez une CloudInvoice et un objet SqlInvoice (à partir de leurs sources de données respectives) et que vous souhaitez créer une seule facture unifiée, créez une fabrique qui en sait suffisamment sur les deux sources de données pour récupérer chaque moitié de l'enregistrement qu'elle est sur le point de créer, puis fusionne les informations dans votre classe de domaine.
KeithS
4

Pour résoudre ce problème, vous pouvez créer une source de données agrégée contenant les données des deux sources de données en un seul endroit. Un travail serait exécuté périodiquement pour vérifier les changements dans les sources Aet B, et écrire les «deltas» dans votre source de données agrégées. Cela convertirait deux sources de données étroitement couplées en une seule source de données cohérente.

Plusieurs choses pourraient vous empêcher d'adopter cette approche:

  • La quantité de données peut être prohibitive - Une copie complète de Aet Bdoit être faite, doublant les exigences d'espace.
  • Les données doivent être en direct - Il y aura des périodes entre le moment où les données dans la source ont changé et le travail d'agrégation les a propagées dans la source agrégée.
  • Vous devez réconcilier les données avec les sources d'origine - La tâche de replacer les modifications dans leurs emplacements d'origine devient beaucoup plus complexe si vous adoptez cette approche.
dasblinkenlight
la source
Je suis d'accord, l'introduction d'une couche d'abstraction est l'approche préférée
neontapir
2
Vous pouvez avoir une couche d'abstraction sans copier les données.
smp7d
@ smp7d Cela cacherait le couplage derrière une belle extrémité avant; J'ai supposé que vous faisiez déjà quelque chose comme ça dans votre système, car sinon la complexité serait répartie sur l'ensemble de votre conception.
dasblinkenlight
Selon l'environnement de base de données, cela peut également être géré avec une ou plusieurs vues, ce qui élimine le besoin de copier des données.
Walter
N'est-ce pas DataSourceAet DataSourceBdéjà découplé? DataSourceAa une dépendance à la fois sur SubSystemA.1et SubSystemA.2, mais pas sur DataSourceB.
Tulains Córdova
1

Il semble qu'au niveau supérieur, il existe deux types: Foo et Bar, et vous n'avez que deux actions de niveau supérieur: findFoo(...)et findBar(...). C'est l'interface avec la couche d'E / S.

Votre description des sources de données implique qu'il existe deux méthodes sur A: findFooet findBaret une méthode sur B: findFooAuxiliaryInformation. Dans findFoovous devrez fusionner les informations de A et B.

Je ne sais pas de quel "couplage étroit" vous parlez. Il existe trois types de données contenues dans les deux ensembles de données: Bar, Fooet FooAuxData. Le couplage entre Fooet FooAuxDataest inhérent aux données d'entrée et ne peut pas être réduit. Mais ce couplage ne devrait apparaître que dans la findFoométhode. C'est le mieux que vous puissiez faire. L'exigence est mise en œuvre en un seul endroit. S'il change, vous devez changer ce code.

Kevin Cline
la source
0

Tu ne peux pas.

Si je comprends bien Fooet que je Barviens dsA. Bars appartiennent à Foos.
De préférence, vous ne voulez pas que Bars soit affecté à Foos, sauf si cela Fooa été complété par Foo.enhancedInfocela dsB.

Votre préférence pour attribuer Bars à Foos est ce qui crée votre couplage serré. Je qualifierais cela de «défi des exigences» qui vous oblige à emprunter un chemin particulier.

Ainsi, les défis techniques sont ceux qui dsBpeuvent ou non avoir des informations sur une donnée donnée Fooet qui dsBpeuvent même ne pas être disponibles.

Vous devez décider à quel point cette préférence Foo.enhancedInfoest difficile et rapide . En fonction de cette exigence, vous pouvez décider de fournir un objet Foo+ Barou non. Autoriser la fourniture d'une version non améliorée Foone fait que compliquer la logique et me dit que la préférence n'est pas aussi stricte qu'elle puisse paraître. Déterminez quelles variantes de Foo, Foo.enhancedet Barvos applications peuvent prendre en charge et vous aurez votre réponse ultime.

Il y a d'autres choses que vous pourriez faire pour rapprocher les Fooinformations associées, et cela pourrait résoudre certains de ces problèmes. De la façon dont votre question est formulée, il semble que vous traitez le problème au niveau de l'objet de données et vous ne pourrez peut-être pas envisager des changements de type d'infrastructure.


la source
L'inverse: les Foo appartiennent à Bar s
fstuijt
@fstuijt Je mettrai à jour ma réponse dans un instant. Fondamentalement, il restera le même. Vous devez décider de la manière dont vous souhaitez mettre en serveur Bar + Foo.
0

Si les données de la source de données B ne peuvent pas se suffire à elles-mêmes, vous souhaiterez probablement les migrer vers la source de données A si possible.

S'ils sont indépendants mais liés, vous devez vous pencher sur la virtualisation des données . Cela permettra aux applications de traiter les données comme un ensemble (le cas échéant) de manière agnostique. En fonction de votre plateforme, il y aura probablement un framework / bibliothèque existant qui pourra vous aider à l'implémenter.

smp7d
la source