holyturt/SwiftOverpassWrapper

Dedicated object for relations lookup

Opened this issue · 1 comments

From issue #3:

I've already started adding tests for the XML parsers, but noticed that in order to create the node, entity or way, I needed to always provide the OverpassResponse that the XML came with. This doesn't feel quite right. Have a look at this snippet from one of the test cases. xmlElement is a AEXMLElement that I read from a local file.

So just for testing the XML parsing, I need to create an OverpassResponse that I don't actually need for the XML parsing. But when wanting to lookup releations, the models need to have a reference to the response. So what could be a solution?

Instead of having the reference to the response that an item was retrieved with, I suggest to use a dedicated object that can be queried for this information. Internally, it would keep track of the "world" that it knows about, and could lazily lookup data when needed.
This serves three purposes:

  • Keeping the models as stupid possible, having only actual data attached to them. This makes unit testing easier and reduces the complexity of the models. Additionally, it improves readability, which is always good to have, as there's no logic in those objects.
  • Letting the app "learn" about the world: With each query, new relations might be discovered, and "old" references to response instances don't contain the whole picture.
  • Preparing/allowing for the addition of optional caching: This is something that I'm currently implementing in my own app, but would be nice to have shared with everyone.

So do you have any ideas you can share for implementing the dedicated object from your works or thoughts?

Yes, I do. First of all, I'd create a central place for storing the results of all the responses so far, and already started working on a protocol. Take a look:

public protocol OverpassEntityManaging {
    /// Provides all available entities from storage.
    var entities: [OverpassEntity] { get }
    
    /// Adds a list of entities to the storage.
    /// The method will filter and list and only add those nodes that are either completely new or updated.
    ///
    /// - Parameter entities: The entities to process.
    func add(_ entities: [OverpassEntity])
}

As you can see, the object takes elements of type OverpassEntity and processes them. In my current implementation, add(_:) already handles multiple instances of the same entity being added, and maintains a list of only the newer ones (= those with a greater version).
I plan on having yet another object that contains a OverpassEntityManaging object for each of the elements (way, node and relation), but haven't started implementing it yet. That object can then have methods for looking up related nodes, ways and relations. I'll come back to you once I have some results to show.

I plan on having yet another object that contains a OverpassEntityManaging object for each of the elements (way, node and relation), but haven't started implementing it yet. That object can then have methods for looking up related nodes, ways and relations. I'll come back to you once I have some results to show.

This seems great. I look forward to seeing the actual code!