lunedì 15 luglio 2019

Java Reflection e CSV

Cosa sono le reflection? Sono sostanzialmente un modo per ottenere tutti i nomi dei metodi, ed eventualmente invocarli, senza sapere quali siano questi metodi. Tutti sanno da codice invocare il metodo "getPippo()" di una certa classe scrivendolo da codice, ed e' quello si fa praticamente di normale. Pero' ci sono delle situazioni per le quali non sai il nome dei metodi da invocare (oppure non li vuoi sapere perche' sono centinaia e devi invocarli tutti).

Java ci mette a disposizione uno strumento potentissimo (se usato bene): le reflections. E' possibile da un oggetto Classe ottenere i nomi dei suoi metodi (come oggetto Method). Tramite questi nomi, e' possibile invocarli per esempio, ma e' necessaria un'istanza di quella classe (ovviamente). E' anche possibile passare argomenti.

Il caso che tratteremo qui e' la generazione di un csv. Il caso che mi ha spinto a creare una classe generica e non una ad hoc e' che la tabella (e quindi l'entity) della quale devo generare il csv ha una pletora di campi (2 o 300 tipo) per cui la decisione era:

  • spendo 2h a fare un csv con possibilita' altissima di sbagliare (visto l'elevato nr. di campi)
  • spendo 10min a farlo con una reflection con la possibilita' poi di usarlo per tutto?

La domanda e' semiretorica anche perche' se non avessi scelto la seconda opzione non sarei qui a scrivere questo articolo. Per arrivarci pero' devo fare un po' di premesse:

La prima e' un metodo "generico" che formatta un oggetto usando istanceof (e restituisce una stringa) controllando pure se e' null o not. Se l'oggetto che mi passo in input e' null restituisco stringa vuota (questo perche' in un csv devi comunque mettere un ; se vuoi un campo vuoto).



Poi ci serve (o almeno a ME!!!) un metodo per convertire il camel case in stringa "normale" - questo perche' uso i nomi dei metodi come nomi di colonne (non vorrai mica fare un csv senza intestazione). Ma questo si fa facile - StringUtils di apache ci viene incontro con splitByCharacterTypeCamelCase il cui risultato passeremo al metodo join sempre di StringUtils (non metto screen abbiate pazienza).

Fatto questo io mi sono fatto un metodo di utilita' che data una classe restituisce tutti i suoi getters (escluso getClass che nel csv non serve)

Poi ci serve un metodo di utilita' che restituisca una stringa csv di una certa istanza (generica). Ho usato i generics perche' voglio potergli passare di tutto. Come si puo' notare per invocare un metodo tramite reflection si invoca il metodo invoke passandogli un'istanza che e' quella sulla quale il metodo verra' eseguito il risultato e' un object. Mi passo anche il separator (perche' voglio essere flessibile).

Come si puo' vedere viene invocato il metodo "formattatore" generico presentato all'inizio, questo evita che nella stringa ci sia il toString degli oggetti (che non e' molto human readable). Inoltre, sempre questo metodo, evita che ci siano dei campi sfalsati nel csv (dovuto alla presenza di campi null).

Vi risparmio la parte di scrittura su file perche' non interessante ai fini di questo articolo.

Alla prossima!

mercoledì 12 giugno 2019

Java get or else get


Quando si ha una lista in mano in Java 1.8 lo stream e' uno strumento molto potente, puo' essere usato per un fracco di cose tra cui la trasformazione della lista in qualcos'altro. Per evitare al programmatroto una .get(0) per prendere il primo (o uno qualsiasi) della lista sempre lo stream ti viene incontro con i metodi findFirst e findAny. La differenza? Il primo ti garantisce che l'elemento sia sempre quello.

Ovviamente suddetti metodi restituisco un Optional - a questo punto avete un po' di possibilita' davanti:

  1. Ve ne battete allegramente e fate la get che c'e' c'e' (non devo dirvi perche' non e' una buona idea)
  2. Fate un ifPresent e nel caso fate la get ma son righe in piu' di codice. Che scherzi?
  3. Invocate uno dei due metodi che sono l'oggetto di questo post

Qual'e' la differenza? orElse restituisce direttamente l'oggetto passato come parametro. Quindi potete tranquillamente passare null. orElseGet (come dice il nome) fa la get su quello che gli passate (quindi dev'essere un Supplier) e non devo dirvi (di nuovo) perche' non e' una buona idea passare null.

Se invece volete lanciare un'eccezione c'e' orElseThrow




Se non sapete cosa c'incastri l'immagine con il post andatevi a cercare cosa vuol dire "stream" in Inglese


giovedì 13 dicembre 2018

Dateception


Oggi mi sono imbattuto in questo esempio di fulgida programmazione. Ho censurato le parti "sensibili" (che potrebbero fare capire da dove proviene) e numerato i punti per facilitarvi la comprensione.

  1. Inizializza una stringa con una data di default
  2. Inizializza un oggetto date ad oggi
  3. Formatta la data odierna come stringa (e la mette nella stringa di prima)
  4. Riparsa la stringa per ritrasformarla in data
  5. Salva e Persiste l'oggetto

Ma seriamente?
Prima di tutto: che senso ha inizializzare una stringa con una data di default se poi non la usi.
Poi convertire una data in stringa e riconvertirla in data. Passare direttamente la data no eh? Troppo facile...
save => salva l'oggetto (nuovo) quindi se gia' esiste va in eccezione.
persist => si gestisce il fatto che l'oggetto possa esistere (equivalente di saveOrUpdate).

Che dire? Nulla ho finito le parole...

I nostri valori


Ecco a voi un estratto da "Metello" di Vasco Pratolini. I motivi per i quali Ida viene considerata una buona ragazza...

martedì 23 ottobre 2018

Il router introverso


E via che si va. Correva l'anno... No l'anno non lo so era tra il 2008 e il 2010 e ancora lavoravo come tecnico informatico (prima di passare al lato oscuro del software). Arrivo' l'allora capo con un router che non riconosceva la password di amministratore per accedere alle impostazioni del router.

Primo pensiero: l'avranno cambiata e non se la ricordano (anche se dicono di no). Lo resetto. Effettuo il reset, attendo che il router mi confermi di essere resettato, vado sul manuale mi leggo quali sono le password di default e...

...non funzionano...

Non e' che il produttore l'ha aggiornato e si e' scordato di aggiornare il manuale? Prova tutte le combinazioni di password note con l'utente "admin".
Niente.

Rileggi il manuale e cerca online. Tutti riportano "admin" come username e "admin" come password.
Forse non mi ha preso il reset.
Ri-reset.
Nada.

Mi viene in mente una cosa: il produttore e' straniero e il manuale e' in italiano e guarda caso "admin" e' la traduzione di "root".
Non e' che...

Si era che. Il fenomeno che ha tradotto in italiano il manuale ha tradotto anche username e password...

venerdì 5 ottobre 2018

Repubblica e gli airbag


Mi sono imbattuto in questo articolo di repubblica in cui si sostiene che gli airbag siano obbligatori da almeno 30 anni.

Siccome me la ricordavo un pelino diversa sono andato a verificare... Il primo articolo che ho trovato e' dell'aci che spiega in maniera molto stringata come gli airbag non siano obbligatori. Forse troppo stringata.

Poi mi imbatto in questo da cui si ricavano un po' piu' di informazioni. Tipo che l'airbag e' obbligatorio per rispettare nel le normative Euro ma solo dal 2002 mentre non lo e' per le altre (quelle che sono state immatricolate senza). Per cui in un certo senso ha ragione l'ACI.
L'articolo pero' aggiunge un'informazione su quando e' stato il primo collaudo degli airbag e sulla cifra, almeno, Repubblica ci ha preso...

mercoledì 3 ottobre 2018

Antibufala iperfast: scafisti per necessita scarcerati

Aggiustero' l'articolo forse dopo.
Comunque ipervelocemente: basta leggere le motivazioni della sentenza.

L'articolo e' qui.

Gli imputati si sarebbero messi alla guida delle imbarcazioni per scappare dall'inferno dei lager dov'erano rinchiusi in Libia.  

I tizi scarcerati non erano scafisti. Erano gente normale che ha guidato il gommone per sfuggire dalla Libia.


Praticamente degli scafisti per caso (scusate non ho resistito a fare la battuta anni '90)...