Estou com problemas para encontrar uma solução adequada para o seguinte problema de arquitetura.
Em nossa configuração (esboçada abaixo) , temos 2 fontes de dados, em que a fonte de dados A é a fonte primária de itens do tipo Foo. Existe uma fonte de dados secundária que pode ser usada para recuperar informações adicionais em um Foo; no entanto, essas informações nem sempre existem.
Além disso, a fonte de dados A pode ser usada para recuperar itens do tipo Bar. No entanto, cada barra refere-se a um Foo. A dificuldade aqui é que cada Bar deve se referir a um Foo que, se disponível, também contém as informações aumentadas pela fonte de dados B.
Minha pergunta é: como remover o acoplamento rígido entre SubsystemA.1 e DataSourceB?
architecture
fstuijt
fonte
fonte
DataSourceA
eDataSourceB
já estão dissociados?DataSourceA
tem uma dependência de ambosSubSystemA.1
eSubSystemA.2
, mas não deDataSourceB
.SubsystemA.1
para usar algo diferenteDataSourceB
,DataSourceA
não saberia.DataSourceA
só se importa queSubsystemA.1
tem umgetFoo(id)
método. Há uma abstração entreDataSourceA
eDataSourceB
.Respostas:
Criei um aplicativo com a mesma arquitetura de dados por trás dele; temos um banco de dados SQL no local que contém a maioria das informações internas do dia-a-dia da automação e, em seguida, um serviço de nuvem de terceiros usado para vendas, gerenciamento de contas, equipe de campo, etc. e equipamento, e o obtive de duas aplicações diferentes até eu entrar.
O longo e o curto é que uma fonte de dados precisa ter uma referência aos registros da outra. No nosso caso, os dados na nuvem de terceiros contêm referências aos dados no local, porque esse é o arranjo sobre o qual tivemos mais controle. Agora, com um ID para um registro de qualquer uma das fontes de dados, podemos obter dados de ambas; com um ID da nuvem, extraímos o registro da nuvem, obtemos o ID no local e extraímos os dados no local. Com um ID no local, pesquisamos as duas fontes de dados com base nesse ID.
No meu sistema, não tornei nenhum objeto filho do outro na camada de domínio; qualquer uso dos dados de ambos os armazenamentos deve manter duas instâncias de objeto. Nenhum deles é garantido que existe, e é por isso que eu fiz dessa maneira; o aplicativo pode funcionar apenas com dados em nuvem, ou com dados no local, ou ambos, com mais limitações quanto menos dados tiver.
No entanto, isso não é difícil de mudar, especialmente se você tiver certeza de que um lado sempre existirá; basta incluir uma propriedade no objeto que representa o lado para o qual os dados sempre existirão, ou seja, do tipo de objeto que representa o registro do outro repositório de dados. É possível uma "fusão" mais avançada dos dois gráficos em um.
Esse tipo de arranjo deve necessariamente ser associado em algum nível. Você pode ter um DAL que possa interagir com os dois armazenamentos de dados ou segmentar os DALs, um por armazenamento de dados, e ter uma camada superior, como um Controlador, obter os dados de cada um e juntá-los. Mas, em algum nível, seu programa precisa ter inteligência para reunir os dados dessas duas fontes de dados diferentes.
Você pode reduzir o acoplamento necessário na maioria dos casos, abstraindo os detalhes exatamente de onde os dados vêm. Se você obtiver dados de um serviço da Web, que é fornecido como instâncias de classes geradas, coloque um conversor para fazer uma cópia profunda da classe de serviço em algo que você controla, que não precisará ser alterado se os dados origem sim (apenas se o esquema sim).
Agora, isso pode ser um grande empreendimento; a nuvem que usamos possui dezenas de classes de domínio, algumas das quais com centenas de campos de dados e - aqui está o kicker - você pode facilmente fazer grandes alterações no tipo de dados abstratos para acomodar uma mudança para uma nuvem diferente ou outro controle remoto fonte de dados. Por esse motivo, eu não me incomodei; Uso o domínio de serviço da web gerado diretamente e agora que uma mudança da nuvem para um armazenamento de dados externo (mas sob nosso controle) está se aproximando, cujos detalhes ainda não sei, estou simplesmente planejando alterar os formulários e codebehinds do aplicativo, que é onde os dados são "combinados", para refletir o novo esquema e / ou objetos de dados. É um grande trabalho, seja qual for o modo como você o corta.
fonte
Uma maneira de lidar com isso é criar uma fonte de dados agregada que contenha os dados das duas fontes de dados em um único local. Um trabalho seria executado periodicamente para verificar as alterações nas fontes
A
eB
, e escrever os "deltas" em sua fonte de dados agregados. Isso converteria duas fontes de dados fortemente acopladas em uma única fonte de dados coerente.Várias coisas podem impedir você de seguir essa abordagem:
A
eB
duplicar os requisitos de espaço.fonte
DataSourceA
eDataSourceB
já estão dissociados?DataSourceA
tem uma dependência de ambosSubSystemA.1
eSubSystemA.2
, mas não deDataSourceB
.Parece que no nível superior existem dois tipos: Foo e Bar, e você tem apenas duas ações de nível superior:
findFoo(...)
efindBar(...)
. Essa é a interface para a camada de E / S.Sua descrição das fontes de dados implica que existem dois métodos em A:
findFoo
efindBar
e um método em B:findFooAuxiliaryInformation
. EmfindFoo
você precisará mesclar as informações de A e B.Não sei ao que "acoplamento apertado" você está se referindo. Existem três tipos de dados contidos nos dois conjuntos de dados:
Bar
,Foo
, eFooAuxData
. O acoplamento entreFoo
eFooAuxData
é inerente aos dados de entrada e não pode ser reduzido. Mas esse acoplamento deve aparecer apenas nofindFoo
método. Isso é o melhor que você pode fazer. O requisito é implementado em um único local. Se isso mudar, você precisará alterar esse código.fonte
Você não pode.
Se bem entendi,
Foo
eBar
venhodsA
.Bar
s pertencem aFoo
s.De preferência, você não deseja que
Bar
s seja atribuído aFoo
s, a menos queFoo
tenha sido complementado porFoo.enhancedInfo
issodsB
.Sua preferência por atribuir
Bar
s aFoo
s é o que está criando seu acoplamento rígido. Eu qualificaria isso como um "desafio de requisitos", que está forçando você a seguir um caminho específico.Portanto, os desafios técnicos são que
dsB
podem ou não ter informações sobre um dadoFoo
e quedsB
podem nem estar disponíveis.Você precisa decidir o quão difícil e rápido essa preferência
Foo.enhancedInfo
realmente é. Com base nesse requisito, você pode optar por fornecer um objetoFoo
+Bar
ou não. Permitir que um não aprimoradoFoo
seja fornecido apenas complica a lógica e me diz que a preferência não é tão rigorosa quanto pode parecer. Determine quais variantes deFoo
,Foo.enhanced
eBar
seus aplicativos podem oferecer suporte e você terá sua resposta final.Há outras coisas que você pode fazer para aproximar as
Foo
informações relacionadas e que podem resolver alguns desses problemas. Da maneira como sua pergunta é formulada, parece que você está lidando com o problema no nível do objeto de dados e talvez não consiga considerar alterações no tipo de infraestrutura.fonte
Se os dados na fonte de dados B não puderem ser independentes, você provavelmente desejará migrá-los para a fonte de dados A, se possível.
Se eles são independentes, mas relacionados, você deve procurar a virtualização de dados . Isso permitirá que os aplicativos tratem os dados como um conjunto (quando apropriado) de maneira independente. Dependendo da sua plataforma, provavelmente haverá uma estrutura / biblioteca existente que pode ajudá-lo a implementar isso.
fonte