如何减少两个数据源之间的紧密耦合


10

我在寻找以下架构问题的适当解决方案时遇到了一些麻烦。

我们的设置(如下所示)中,我们有2个数据源,其中数据源A是Foo类型项目的主要来源。存在辅助数据源,可用于检索Foo上的其他信息。但是,此信息并不总是存在。

此外,数据源A可用于检索Bar类型的项目。但是,每个Bar都指一个Foo。这里的困难在于每个Bar应该引用一个Foo,如果有的话,它还包含由数据源B扩充的信息。

我的问题是:如何消除SubsystemA.1与DataSourceB之间的紧密耦合?

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


10
那是一个美丽的草图。您使用什么程序来绘制它?
Marcelo MD

我也想知道您使用什么程序来绘制它。请。
图兰斯·科尔多瓦

2
yuml.me是他使用过多的网站来创建图表的机会。
杰森·特纳

1
DataSourceADataSourceB已经脱钩?DataSourceASubSystemA.1和都有依赖SubSystemA.2,但对DataSourceB
图兰斯·科尔多瓦

1
@fstuijt不,不是。如果您修改SubsystemA.1为使用以外的其他内容DataSourceB,则DataSourceA不会知道。DataSourceA只在乎SubsystemA.1getFoo(id)办法。DataSourceA和之间有一个抽象DataSourceB
图兰斯·科尔多瓦

Answers:


3

我创建了一个具有几乎相同的数据架构的应用程序。我们有一个现场SQL数据库,其中包含大多数自动化和内部日常信息,然后还有一个用于销售,客户管理,现场人员等的第三方云服务。帮助台需要这两个有关客户实际位置的信息和设备,并且一直是从两个不同的应用程序获得的,直到我介入。

总而言之,一个数据源需要引用另一个数据源的记录。在我们的案例中,第三方云数据包含对现场数据的引用,因为这是我们最能控制的安排。现在,有了来自任何一个数据源的记录的ID,我们就可以从两个数据源中获取数据。使用云ID,我们从云中提取记录,获取现场ID,然后提取现场数据。使用现场ID,我们根据该ID轮询两个数据源。

在我的系统中,我没有在域层中使任何一个对象成为另一个对象的子对象。来自两个存储的数据的任何使用都必须维护两个对象实例。没有人保证存在,这就是为什么我这样做了。该应用程序只能使用云数据或现场数据,或同时使用这两种数据,但限制越多,其数据越少。

但是,这并不难改变,尤其是在您确定一侧将始终存在的情况下。只需在对象中包含一个属性,该属性表示将始终存在数据的那一侧,即对象类型的属性表示另一个数据存储的记录。可以将两个图形更高级地“合并”为一个。

这种安排必须在某种程度上耦合。您可以拥有一个既可以与两个数据存储接口的DAL,也可以对每个数据存储的DAL进行分段,并具有更高的层,例如Controller从每个数据存储中获取数据并将它们对齐。但是,在某种程度上,您的程序必须具有将这两个不同数据源的数据放在一起的技巧。

您可以通过抽象出数据确切来源的详细信息来减少大多数情况下所需的耦合。如果您从Web服务获取数据(将其作为生成的类的实例提供给您),则放置一个转换器以将服务类的深层副本复制到您控制的内容中,如果数据源(仅在架构存在的情况下)。

现在,这可能是一项艰巨的任务。我们使用的云具有数十个域类,其中一些具有数百个数据字段,而且,这很重要,您可以非常轻松地对抽象数据类型进行大的更改,以适应迁移到其他云或其他远程站点数据源。因此,我没有打扰。我直接使用生成的Web服务域,现在从云到异地(但在我们的控制之下)数据存储的变化迫在眉睫,我仍然不知道其详细信息,我只是打算更改表单和应用程序的代码隐藏(在此处数据被“组合”),以反映新的架构和/或数据对象。无论您采用哪种方式切片,这都是一项艰巨的工作。


该答案最能涵盖我遇到的问题,并且我认为到目前为止也提供了最佳答案。但是,我认为合并来自多个来源的数据是一个普遍的问题。任何设计模式可能会有所帮助?
fstuijt 2012年

1
在Factory模式上进行一些更改可能会很有用。如果您有一个CloudInvoice和SqlInvoice对象(来自它们各自的数据源),并且想要创建一个统一的发票,请创建一个对这两个数据源都足够了解的Factory,以检索将要创建的记录的每一半,然后将信息合并到您的域类中。
KeithS 2012年

4

解决此问题的一种方法是制作一个聚合数据源,该数据源将一个位置的两个数据源中的数据包含在内。作业将定期运行以检查源A和中的更改B,并将“增量”写入聚合的数据源中。这会将两个紧密耦合的数据源转换为单个相干数据源。

有几件事可能会阻止您采用这种方法:

  • 数据量可能过高 - 需要复制完整的数据AB进行复制,从而使空间需求增加了一倍。
  • 数据处于活动状态 -从源中的数据更改到聚合作业将其传播到聚合的源之间,会有一段时间。
  • 您需要使数据与原始源保持一致 -如果采用这种方法,将更改移回原始位置的任务将变得更加复杂。

我同意,引入抽象层是首选方法
neontapir 2012年

2
您可以拥有一个抽象层,而无需复制数据。
smp7d 2012年

@ smp7d这会将联轴器隐藏在漂亮的前端后面;我假设您已经在系统中进行了类似的操作,因为否则,复杂性将分散到整个设计中。
dasblinkenlight 2012年

根据数据库环境的不同,也可以使用一个/多个视图来解决此问题,从而无需复制数据。
Walter

DataSourceADataSourceB已经脱钩?DataSourceASubSystemA.1和都有依赖SubSystemA.2,但对DataSourceB
图兰斯·科尔多瓦

1

似乎在顶层有两种类型:Foo和Bar,而您只有两个顶层动作:findFoo(...)findBar(...)。这是I / O层的接口。

您的数据源描述意味着有两种方法上的一个:findFoofindBar和B中的一个方法,包括:findFooAuxiliaryInformation。在中,findFoo您将需要合并来自A和B的信息。

我不确定您指的是“紧密耦合”。有包含在两个数据集三种数据类型:BarFoo,和FooAuxDataFoo和之间的耦合FooAuxData是输入数据中固有的,无法减少。但是,这种耦合只能出现在findFoo方法中。那是你能做的最好的。该要求在一个地方实现。如果更改,则必须更改该代码。


0

你不能

如果我理解正确,Foo并且Bar来自dsABars属于Foos。
最好,你不想Bar分配送FooS,除非Foo已通过补充Foo.enhancedInfo说来自dsB

您最喜欢将Bars 分配给Foos是造成紧密耦合的原因。我认为这是“要求挑战”,它迫使您走上一条特定的道路。

因此,技术挑战是dsB可能没有信息FoodsB也可能没有信息。

您需要确定这种偏好的Foo.enhancedInfo真实程度。根据该要求,您可以决定是否提供Foo+ Bar对象。允许提供不增强的功能Foo只会使逻辑复杂化,并告诉我,首选项并不像它看起来的那么严格。确定哪些变种FooFoo.enhancedBar你的应用程序(一个或多个),能够支持和你有你最终的答案。

您还可以执行其他一些操作来使Foo相关信息更加接近,这可能会解决其中的一些问题。问题的表达方式听起来像是您在数据对象级别处理问题,并且您可能无法考虑基础结构类型的更改。



@fstuijt我将稍后更新我的答案。从根本上讲,它将保持不变。您需要确定如何配置Bar + Foo。

0

如果数据源B中的数据不能独立存在,那么您可能需要将其迁移到数据源A上。

如果它们是独立但相关的,则应研究数据虚拟化。这将允许应用程序以不可知的方式将数据视为一组(如果适用)。根据您的平台,可能会有一个现有的框架/库可以帮助您实现此目标。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.