Шаблоны / структуры для обратной навигации отношения «многие ко многим»? - PullRequest
0 голосов
/ 16 сентября 2011

Пользовательская история:

Пользователь нашего приложения создает дорожные поездки.A roadtrip - это последовательная серия интересных направлений.Каждый destination имеет некоторые подробности о деятельности или зрелище, чтобы увидеть, пока там.Таким образом, наш пользователь определяет две дорожные поездки, в которых каждая поездка имела несколько уникальных направлений и некоторые направления, общие для обоих - например, обе поездки включают Смитсоновский институт.Приложение поддерживает все обновления в памяти и фиксирует только базу данных, когда пользователь нажимает сохранить.Пользователь активно обновляет обе поездки и может переключаться между ними по желанию.В некоторых точках нашего приложения мы имеем дело со Смитсоновским пунктом назначения, но иногда нам нужно перемещаться вверх по нашей иерархии объектов от пункта назначения до содержащего его маршрута.Проблема заключается в том, что пункт назначения участвует в двух дорожных поездках.

RoadTrip1
 |
 +-Destination1
 +-Destination2
 +-Destination3
 +-Smithsonian (A) //Navigate up to RoadTrip1

RoadTrip2
 |
 +-Destination4
 +-Smithsonian (B) //Navigate up to RoadTrip2
 +-Destination5

Какой хороший шаблон проектирования или структуру данных мы могли бы использовать для обеспечения обратной навигации, обеспечивая при этом только одну копию объекта назначения?

Требования:

  1. Ваша модель участвует в отношениях "многие ко многим".
  2. Представляет все модели только один раз в памяти (Карта идентичности).
  3. Ваша структура данных должна быть легко ориентируемой.Вы можете не только переходить от родителя к потомку, но вы также можете переходить от потомка к родителю, по которому изначально был получен потомок.
  4. Я хочу избежать введения дополнительной схемы в модель данных.

До сих пор моя лучшая идея заключалась в том, чтобы обернуть каждый целевой объект контекстным объектом (аналогично тому, как связанные списки оборачивают узлы).Объект контекста будет поддерживать указатель на родительский объект, из которого он был изначально выбран.Мы будем иметь дело с каждым пунктом назначения всегда через его оболочку.Я полагаю, что это будет либо шаблон Proxy, либо Decorator (я склоняюсь к Proxy).(Разве это не было бы той же самой идеей, как то, как объект jQuery охватывает много элементов, и несколько объектов jQuery делятся ссылками на одни и те же элементы?)для навигации от пункта назначения до его вмещающей поездки.Это не так надежно, как фактический «выборочный контекст».На самом деле, это совершенно другая тактика, и я не уверен, что мне это нравится.

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

Были ли другие сталкивались с этой проблемой раньше - то есть, хотели ли идти назад туда, где многие родители путают обратную навигацию?Вы когда-нибудь спрашивали "от какого родителя я приехал сюда?"Как ты ответил на это?

Ответы [ 2 ]

0 голосов
/ 19 сентября 2011

Мне удалось выработать решение, которое я получил после использования шаблона прокси.Что я действительно хотел, так это концепция «извлечения контекста».Я хотел знать, от какого родителя я первоначально выбрал модель (ребенок, имеющий несколько родителей).

Ключом к решению проблемы было обеспечение поддержки контекста выборки. Мы отвечали за объекты запроса, а не за наши модели.

var activity = roadtrip.destinations().all().activities().first();

Мы начинаем с roadtrip модели и вызываем destinations функция.Эта функция возвращает объект запроса.Этот объект запроса похож по дизайну на реализацию Rails в Rails в том, что он ленив, фактически не возвращает никаких записей, пока вы не вызовете all, first, each и т. Д. Объект запроса имеет переменную context, которая указываетего родителю - модель roadtrip.

Вызов all возвращает объект коллекции, чей context указывает на запрос, из которого он был вызван.Каждый элемент в коллекции - это прокси (queried item), который охватывает каждую базовую модель destination.Прокси поддерживает ссылку на свою коллекцию.Самый простой способ получить этот прокси-сервер выглядит следующим образом:

var proxied_destination = Object.create(destination);

Таким образом, вы можете назначить context для прокси, не влияя на оригинал.

proxied_destination.context = collection;

Это позволяет«мастерская» модель осталась нетронутой и, таким образом, отображалась на личность.Это было бы невозможно, если бы наша модель поддерживала прямую ссылку на свою коллекцию, поскольку модель может принимать участие в нескольких результирующих наборах (мы можем выполнить столько запросов, сколько захотим), и в моем сценарии мы ожидаем только один контекст (родительский).

Мы вызываем activities, который предоставляет нам другой объект запроса, контекст которого является прокси destination.Мы вызываем first и вместо того, чтобы получить коллекцию, мы получаем прокси activity, имеющий контекст, который указывает на объект запроса действий.

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

0 голосов
/ 16 сентября 2011

У вас должно быть 3 класса: Roadtrip, Destination и Place.Таким образом, ваши пункты назначения A и B - это два разных объекта, которые оба ссылаются на одно и то же место.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...