menpo / landmarker.io

Image and mesh annotation web application
https://www.landmarker.io
BSD 3-Clause "New" or "Revised" License
114 stars 21 forks source link

Handling different backends #92

Closed lirsacc closed 9 years ago

lirsacc commented 9 years ago

As discussed we will start work on restructuring the code in order to make the server optional and allow for different backends in the way the app starts.

Restructuring: Currently most models are aware of the server in order to leverage the fetch + url behaviour from Backbone giving us free Ajax and change propagation. However, we might have backends which are not HTTP based (local fs, dropbox) and to the best of my knowledge Backbone fetch doesn't handle anything else.

I'd propose uniformising the data handling under a common object which would expose all the required methods which return promises. We then subclass it as needed for custom backends.

To interact with it, I see 2 options given the current structure of the code:

I'd go with the former, as even if there would be more code to rewrite and test, everything would be explicit. We'd lose the reliance on Backbone for loading data (propagating changes would still happen in the models through Backbone set and changed) which I feel is more sane. The basic fetching logic is simple enough to centralise and the custom ones would have to be adapted either way.

In both cases the first step will be to pull out implicit references to the server and replace them by explicit calls to the backend (namely in asset, assetsource and landmarks which have custom behaviour, the rest of the models use standard fetch).

Startup phase: Handling various backends means we need to select one at some point. I'd make the app start in a blank state and ask user for which way they'd want it to work (local, server url, dropbox...), we delay the initialisation until we can instantiate a backend. To make it faster in some cases we can default to current behaviour if a server parameter is present in the url and store some data in local storage to automatically load the previously known backend after a hard reload.

As well, all backends will not be equal feature-wise. The idea would then be to advertise this in the backend (fetched or hard coded) and toggle functionality accordingly. We'll likely cross that bridge when implementing the various backends, but to accommodate I think the app startup should be in 2 phases: load a backend and then start the UI once we are aware of the backends' capabilities. We'd be able to check allowed behaviours in this phase rather than at runtime.

With this in mind, I'd stop making the server a Backbone model (doesn't carry state or propagate changes) but rather a simple object and a change in the backend would likely be equivalent to a restart of the app.


So to sum up, the plan is:

  1. Abstract the server into a DataStore object (after we selected how we abstract it)
  2. Make the server model an implementation
  3. Update startup code to be app > server > app > rest instead of server > app > rest as it currently is
  4. Implement a new context / backend, we can worry about tis one once the previous restructuring has been done

What do you think so far @jabooth ?

lirsacc commented 9 years ago

Closed with v2 - Dropbox is the first alternative Backend implementation for refrence