Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a new NSManagedObject subclass to (eventually) support full JSON documents #216

Open
jcmosc opened this issue Feb 24, 2014 · 7 comments

Comments

@jcmosc
Copy link
Contributor

jcmosc commented Feb 24, 2014

Out of all the things that need to change in order to support full JSON documents with nested JSON structures, The first step that can happen independently is to be able to distinguish between Core Data entities that represent top-level objects, and entities that represent nested objects.

I propose changing:

@interface SPManagedObject : NSManagedObject <SPDiffable>
@property (nonatomic, copy) NSString *simperiumKey;
.... remaining SPDiffable methods and properties ...
@end

to:

@interface SPManagedObject : SPManagedObjectElement <SPDiffable>
.... remaining SPDiffable methods and properties ...
@end

@interface SPManagedObjectElement : NSManagedObject
@property (nonatomic, copy) NSString *simperiumKey;
@end

This naming and class hierarchy is analogous to document-object-model class structure, i.e. everything is a Simperium element (DOM node) and the top-level entity is also the Simperium bucket object itself (DOM document).

Currently in happy-inspector:embedded-objects we just added SPEmbeddedManagedObject parallel to SPManagedObject, but I think it's awkward. It also leads to some code duplication in that branch, i.e. there are two completely independent code paths for fetching objects and ensuring each object has a Simperium key.

@mikejohnstn
Copy link
Contributor

Did you see SPObject? It and the SPDiffable protocol were intended for this: https://github.com/Simperium/simperium-ios/blob/develop/Simperium/SPObject.h

But I haven't thought about this in quite awhile.

@jcmosc
Copy link
Contributor Author

jcmosc commented Feb 24, 2014

Sorry I didn't write <SPDiffiable> anywhere, so the intention may be a bit unclear. I'll fix that now.

So the rest of the client would and does work with the SPDiffable protocol, not the underlying concrete class. At the moment the two implementations of SPDiffable are SPObject and SPManagedObject, and this wouldn't change.

This change is uniquely for Core Data stores since you can only work with semi-scalar attributes or full relationships, but not embedded relationships. So we have to model a single bucket across multiple Core Data entities. SPManagedObjectElement would not implement SPDiffable since it does not correspond to a bucket. It's only property is simperiumKey which is used to perform list-diffing etc. It doesn't implement any of the other SPDiffable properties, not even ghost.

I assume SPObject would handle embedded relationships in it's own way since it does not have the same structural limitations as Core Data. I haven't thought about how to implement it though...

@mikejohnstn
Copy link
Contributor

So we have to model a single bucket across multiple Core Data entities.

Interesting, I think this is the inverse of a feature @fredrocious has considered (mapping multiple buckets to a single entity). Anyway, I think I see what you mean now.

As for the other stuff, doing it incrementally makes sense and could be divided something like:

  1. Finish SPJSONStorage and add support for persistence (it's in-memory only right now). I don't believe this is needed for your use case, but it overlaps and will be a very handy feature.
  2. Add full diffing support to SPMemberJSONList including recursive lists.
  3. Create SPMemberJSONDictionary with full diffing and recursion.
  4. Solve embedded relationships, perhaps via a SPMemberEntity subclass which could use SPMemberJSONList and SPMemberJSONDictionary for recursive embedding of relationships. Update SPCoreDataExporter to look for a UserInfo key on relationships that lets you say which relationships you want to be embedded.

Plus unit tests for each of these steps.

@mackross
Copy link
Contributor

SPEmbeddedManagedObject makes sense from a JSON document storage system like mongo where you have documents and embedded documents. I removed SPMember classes in favour of something more like JSONDiff from the javascript library. This code is then easily reusable between SPJSONStorage & SPCoreDataStorage.

@mackross
Copy link
Contributor

Then again perhaps SPManagedObjectDocument and SPManagedObjectEmbeddedDocument would be better names.

@mikejohnstn
Copy link
Contributor

Any names with "document" probably aren't great due to other connotations (like Core Data documents).

All the SPMember subclasses can already be used with any SPStorage. This may not be obvious, but SPJSONStorage and SPObject are intended to work transparently with your NSMutableDictionary objects so you don't have to riddle your code with Simperium subclasses or custom objects. Subclassing and custom objects bother me in the various commercial frameworks out there. See NSMutableDictionary+Simperium.m for various swizzling intended to enable this. But it's been awhile since I've thought about all this—it might be too magical.

The only SBMember exception right now is SPMemberEntity which is specific to Core Data, but could be generalized and divided into subclasses.

I took this approach anticipating we'd add more types over time, some of which need specific libraries (like DiffMatchPatch), with the goal of keeping the code separate and allowing subclassing. See SPMemberBinaryInfo, SPMemberBase64, and SPMemberText for some examples. I'm not a huge fan of JSONDiff's "put everything in one big file" approach.

Yet, unifying diffing across the libraries (with common unit tests) remains a good goal. A change might be in order if only for that. @jleandroperez probably has some thoughts.

@jcmosc
Copy link
Contributor Author

jcmosc commented Feb 25, 2014

The main thing I wanted to figure out with this issue was, regardless of naming, whether it would be better in the long term to have:

@interface SPManagedObject : NSManagedObject <SPDiffable>
@interface [Embedded] : NSManagedObject

or:

@interface SPManagedObject : [Embedded] <SPDiffable>
@interface [Embedded] : NSManagedObject

We can create separate issues for tackling any diffing etc. stuff.

@jleandroperez jleandroperez self-assigned this Mar 5, 2014
@jleandroperez jleandroperez modified the milestones: v0.7.0, v0.8.0 Mar 5, 2014
jleandroperez added a commit to happy-co/simperium-ios that referenced this issue Jun 5, 2014
@jleandroperez jleandroperez modified the milestone: v0.8.0 Sep 9, 2014
@jleandroperez jleandroperez modified the milestone: v0.7.5 Nov 20, 2014
@jleandroperez jleandroperez modified the milestones: v0.7.5, v0.7.6 Nov 28, 2014
@jleandroperez jleandroperez modified the milestones: v0.7.6, v0.7.7 Jan 6, 2015
@jleandroperez jleandroperez modified the milestones: v0.7.7, v0.7.8, v0.7.9 Feb 4, 2015
@jleandroperez jleandroperez modified the milestones: v0.7.9, v0.7.8 Feb 4, 2015
@jleandroperez jleandroperez removed their assignment Jan 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants