Il modo migliore per gestire le date vuote

3

Sto provando a creare un'applicazione per i contatti e attualmente sto lavorando a una classe chiamata Persona. Uno dei campi di persona è dateObBirth, tuttavia non so come gestire date sconosciute. Fino ad ora ho usato java.time.LocalDate per dateOfBirth e ho inizializzato il campo in null alla istanziazione. Questo non è l'ideale, perché quando si tenta di confrontare dateOfBirth con altre date come LocalDate.now ().

Quale sarebbe il modo migliore per gestire dateOfBirth? Dovrei semplicemente creare una classe completamente nuova e gestire internamente date sconosciute? O c'è un modo migliore per farlo. Stavo solo estendendo LocalDate ma è immutabile, quindi non può essere esteso senza andare alla fonte.

    
posta Helios 13.06.2015 - 11:14
fonte

4 risposte

8

Utilizza la classe Optional<LocalDate>

Questa classe contenitore utile è stata introdotta in Java 8. È un wrapper utilizzato per valori che potresti o non potresti conoscere. È unboxed con vari metodi che ti consentono di gestire il caso in cui il valore è sconosciuto in modo aggraziato.

  • get() disattiva il LocalDate, ma genera un NoSuchElementException nel caso in cui non ne hai nessuno. Sfortunatamente è un'eccezione non controllata, proprio come il temuto NullPointerException . Quindi consiglierei di evitare l'uso di questo metodo e utilizzare invece:
  • orElseThrow(exception) che genera detta eccezione quando non si ha un valore. L'eccezione può (e dovrebbe essere) un'eccezione controllata in modo da essere costretta a gestirla. Non hai voglia di scrivere un costrutto rozzo try...catch... ? In tal caso:
  • ifPresent(Consumer<? super T> consumer) è un costrutto utile quando vuoi eseguire del codice solo se hai un valore e altrimenti non fare nulla.
  • orElse(T value) cancella il valore ma ti fornisce il valore fittizio che fornisci quando non ne hai nessuno

Per ulteriori informazioni, consultare l'articolo "Stanco delle eccezioni dei puntatori nulli? Prendere in considerazione l'utilizzo di Java SE 8's Opzionale! " su Oracle Tech Net e la documentazione per vedere quali altri metodi fornisce.

Non si sta ancora utilizzando Java 8?

Quando usi ancora una versione precedente di Java, potresti facilmente improvvisare la tua classe OptionalDate , che ha solo:

  • private LocalDate
  • public void set(LocalDate value) e
  • public LocalDate get() throws DateUnknownException

Se il getter lancia un'eccezione controllata, sei costretto a gestire sempre il caso null.

    
risposta data 13.06.2015 - 11:45
fonte
1

Tony Hoare si dice che abbia inventato, ciò che ora chiamiamo null . E se ne pentì:

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years

Fonte: wikipedia .

Ora dobbiamo vivere e affrontarlo.

however I don't know how to handle unknown dates.

Fidati, non sei solo.

Il problema è che c'è qualcosa che chiamerei ambiguità delle informazioni . Chiedere » quando è stata la battaglia di waterloo? « nella vita di tutti i giorni » I do not know « è una risposta accettata. Ma non è la risposta su la data stessa , riguarda la conoscenza dell'altoparlante .

Per il tuo problema: chiedere person.getBirthDate() ti dà una risposta ambigua :

  • o era il 1952-11-02

  • o l'equivalente di non so , che è null .

Qual è una soluzione adeguata a quella miseria di ambiguità ?

Dato che abbiamo null e poiché è ampiamente accettato in datastore , dovresti usare null come risposta corretta nel contesto del DB.

Ma per quanto riguarda il tuo programma:

Come hai detto correttamente

because it's resulting in null pointer exceptions when I try to compare dateOfBirth to other dates such as the LocalDate.now()

Devi custodire contro questo in un modo o nell'altro:

1) Potresti introdurre un getter person.birthdayKnown() per fare quanto segue:

if (personA.birthdayKnown() && personA.birthdayKnown()) // allow further operations

2) Con l'avvento di Java8, potresti renderlo un Facoltativo e funziona con isPresent() .

    
risposta data 13.06.2015 - 11:42
fonte
0

Come ha detto @Philipp, Opzionale è una buona risposta a questo problema. Tuttavia, richiede Java 8 (anche se è possibile implementarlo da soli) e questo tipo di struttura è in genere adattato allo stile di programmazione funzionale e potrebbe quindi sembrare strano in un sistema orientato agli oggetti.

Un'alternativa OOP tipica è Null Object. Vedi ad esempio la mia risposta su questo altro post . Ti consente di definire un "comportamento predefinito" quando l'oggetto non è impostato, che è ciò che desideri.

    
risposta data 13.06.2015 - 19:48
fonte
0

Le tue opzioni sono:

1) Usa null . Quindi non dimenticare di controllare null. Annotazioni @NotNull e @Nullable (e simili) ti aiuteranno a evitare NullPointerException.

2) Usa Optional . Questo è come essere costretti a controllare per nulla. Ma aggiunge alcuni overhead e altri riferimenti indiretti.

3) Usa il pattern DefaultObject: crea un static final LocalDate DEFAULT come predefinito. Non mi piace, poiché in seguito è facile dimenticare che non hai una data reale nota.

4) Usa il pattern NullObject: crea la tua classe che avvolgerà un java.time.LocalDate, e poi, invece di null, definisci e usa coerentemente: static final MyLocalDate UNKNOWN

5) Utilizzare una classe di utilità per confrontare sempre o elaborare le date. Quindi, invece di date1.foo(date2) dovresti usare UtilDates.foo(date1, date2) . Il metodo foo dovrebbe accettare valori nulli.

Ma prima di scegliere una di queste opzioni devi decidere cosa fare quando non conosci la data. Ad esempio, quando si controlla se qualcuno ha più di 21 anni, ma dateOfBirth è sconosciuto, cosa vuoi fare? Vuoi sempre presumere che la persona abbia più di 21 anni? O sempre più giovane di 21? Vuoi emettere un avviso e interrompere l'operazione corrente, costringendo l'utente a inserire una data? A seconda di ciò che vuoi fare, ognuna delle opzioni di cui sopra ha vantaggi e svantaggi.

Ce n'è un altro, forse non un'opzione nel tuo caso, ma:

6) Forzare l'utente a scegliere una data valida (vale a dire, non consentire i valori null) quando Persona viene istanziata / salvata.

    
risposta data 14.06.2015 - 10:10
fonte

Leggi altre domande sui tag