wvteijlingen / Spine

A Swift library for working with JSON:API APIs. It supports mapping to custom model classes, fetching, advanced querying, linking and persisting.
MIT License
264 stars 109 forks source link

Change Resource class to protocol #151

Open mathebox opened 7 years ago

mathebox commented 7 years ago

Hi there! This is going to be a bigger issue. So I create some sections..

Prologue I'm using Spine for an iOS application that syncs with JSON API endpoints. The Resource objects by Spine are converted to NSManagedObjects and stored in the app for the offline mode. Since you can also edit these CoreData objects, this leads to the classic client-server sync problem on the one side. On the other side you will always have the conversion from Resource to NSManagedObject and vice versa.

Proposal I was wondering whether it would to practical to change Resource from a class to a protocol. In this way you could extend a NSManagedObject to be a Resource using both CoreData and Spine functionality. This should not replace the current implementation of Resource as a standalone object. By using protocol extension, you can provide default implementations of standalone objects, CoreData, or other databases (like Realm.io). Yes, I have seen #17 but it is a year old.

The usage of a protocol would trigger more generic type throughout the code. Furthermore, Swift is static typed. I think it could be great if we could use to optimizations of the compiler and the latest swift 3 features. For example:

A Resource protocol would also prevent code like:

open class var resourceType: ResourceType {
    fatalError("Override resourceType in a subclass.")
}

This method implementation will be enforced by the protocol.

Current state I already made some local changes. Some critical complication occur when adapting the code of Deserialization (Relationships) and ResourceFactory. But I think this will work.

Closing words @wvteijlingen What is your opinion on this? I'm aware that this would be quite a big change. But I can't and will not maintain a fork of Spine.

wvteijlingen commented 7 years ago

Hi Max!

Thanks for your extensive writeup. I fully agree with you, I'd love to have Resource as a protocol. In fact, I've already tried numerous times to refactor it. The use case I had in mind is exactly what you described.

Unfortunately every time I ran into the type system that did not allow me to express what I wanted. I can't remember exactly what the issues were, but I think it was something with associated types and type constraints that didn't work with protocols.

Making more use of generics, such as generic collections, is also something I've tried to do before. What I ran into here is that you need to know beforehand what resource type will be returned from the server. To get this to work with included (sideloaded) resources proved to be a lot of work, and thus I've abandoned that for now.

That said, it might be worth it to look into this again and see if things changed with Swift 3. Would you be willing to work on this?

mathebox commented 7 years ago

I can give it a try. But I can't make any promises. I think at some point I will have to ask for your counsel and/or help for realizing this.