Progettazione della struttura dei dati del servizio di archiviazione per i modelli disaccoppiati che condividono gli stessi dati

4

Sicuramente la maggior parte di voi ricorda l'applicazione Norton Commander dove dati simili (a volte uguali) vengono visualizzati in viste separate disaccoppiate .

Sto costruendo un'applicazione web che segue lo stesso principio. La quantità di dati è troppo grande per essere recuperata / visualizzata interamente nella pagina e i sottoinsiemi di dati potenzialmente sovrapposti devono essere visualizzati in viste separate.

La mia architettura ha questo aspetto:

                           ┌──────── EventBus ────────┐
                           │             │            │
                           │      StorageService      │
                           │       ╱          ╲       │
                     PresenterLeft┤            ├PresenterRight
                        ╱     ╲    ╲          ╱    ╱      ╲ 
                  ViewLeft   ModelLeft      ModelRight   ViewRight

L'applicazione crea entrambi i relatori e passa loro l'istanza di EventBus e StorageService. I presentatori, a loro volta, creano i rispettivi modelli e punti di vista. StorageService viene passato ai modelli. La comunicazione tra i presentatori avviene tramite l'EventBus.

In questo scenario il lato sinistro non ha consapevolezza del lato destro, tuttavia i modelli dovrebbero possedere le stesse informazioni senza la necessità di effettuare un doppio round trip sul server.

Per raggiungere questo obiettivo, utilizzo lo StorageService. I modelli implementano il metodo model.fetch() che richiede l'archiviazione per i dati. Se gli stessi dati sono stati precedentemente richiesti, lo storage lo restituirà semplicemente come una cache in memoria.

Ecco la vera domanda. Nel contesto precedente, come progettare una struttura dati per un servizio di archiviazione efficiente dal punto di vista della rete per il seguente caso d'uso:

  1. Richieste di modello a sinistra GET /files?limit=100
  2. Richieste di modello giuste GET /files?limit=110 (ma in realtà ho bisogno solo degli ultimi 10)

Il mio tentativo di approccio era:

  • memorizza le richieste fatte dai modelli
  • per ogni richiesta aggiuntiva, fai del mio meglio per capire la richiesta di diff
  • fai la richiesta di diff (ad esempio GET /files?offset=100&limit=10 )
  • archivia gli elementi recuperati in {"files": {"id1": item1, ..., "id110": item110}}

Purtroppo i passaggi precedenti non aiutano, perché non c'è alcuna relazione tra l'url e gli id. Quando un modello richiede il prossimo set di valori, non so mai se si trovano effettivamente nella cache in memoria.

Ovviamente, potrei usare la strategia di caching in-memory per-url, ma poi avrei delle voci duplicate nella cache, cosa che vorrei evitare.

Quali sono i tuoi pensieri? Mi sento come se stessi reinventando la ruota qui. Esiste un metodo migliore / più semplice / comunemente accettato? Forse la mia architettura è difettosa ...

    
posta Oleg 20.02.2014 - 11:26
fonte

1 risposta

1

Gli URL dovrebbero semplicemente mappare internamente ad alcune chiamate a un repository che implementa il comportamento di caching che desideri.

LeftViewModel should call IFileRepository getRecentFiles(100) through /files?limit=100
RightViewModel should call IFileRepository getRecentFiles(110) through /files?limit=110

Quindi crea qualcosa del tipo:

CachingFileRepository implements IFileRepository
  depends on another IFileRepository for permanent storage
  function getRecentFiles (limit)
    if cacheSize < limit
      get the rest of the files from the permanent repository
      add the files to the cache
    return the files

Se vuoi avere la mappatura 1: 1 per url, dovresti avere più URL (uno in più per la memoria permanente, usa quello esistente per la cache).

Se vuoi avere un URL per il servizio, dovresti avere più classi dietro quel solo URL.

EDIT: Inoltre, se si desidera eseguire questa operazione senza due roundtrip per lo storage, è possibile tenere traccia delle visualizzazioni che si stanno generando e richiedere i dati del modello una volta dopo aver appreso quali sono i modelli necessari. Qualcosa come

BaseFileModel
  limit = 0
  require()
    storageService->requireLimit(limit)
  populate()
    storageService->getFiles(limit)

ModelLeft extends BaseFileModel
  limit = 100

ModelRight extends BaseFileModel
  limit = 110

Application
  createModels() //creates ModelLeft and ModelRight, sending storageService and calling populate
  storageService->getRemoteData() - one call to get data
  populateModels()
  renderViews()
    
risposta data 26.02.2014 - 08:34
fonte

Leggi altre domande sui tag