Come posso memorizzare più viste di dati in memoria?

8

Ho un sacco di moduli. Posso rompere questi moduli in diverse categorie che sono complete e non si sovrappongono. Ad esempio, tre categorie, con ID che possono essere espressi come Animal , Vegetable e Mineral . Rompo ulteriormente queste categorie in sottocategorie, che ancora sono distinte, complete e non si sovrappongono. Ad esempio, id che possono essere espressi come Mammal , Reptile , Legume , Root , Rock , Gem . Infine, al di sotto di queste categorie, ci sono i moduli stessi, ad es. Cat , Dog , Iguana , Bean , Quartz , Emerald , ecc.

Eccoicasidiutilizzocomune:

  1. Devochiamarevarimetodisututtiimoduli.
  2. Hobisognodiottenereun'istantaneapiattadellostatocorrentedituttiidatisututtiimoduli.
  3. Devochiamarevarimetodisututtiimoduliinunaparticolarecategoria(manonnellasottocategoria).
  4. HobisognodichiamarevarimetodisuunparticolaremodulospecificobasatosulsuoIDnoto.
    • Questopotrebbeessereun"fai qualcosa" o un "dimmi alcuni dati su di te"
  5. Ho bisogno di archiviare dati aggregati su tutti i moduli in una particolare categoria (ma non nella sottocategoria).

Come dovrei memorizzare questi dati?

Alcuni altri fatti rilevanti:

  • Le categorie sono stabilite in runtime
    • Pertanto, i moduli di livello inferiore condividono un'interfaccia comune.
  • Una volta impostati, non cambiano in quella particolare esecuzione, sono basati sui dati nei file di configurazione.

Ecco cosa faccio attualmente:

  1. Ho una classe che contiene Map<Category, CategoryDataStructure> . Questa classe mantiene anche un Collection<Module> separato visualizza dei dati da utilizzare con il requisito # 2.
  2. CategoryDataStructure ha metodi di delega concatenati che inviano il metodo call sulla catena, tramite SubCategoryDataStructure .
  3. CategoryDataStructure memorizza anche i dati aggregati utilizzati nel requisito # 5.

Funziona, ma è onestamente abbastanza ingombrante. Il tutto è stato / mutevole e difficile da cambiare. Se voglio aggiungere un nuovo comportamento, devo aggiungerlo in molti posti. Attualmente le strutture di dati stesse hanno anche molta logica di business; i metodi di delega. Anche la struttura dei dati genitore deve fare molta logica aziendale per creare un particolare modulo e la sua struttura di dati padre se necessario e la struttura dei dati del genitore, se necessario.

Sto cercando di scomporre in qualche modo la logica di gestione dei dati dalla struttura dei dati stessa, ma a causa del nesting è complicato. Ecco alcune altre opzioni che ho preso in considerazione:

  1. Crea un semplice Map<Category, Map<Subcategory, Module>> e metti tutto il codice per mantenere il suo stato in una classe diversa. La mia preoccupazione per questo è i requisiti # 1 e # 2, sarà difficile mantenere la vista coerente poiché ora avrò due diverse strutture di dati che rappresentano gli stessi dati.
  2. Fai tutto in una struttura di dati piatta e fai un ciclo attraverso l'intera struttura quando cerco una particolare categoria o sottocategoria.
posta durron597 02.10.2015 - 17:22
fonte

2 risposte

6

Sembra che il problema principale qui è che gli oggetti sono disposti in una gerarchia in base alla loro identità, ma li stanno usando in modo non gerarchico.

Un'analogia sarebbe memorizzare i file nelle directory in base al loro tipo di file, ma cercare in ogni directory e caricarne solo alcuni in base a criteri diversi dal tipo.

I'm looking to somehow break apart data management logic away from the data structure itself, but because of the nesting it's complicated. Here are some other options I've been considering:

Questo è un buon obiettivo e c'è un modo semplice per iniziare a dividere le responsabilità senza un refactoring principale: usa Visitatori .

L'idea è che se hai bisogno di ispezionare o operare solo su determinati elementi della gerarchia, metti questa logica nel visitatore stesso. È quindi possibile scrivere più visitatori, ognuno dei quali opera su elementi diversi ed eseguire azioni diverse.

Ogni unità di logica è ora autonoma per un visitatore specifico . Questo migliora l'SRP-ness del tuo codice. Se è necessario modificare il modo in cui un'operazione viene eseguita, lo si fa solo nel visitatore che implementa tale logica. La gerarchia degli oggetti dovrebbe rimanere la stessa, senza le modifiche superficiali per esporre i dati necessari.

Ci sono molti modi per implementare i visitatori a seconda degli obiettivi specifici, ma l'idea generale è che ogni nodo nella gerarchia accetta un oggetto visitatore. La sua implementazione è simile a questa e può essere inserita in una classe genitore astratta:

public class Node {
  public void accept(Visitor v) {
    v.accept(this);
    for (Node child : children) {
      child.accept(v);
    }
  }
}

Ciò garantisce che, indipendentemente dal modo in cui si collegano i nodi in fase di runtime, ogni nodo verrà elaborato.

Il tuo visitatore assomiglia a questo:

public interface Visitor {
  accept(Node n);
}

Il metodo accept(Node) del visitatore è il luogo in cui viene eseguito il lavoro reale. Dovrai ispezionare il nodo e fare condizionalmente cose diverse (incluso ignorare il nodo).

Ad esempio, potresti essere in grado di effettuare le seguenti operazioni:

Node root = ...;

// Print information on the hierarchy.
root.accept(new DebugVisitor());

// Does stuff with modules, ignores subcategories.
root.accept(new FrobnicateModulesVisitor());

// Eats vegetables, ignores animals and minerals.
root.accept(new EatYourVegetableVisitor());

Ogni visitatore è una classe autonoma che contiene la logica per ogni operazione senza necessità di mescolare le preoccupazioni con altri visitatori o i nodi.

    
risposta data 02.10.2015 - 18:02
fonte
1

Un livello profondo di nidificazione suggerisce che devi refactoring azioni in funzioni più piccole, che può essere incatenato utilizzando dichiarazioni di ritorno. Se è necessario applicare lo stesso metodo per più input, è possibile usufruire di function.apply() in Java 8.

Supponendo che i diversi elementi non condividano alcuna proprietà, potresti implementare un'interfaccia , che richiede che un vengono implementati specifici set di metodi. Per ogni livello vorrei creare un'interfaccia, che viene poi estesa per ciascun sottonodo, ad esempio: Entity , Phylum , Species . Inoltre, sono necessarie tre classi per ciascuna delle tre entità.

I dati possono essere archiviati come proprietà delle istanze dell'oggetto. Per ottenere un'istantanea piatta, eseguirò l'iterazione sui dati utilizzando function.apply() .

    
risposta data 02.10.2015 - 18:20
fonte

Leggi altre domande sui tag