开发者

Core Data Model Design - Changing "Live" Objects also Changes Saved Objects

I'm working on my first Core Data project (on iPhone) and am really liking it. Core Data is cool stuff.

I am, however, running into a design difficulty that I'm not sure how to solve, although I imagine it's a fairly common situation. It concerns the data model.

For the sake of clarity, I'll use an imaginary football game app as an example to illustrate my question. Say that there are NSMO's called Downs and Plays. Plays function like templates to be used by Downs. The user creates Plays (for example, Bootleg, Button Hook, Slant Route, Sweep, etc.) and fills in the various properties. Plays have a to-many relationship with Downs. For each Down, the user decides which Play to use. When the Down is executed, it uses the Play as its template. After each down is run, it is stored in history. The program remembers all the Downs ever played.

So far, so good. This is all working fine.

The question I have concerns what happens when the user wants to change the details of a Play. Let's say it originally involved a pass to the left, but the user now wants it to be a pass to the right. Making that change, however, not only affects all the future executions of that Play, but also changes the details of the Plays stored in history. The record of Downs gets "polluted," in effect, because 开发者_开发技巧the Play template has been changed.

I have been rolling around several possible fixes to this situation, but I imagine the geniuses of SO know much more about how to handle this than I do. Still, the potential fixes I've come up with are:

  1. "Versioning" of Plays. Each change to a Play template actually creates a new, separate Play object with the same name (as far as the user can tell). Underneath the hood, however, it is actually a different Play. This would work, AFAICT, but seems like it could potentially lead to a wild proliferation of Play objects, esp. if the user keeps switching back and forth between several versions of the same Play (creating object after object each time the user switches). Yes, the app could check for pre-existing, identical Plays, but... it just seems like a mess.

  2. Have Downs, upon saving, record the details of the Play they used, but not as a Play object. This just seems ridiculous, given that the Play object is there to hold those just those details.

  3. Recognize that Play objects are actually fulfilling 2 functions: one to be a template for a Down, and the other to record what template was used. These 2 functions have a different relationship with a Down. The first (template) has a to-many relationship. But the second (record) has a one-to-one relationship. This would mean creating a second object, something like "Play-Template" which would retain the to-many relationship with Downs. Play objects would get reconfigured to have a one-to-one relationship with Downs. A Down would use a Play-Template object for execution, but use the new kind of Play object to store what template was used. It is this change from a to-many relationship to a one-to-one relationship that represents the crux of the problem.

Even writing this question out has helped me get clearer. I think something like solution 3 is the answer. However if anyone has a better idea or even just a confirmation that I'm on the right track, that would be helpful. (Remember, I'm not really making a football game, it's just faster/easier to use a metaphor everyone understands.)


I think you need to start over with your design.

(1) Why are using a PlayEntity as a template for the DownEntity? Entities are really (under the hood) classes so the class definition itself is the "template" for each instance.

(2) Managed Objects should represent data models of real objects or real information relationships. Therefore you need to think hard about what you the real objects or information you are trying to model. A good place to start is to ask yourself how this information would be recorded with pen and paper.

In your example, Plays and Downs model entirely different things.

A Down is an event ordered in time. There is only one particular Down in any particular game. This means every Down every played in every game in the history of football is utterly unique. A Down data model entity therefore would be primarily interested in modeling the Down's relation in time to other downs and the total game.

A Play by contrast is a spatial event. Plays are not unique and are often repeated within a game and from game to game. A Play entity should be concerned with the spatial relationships between players, the ball and the field.

You would end up with something like this:

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;
}

Note that neither entity duplicates information held in the attributes of the other. Neither do they share inheritance because they don't model the same aspects of the game. The Down models a temporal sequence and the Play models a spatial one. It requires both of them to completely describe what happened upon each down.

You would build your database by first creating any standardized PlayEntities you wanted. If you had a novel play, you would create a new PlayEntity and populate it as needed. Every time you had a down you would create a DownEntity and create a relationship to an existing or newly created PlayEntity.


I would go with your #3 as the clearest, most sensible option. It covers the intended usage of your (metaphorical) application well.

I ran into a similar situation a while back with an app that tracked tests administered to people; the tests contained multiple questions, and could be changed and re-administered on multiple dates. Having a test template, along with individual test objects, made the entire model much easier to deal with.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜