Разработка базовой модели данных - изменение «живых» объектов также изменяет сохраненные объекты - PullRequest
2 голосов
/ 29 марта 2010

Я работаю над своим первым проектом Core Data (на iPhone), и он мне действительно нравится. Core Data - это классная штука.

Я, однако, сталкиваюсь с трудностями проектирования, которые я не знаю, как решить, хотя я предполагаю, что это довольно распространенная ситуация. Это касается модели данных.

Для ясности я буду использовать воображаемое приложение для игры в футбол в качестве примера для иллюстрации своего вопроса. Скажем, что есть NSMO, которые называются Даунс и Плейс. Воспроизводит функции как шаблоны, которые будут использоваться Даунс. Пользователь создает Plays (например, Bootleg, Button Hook, Slant Route, Sweep и т. Д.) И заполняет различные свойства. У пьес много общего с Даунсом. Для каждого дауна пользователь решает, какую игру использовать. Когда выполняется Down, он использует Play в качестве шаблона. После каждого запуска он сохраняется в истории. Программа запоминает все когда-либо сыгранные Дауны.

Пока все хорошо. Это все работает нормально.

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

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

  1. «Управление версиями» пьес. Каждое изменение в шаблоне Play фактически создает новый отдельный объект Play с тем же именем (насколько пользователь может судить). Однако под капотом это на самом деле другая игра. Это работает, AFAICT, но кажется, что это может потенциально привести к дикому распространению объектов Play, особенно. если пользователь продолжает переключаться между несколькими версиями одного и того же Play (создание объекта за объектом каждый раз, когда пользователь переключается). Да, приложение может проверять наличие уже существующих идентичных пьес, но ... это просто беспорядок.

  2. При сохранении записывайте детали, которые они использовали для воспроизведения, но не в качестве объекта воспроизведения. Это просто кажется смешным, учитывая, что объект Play находится там , чтобы хранить только эти детали.

  3. Признайте, что объекты Play на самом деле выполняют 2 функции: одну для шаблона Down, а другую для записи того, какой шаблон был использован. Эти 2 функции имеют разные отношения с Down. Первый (шаблон) имеет отношение ко многим. Но вторая (запись) имеет отношение один к одному. Это будет означать создание второго объекта, что-то вроде «Play-Template», который сохранит связь «многие-многие» с Даунами. Игровые объекты будут переконфигурированы, чтобы иметь отношение один к одному с Даунами. A Down будет использовать объект Play-Template для выполнения, но использовать новый тип объекта Play для хранения того, какой шаблон был использован. Именно это изменение отношения «многие ко многим» к отношениям «один к одному» и составляет суть проблемы.

Даже написание этого вопроса помогло мне прояснить ситуацию. Я думаю, что что-то вроде решения 3 является ответом. Однако, если у кого-то есть идея получше или просто подтверждение, что я на правильном пути, это было бы полезно. (Помните, я на самом деле не создаю футбольную игру, просто использовать метафору быстрее / проще для всех).

Ответы [ 2 ]

1 голос
/ 30 марта 2010

Я думаю, вам нужно начать с вашего дизайна.

(1) Почему PlayEntity используется в качестве шаблона для DownEntity? Сущности на самом деле (скрытые) классы, поэтому само определение класса является «шаблоном» для каждого экземпляра.

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

В вашем примере Plays and Downs моделируют совершенно разные вещи.

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

Игра по контрасту - это пространственное событие. Игры не уникальны и часто повторяются в игре и от игры к игре. Игровая сущность должна учитывать пространственные отношения между игроками, мячом и полем.

В итоге вы получите что-то вроде этого:

DownEntity{
    game;
    half;
    quarter;
    turnover;
    gameClockTime;
    yardLine;
    penalties;
    play --(required,Cascade)->PlayEntity.down
    previousDown --(optional, nullify)-->Down.nextDown;
    nextDown --(optional, nullify)-->Down.previousDown
}


PlayEntity {
    playName;
    //whatever other detail you want to model
    down --(optional,nullify)-->>DownEnity.play;
}

Обратите внимание, что ни один объект не дублирует информацию, содержащуюся в атрибутах другого. Они также не разделяют наследство, потому что они не моделируют одни и те же аспекты игры. Down моделирует временную последовательность, а Play - пространственную. Это требует, чтобы они оба полностью описали то, что произошло на каждом из них.

Вы бы создали свою базу данных, сначала создав любые стандартизированные PlayEntities, которые вы хотели. Если бы у вас была новая пьеса, вы бы создали новую PlayEntity и заполнили ее по мере необходимости. Каждый раз, когда у вас был сбой, вы создавали DownEntity и устанавливали связь с существующим или вновь созданным PlayEntity.

0 голосов
/ 29 марта 2010

Я бы выбрал ваш # 3 как самый ясный и разумный вариант. Он хорошо охватывает предполагаемое использование вашего (метафорического) приложения.

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

...