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?
la source
DataSourceA
etDataSourceB
déjà découplé?DataSourceA
a une dépendance à la fois surSubSystemA.1
etSubSystemA.2
, mais pas surDataSourceB
.SubsystemA.1
pour utiliser autre chose queDataSourceB
,DataSourceA
je ne sais pas.DataSourceA
ne se soucie queSubsystemA.1
d'unegetFoo(id)
méthode. Il y a une abstraction entreDataSourceA
etDataSourceB
.Réponses:
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.
la source
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
A
etB
, 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:
A
etB
doit être faite, doublant les exigences d'espace.la source
DataSourceA
etDataSourceB
déjà découplé?DataSourceA
a une dépendance à la fois surSubSystemA.1
etSubSystemA.2
, mais pas surDataSourceB
.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(...)
etfindBar(...)
. 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:
findFoo
etfindBar
et une méthode sur B:findFooAuxiliaryInformation
. DansfindFoo
vous 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
,Foo
etFooAuxData
. Le couplage entreFoo
etFooAuxData
est inhérent aux données d'entrée et ne peut pas être réduit. Mais ce couplage ne devrait apparaître que dans lafindFoo
mé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.la source
Tu ne peux pas.
Si je comprends bien
Foo
et que jeBar
viensdsA
.Bar
s appartiennent àFoo
s.De préférence, vous ne voulez pas que
Bar
s soit affecté àFoo
s, sauf si celaFoo
a été complété parFoo.enhancedInfo
celadsB
.Votre préférence pour attribuer
Bar
s àFoo
s 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
dsB
peuvent ou non avoir des informations sur une donnée donnéeFoo
et quidsB
peuvent même ne pas être disponibles.Vous devez décider à quel point cette préférence
Foo.enhancedInfo
est difficile et rapide . En fonction de cette exigence, vous pouvez décider de fournir un objetFoo
+Bar
ou non. Autoriser la fourniture d'une version non amélioréeFoo
ne 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 deFoo
,Foo.enhanced
etBar
vos 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
Foo
informations 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
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.
la source