I have a Core Data model with two entities: Video
and Playlist
.
- A
Video
can be a member of manyPlaylist
s - A
Playlist
can have manyVideo
s, including the sameVideo
multiple times - A
Playlist
'sVideo
s are ordered
Video
<<----->>Playlist
That being said, I've decided that I need a third entity: Playlist Item
.
- A
Playlist Item
has an index - A
Playlist Item
can only have a relationship with oneVideo
entity and onePlaylist
entity
And so, this causes the original specification to be revised...
- A
Video
can have manyPlaylist Item
s - A
Playlist
can have manyPlaylist Item
s, but eachPlaylist Item
has a unique index - A
Playlist
'sPlaylist Item
s are ordered using the index attribute
Video <---->> Playlist Item <<----> Playlist
So, the addition of the Playlist Item
entity allows me to have many-to-many relationships between Video
and Playlist
and still maintain ordered lists. Adding this third entity however adds complexity to the overall design.
I am wondering if it is wise to hide that complexity managing the Playlist Item
objects in the Video
and Playlist
implementations.
Video
@interface Video : NSManagedObject
@property (strong, nonatomic) NSSet *playlists; // Custom accessor; Transient attribute; data persisted in Playlist Item
// No declared NSSet for playlistItems
@end
Playlist
@interface Playlist: NSManagedObject
@property (nonatomic, strong) NSArray *videos; // Custom accessor...
// No declared playlistItems here either!
@end
It seems by doing this I will gain code that is better at revealing intentions.
The code smell I'm getting is that NSManagedObjects
subclasses are model classes and should therefore not have any controller type glue. Furthermore it makes my Video
and Playlist
classes completely dependent upon the Playlist Item
s class. But, all of that said writing the accessor is trivial, which is why I'm considering this approach:
- (NSArray *)videos
{
[self willAccessValueForKey:@"videos"];
NSArray *v = [self primitiveVideos];
[self didAccessValueForKey:@"videos"];
if (v) {
return v;
}
NSSet *pi = [self playlistItems];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES];
NSArray *orderedPlaylistItems = [pi sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
NSUInteger count = [orderedPlaylistItems count];
NSMutableArray *videos = [NSMutableArray arrayWithCapacity:count];
for (int index = 0; index < count; index++) {
[videos addObject:[[orderedPlaylistItems objectAtIndex:index] video]];
}
v = videos;
[self setPrimitiveVideos:v];
return v;
}
(This code is pretty rough, but you get the point, a few lines and voila! an array of video objects from the set of playlist items)
Maybe there is a design pattern or best practice that would help guide my decision?