Как уменьшить жесткую связь между двумя источниками данных

10

У меня возникли проблемы с поиском правильного решения следующей проблемы архитектуры.

В нашей настройке (набросок ниже) у нас есть 2 источника данных, где источник данных A является основным источником для элементов типа Foo. Существует вторичный источник данных, который можно использовать для получения дополнительной информации о Foo; Однако эта информация не всегда существует.

Кроме того, источник данных A может быть использован для извлечения элементов типа Bar. Тем не менее, каждый бар относится к Foo. Трудность заключается в том, что каждый столбец должен ссылаться на Foo, который, если имеется, также содержит информацию, дополненную источником данных B.

Мой вопрос: как устранить тесную связь между SubsystemA.1 и DataSourceB?

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

fstuijt
источник
10
Это красивый эскиз. Какую программу вы использовали, чтобы нарисовать его?
Marcelo MD
Я также хочу знать, какую программу вы использовали для рисования. Пожалуйста.
Тулаинс Кордова
2
yuml.me - это сайт, который он использовал для создания диаграммы.
Джейсон Тернер
1
Разве не DataSourceAи DataSourceBуже развязаны? DataSourceAзависит как от, так SubSystemA.1и от SubSystemA.2, но не от DataSourceB.
Тулаинс Кордова
1
@fstuijt Нет, это не так. Если вы измените, SubsystemA.1чтобы использовать что-то другое DataSourceB, DataSourceAне будет знать. DataSourceAтолько заботы, у SubsystemA.1которых есть getFoo(id)метод. Есть абстракция между DataSourceAи DataSourceB.
Тулаинс Кордова

Ответы:

3

Я создал приложение с почти такой же архитектурой данных; у нас есть локальная база данных SQL, содержащая большую часть автоматизированной и внутренней оперативной информации, а затем стороннюю облачную службу, используемую для продаж, управления учетными записями, полевого персонала и т. д. Служба поддержки нуждалась в информации как физических лиц, так и клиентов. и оборудование, и получал его из двух разных приложений, пока я не вмешался.

Длинным и коротким является то, что один источник данных должен иметь ссылку на записи другого. В нашем случае сторонние облачные данные содержат ссылки на локальные данные, потому что это механизм, который мы контролировали больше всего. Теперь, с помощью идентификатора для записи из любого источника данных, мы можем получить данные из обоих; с помощью идентификатора облака мы извлекаем запись из облака, получаем идентификатор на месте и извлекаем данные на месте. Используя локальный идентификатор, мы опрашиваем оба источника данных на основе этого идентификатора.

В моей системе я не делал ни одного объекта дочерним по отношению к другому на уровне домена; любое использование данных из обоих хранилищ должно поддерживать два экземпляра объекта. Ни один из них не гарантированно существует, поэтому я так и сделал; приложение может работать только с облачными данными, с локальными данными или с обоими, с большими ограничениями, чем меньше данных.

Однако это не сложно изменить, особенно если вы уверены, что одна сторона будет существовать всегда; просто включите в объект свойство, представляющее сторону, для которой всегда будут существовать данные, то есть тип объекта, представляющий запись другого хранилища данных. Возможно более сложное «объединение» двух графиков в один.

Такая договоренность обязательно должна быть связана на каком-то уровне. У вас может быть DAL, который может взаимодействовать с обоими хранилищами данных, или вы можете сегментировать DAL, по одному на хранилище данных, и иметь более высокий уровень, такой как Контроллер, который получает данные из каждого и связывает их вместе. Но на каком-то уровне ваша программа должна обладать умом объединять данные этих двух разнородных источников данных.

Вы можете уменьшить требуемую связь в большинстве случаев, абстрагировавшись от подробностей, откуда именно поступают данные. Если вы получаете данные из веб-службы, которая предоставляется вам в качестве экземпляров сгенерированных классов, то установите конвертер для создания глубокой копии класса службы в то, что вы контролируете, которое не нужно будет менять, если данные источник делает (только если схема делает).

Теперь это может быть огромным предприятием; Облако, которое мы используем, имеет десятки классов доменов, некоторые из которых имеют сотни полей данных, и - вот что примечательно - вам может быть очень легко внести большие изменения в абстрактный тип данных, чтобы приспособиться к переходу в другое облако или другое удаленное источник данных. По этой причине я не беспокоился; Я использую сгенерированный домен веб-службы напрямую, и теперь, когда переход от облака к внешнему (но под нашим контролем) хранилищу данных вырисовывается, подробности которого я до сих пор не знаю, я просто планирую изменить формы и кодовые привязки приложения, в котором данные «объединяются», чтобы отразить новую схему и / или объекты данных. Это большая работа, независимо от того, как ты ее нарезаешь.

Keiths
источник
Этот ответ наилучшим образом охватывает проблему, с которой я столкнулся, и, на мой взгляд, также предлагает лучший ответ на данный момент. Тем не менее, я думаю, что объединение данных из нескольких источников является распространенной проблемой. Какие-то шаблоны дизайна, которые могут помочь?
Фстуйт
1
Некоторые вариации на фабричном шаблоне могут быть полезны. Если у вас есть CloudInvoice и объект SqlInvoice (из их соответствующих источников данных), и вы хотите создать единый унифицированный счет-фактуру, создайте Factory, которая знает достаточно об обоих источниках данных, чтобы извлечь каждую половину записи, которую она собирается создать, и затем объединяет информацию в класс вашего домена.
KeithS
4

Одним из способов решения этой проблемы является создание агрегированного источника данных, который содержит данные из обоих источников данных в одном месте. Задание будет периодически запускаться для проверки изменений в источниках Aи Bи записи «дельт» в ваш агрегированный источник данных. Это позволит преобразовать два тесно связанных источника данных в единый связный источник данных.

Несколько вещей могут помешать вам принять этот подход:

  • Объем данных может быть чрезмерным - полная копия Aи Bдолжна быть сделана, удваивая требования к пространству.
  • Данные должны быть живыми - между периодами, когда данные в источнике изменились, и заданием агрегирования распространило его в агрегированный источник.
  • Вам необходимо согласовать данные с исходными источниками - если вы воспользуетесь этим подходом, задача переместить изменения обратно в исходные места станет намного сложнее.
dasblinkenlight
источник
Я согласен, введение абстракции является предпочтительным подходом
neontapir
2
Вы можете создать слой абстракции без копирования данных.
smp7d
@ smp7d Это скрыло бы связь за хорошим внешним интерфейсом; Я предположил, что вы уже делаете что-то подобное в своей системе, потому что в противном случае сложность будет распространяться на весь ваш проект.
dasblinkenlight
В зависимости от среды БД это также можно обрабатывать одним или несколькими представлениями, что устраняет необходимость в копировании данных.
Уолтер
Разве не DataSourceAи DataSourceBуже развязаны? DataSourceAзависит как от, так SubSystemA.1и от SubSystemA.2, но не от DataSourceB.
Тулаинс Кордова
1

Кажется, что на верхнем уровне есть два типа: Foo и Bar, и у вас есть только два действия верхнего уровня: findFoo(...)и findBar(...). Это интерфейс к уровню ввода / вывода.

Ваше описание источников данных следует , что существует два способа на А: findFooи findBarи один метод на B: findFooAuxiliaryInformation. В findFooвас нужно будет объединить информацию от А и Б.

Я не уверен, о какой "жесткой связи" ты говоришь. Есть три типа данных , содержащихся в этих двух наборов данных: Bar, Foo, и FooAuxData. Связь между Fooи FooAuxDataприсуща входным данным и не может быть уменьшена. Но эта связь должна появляться только в findFooметоде. Это лучшее, что вы можете сделать. Требование реализовано в одном месте. Если он меняется, вы должны изменить этот код.

Кевин Клайн
источник
0

Ты не можешь

Если я правильно понимаю, Fooи Barоткуда dsA. Bars принадлежат Foos.
Предпочтительно, чтобы вы не хотите , BarS , присвоенный Fooс, если Fooне было дополнено , Foo.enhancedInfoчто исходит от dsB.

Вы предпочитаете присваивать Bars Foos, что создает тесную связь. Я бы назвал это «проблемой требований», которая заставляет вас идти по определенному пути.

Таким образом, технические проблемы заключаются в том, что dsBможет иметь или не иметь информацию о какой-либо информации, Fooа dsBможет даже не быть доступной.

Вам нужно решить, насколько сложным и быстрым является это предпочтение Foo.enhancedInfo. Основываясь на этом требовании, вы можете решить, предоставлять объект Foo+ Barили нет. Разрешение на предоставление расширенного Fooкода только усложняет логику и говорит мне, что предпочтение не так строго, как может показаться. Определите , какие варианты Foo, Foo.enhancedи Barваше приложение (s) может поддерживать , и вы будете иметь свой окончательный ответ.

Есть и другие вещи, которые вы можете сделать, чтобы Fooсблизить связанную информацию, и это может решить некоторые из этих проблем. То, как сформулирован ваш вопрос, звучит так, как будто вы имеете дело с проблемой на уровне объекта данных, и вы не сможете учесть изменения типа инфраструктуры.


источник
Другой путь »: Foo s принадлежат Bar s
fstuijt
@fstuijt Я обновлю свой ответ немного. Принципиально это останется прежним. Вам нужно решить, как вы хотите настроить сервер Bar + Foo.
0

Если данные в источнике данных B не могут стоять самостоятельно, вы, возможно, захотите перенести их в источник данных A, если это возможно.

Если они независимы, но связаны между собой, вам следует заняться виртуализацией данных . Это позволит приложениям обрабатывать данные как один набор (когда это необходимо) независимым образом. В зависимости от вашей платформы, вероятно, будет существующая инфраструктура / библиотека, которая поможет вам реализовать это.

smp7d
источник