Uso di Map in Java (o altre lingue strongmente tipizzate) per lavorare con dati non strutturati

5

Dopo aver esaminato il tipo di dati di base per i framework che trattano i dati non strutturati in java:

il tema comune sembra essere che i dati vengono prima deserializzati in Map, quindi trasformati in una determinata classe tramite reflection.
Quindi questo solleva la domanda, perché non lavorare direttamente con questa Mappa (o sottotipo di mappa) direttamente? Puoi estendere la mappa e creare il tuo sottotipo, e avrai ancora tutti i vantaggi della programmazione OO.

Modifica Non mi interessa il costo della deserializzazione, ma la flessibilità offerta da Map quando si gestiscono dati non strutturati. Con questo, voglio dire non dover definire una classe in cui i dati possono essere deserializzati.
Modifica 2 Sono più interessato al "perché no (svantaggi)", dal momento che il framework che ho citato ha già dimostrato che potrebbe essere fatto.

    
posta ltfishie 21.02.2012 - 17:22
fonte

3 risposte

7

La comodità di lavorare con un oggetto strongmente tipizzato a volte supera il costo della serializzazione su / da quell'oggetto. Ad esempio, di solito uso JSON per trasmettere MVVM ViewModels via cavo. Una volta che i dati sono deserializzati, posso sfruttare la funzionalità incorporata nella classe ViewModel che funziona sui dati. Se stavo solo passando dei dati stupidi, allora sono d'accordo che probabilmente ha senso rinunciare a quel passo in più.

Che cosa sono i dati stupidi? Per me i dati stupidi sono una classe che non contiene nulla, ma semplici proprietà / campi e qualsiasi logica è fornita da altre classi che li consumano (cfr. Modello di dominio anemico o Oggetto di trasferimento dati ).

Se invece (de) serializzi oggetti intelligenti (come il mio esempio ViewModel), c'è molto altro da guadagnare. Questo va oltre la semplice validazione. Se si esamina l'argomento relativo ai modelli di domini avanzati rispetto ai modelli di dominio anemico, il caso è che stiamo mettendo la logica che opera sui dati con i dati stessi. Questo è l'intero punto di utilizzo di un linguaggio orientato agli oggetti. Presumibilmente stai passando i dati in giro per avere qualche funzione eseguita su di esso. Serializzalo in un oggetto ricco e metti la funzione su quell'oggetto, quindi tutto ciò che devi fare è invocare la funzione. Ho toccato l'idea in un post di blog qui .

    
risposta data 21.02.2012 - 17:42
fonte
2

... why not just work with these Map (or sub-type of map) directly? You can extend Map and create your own sub-type, and you will still have all the benefit of OO programming.

Buona domanda. Perché davvero? Nei linguaggi OO dinamici (ad esempio Ruby, LUA, Javascript, Python, Perl e altri) ogni oggetto è fondamentalmente solo una mappa. È possibile aggiungere nuove proprietà e metodi agli oggetti in fase di esecuzione. È molto potente, ma si rinuncia alla validazione in fase di compilazione delle chiamate di metodo. Non è solo il modo Java.

    
risposta data 21.02.2012 - 17:40
fonte
2

Non c'è una vera ragione: puoi lavorare con le mappe hash invece delle classi e talvolta ha perfettamente senso. Tendo ad usare gli hash anziché le classi per uno dei seguenti casi:

  • Tutti i valori sono dello stesso tipo (stringa)
  • Non ho mai direttamente o individualmente referenziato i valori nel codice.
  • Strumenti (come le cose menzionate nella domanda)

Il vantaggio che una mappa ha su una classe è che è molto facile gestire genericamente un record alla volta. Una volta inseriti i valori in una classe, si tende a fare riferimento ai valori per nome, rendendo più difficile l'iterazione su di essi.

L'alternativa comune agli Hash in questo spazio problema è Java Beans. I fagioli sono una classe con proprietà e setter / getter per ogni proprietà. Alcune persone chiamano questi pojos, ma i pojos non hanno restrizioni, quindi se la tua classe è destinata ad avere solo setter & i getter chiamano un bean, non un pojo.

Sia i bean che le mappe sono esempi dei fantastici "dati stupidi" di Michael Brown, e questo è un problema separato dalla scelta di utilizzare Maps o Beans.

Ci sono due grossi problemi con "Dumb Data" di entrambi gli aromi, il primo è che hai bisogno di metadati per sapere come usarlo (ad esempio come associarlo a un controllo della GUI o al nome di una colonna di database o convalide)

Con le mappe devi risolvere il problema dei meta-dati con alcuni file di dati esterni - XML o file di configurazione o qualcosa del genere - puoi intuire molto di ciò che vuoi sapere (ad esempio assumendo il nome della colonna nelle corrispondenze DB il nome della chiave nella mappa) ma ho sempre bisogno di alcuni dati.

Con i fagioli è spuntata una soluzione accurata - annotazioni.

Un bean annotato può funzionare come una mappa poiché non si accede direttamente alle variabili per nome, si esegue semplicemente un'iterazione sui campi annotati. Anche i fagioli annotati offrono un miglioramento perché le annotazioni definiscono in linea tutti i metadati anziché richiedere una descrizione separata. Questo è il modo in cui la maggior parte degli strumenti ORM funziona attualmente, ma puoi creare e utilizzare le tue annotazioni abbastanza facilmente.

Il secondo problema è più difficile però - è che i dati sono separati dal codice - non è possibile aggiungere metodi commerciali a un HashMap o un bean. Ciò significa che non sono oggetti, sono entrambi più simili a strutture di dati. Romperanno TUTTO il tuo codice OO / design se li usi direttamente - e lo romperanno in modi davvero infetti e difficili da risolvere.

Normalmente con il codice OO non devi chiedere al tuo oggetto dati, chiedi al tuo oggetto di fare qualcosa con i suoi dati per te. Come diavolo fai questo lavoro con "dati stupidi"?

Ultimamente la mia soluzione è che qualsiasi "Dumb data" usato direttamente dal mio codice ha una classe "Helper". Appena lo tiro dal DB (o dovunque) lo incapsula nella sua classe helper e non lo espongo mai al resto della mia base di codice. qualsiasi codice che accede al bean deve passare attraverso la classe helper, qualsiasi metodo per leggere / modificare / comprendere i dati nel bean viene inserito nell'helper. Nota che non sto parlando di getter e setter: evitali laddove possibile, sono comunque casi di "Chiedere i dati dell'oggetto".

Dopo aver aggiunto questo helper, diventa ovvio dove mettere un sacco di codice che hai usato per distribuire nel resto della tua base di codice (spesso duplicato). Ora chiedi alla classe helper di fare qualcosa, interagisce con il bean per farlo.

Ho persino avuto wrapper separati che implementano la logica di business sul server e la logica / le convalide della GUI sul client, ciascuna contenente gli stessi "dati stupidi".

Penso che la distinzione più importante non sia tra Maps e Bean, sia tra Classi e Dati stupidi. Una volta che i tuoi dati stupidi sono incapsulati in una classe, la sua effettiva implementazione (Bean, Hash, ???) non è nemmeno molto interessante ...

    
risposta data 18.07.2017 - 21:01
fonte

Leggi altre domande sui tag