Perché l’API della data Java (java.util.Date, .Calendar) è un tale casino?

Come ormai la maggior parte delle persone è dolorosamente consapevole, l’API Java per gestire le date del calendario (in particolare le classi java.util.Date e java.util.Calendar ) sono un pasticcio terribile.

Fuori dalla mia testa:

  • La data è mutabile
  • La data rappresenta un timestamp, non una data
  • nessun modo semplice per convertire tra i componenti della data (giorno, mese, anno …) e Data
  • Il calendario è goffo da usare e cerca di combinare diversi sistemi di calendario in un’unica class

Questo post lo riassume abbastanza bene, e JSR-310 espande anche questi problemi.

Ora la mia domanda è:

In che modo queste classi sono entrate nell’SDK Java? La maggior parte di questi problemi sembra abbastanza ovvia (in particolare Data è mutevole) e avrebbe dovuto essere facile da evitare. Quindi come è successo? Pressione del tempo? O i problemi sono evidenti solo a posteriori?

Mi rendo conto che questa non è propriamente una domanda di programmazione, ma troverei interessante capire come il design dell’API potrebbe andare così male. Dopotutto, gli errori sono sempre una buona opportunità di apprendimento (e sono curioso).

Qualcuno lo ha messo meglio di quanto potrei mai dire:

  • Class Date rappresenta un istante specifico nel tempo, con precisione millisecondo. Il design di questa class è uno scherzo molto brutto – un esempio deludente di come anche i bravi programmatori falliscono. La maggior parte dei metodi in Date sono ora deprecati, sostituiti da metodi nelle classi sottostanti.
  • Class Calendar è una class astratta per la conversione tra un object Date e un insieme di campi interi come anno, mese, giorno e ora.

  • Classe GregorianCalendar è l’unica sottoclass di Calendar nel JDK. Effettua le conversioni Date-to-fields per il sistema del calendario in uso comune. Sun ha concesso in licenza questa spazzatura ipersensibile di Taligent – un esempio che fa riflettere su come i programmatori medi falliscono.

da Java Programmers FAQ , versione 07.X.1998, di Peter van der Linden – questa parte è stata rimossa dalle versioni successive.

Per quanto riguarda la mutabilità, molte delle prime classi JDK ne soffrono ( Point , Rectangle , Dimension , …). Ottimizzazioni errate, ne ho sentito dire qualcuno.

L’idea è di voler riusare oggetti ( o.getPosition().x += 5 ) piuttosto che creare copie ( o.setPosition(o.getPosition().add(5, 0)) ) come hai fare con immutables. Potrebbe anche essere stata una buona idea con le prime VM, mentre molto probabilmente non è con le VM moderne.

Le prime API di Java non sono altro che un prodotto del loro tempo. L’immutabilità divenne solo un concetto popolare anni dopo. Tu dici che l’immutabilità è “ovvia”. Potrebbe essere vero ora ma non lo era allora. Proprio come l’iniezione di dipendenza è ora “ovvia” ma non è stata 10 anni fa.

È stato anche un tempo costoso creare oggetti Calendar.

Rimangono in questo modo per ragioni di compatibilità all’indietro. Ciò che è forse più sfortunato è stato il fatto che una volta che l’errore è stato realizzato la vecchia class non è stata deprecata e sono state create nuove classi data / ora per tutte le API in futuro. Questo si è in qualche misura verificato con l’adozione di JDK 8 di un’API JodaTime like ( java.time , JSR 310) ma in realtà è troppo poco tardi.

Il tempo non è di per sé facile da misurare e da gestire. Basta guardare la lunghezza dell’articolo su Wikipedia di tempo . E poi, ci sono diverse comprensioni sul tempo stesso: un punto temporale absoulte (come costante), un punto temporale in un certo punto, un intervallo di tempo, la risoluzione del tempo ….

Ricordo quando ho visto java.util.Date la prima volta (JDK 1.0?) Ne sono stato davvero contento. Le lingue che conoscevo non avevano questa caratteristica. Non avevo pensato alla conversione temporale ecc.

Penso che sia un casino, perché tutto ciò che cambia lascia un casino se evolvi da un livello di comprensione (XMLGregorianCaldender vs. Date) e requisiti (Nanoseconds, passato 2030) a un livello superiore, ma mantenendo il vecchio intatto. E java.util.Date non è un’eccezione. Basta guardare il sottosistema I / O o la transizione da AWT a Swing …

E a causa di ciò, “a volte dovremmo premere il pulsante di reset.” (chi l’ha detto, btw?)

Potresti trovare il seguente post interessante. In sostanza, spiega in primo luogo come la class di Calendar è entrata nell’API Java, e fa luce sulle origini della class data.

Le sette abitudini del design altamente disfunzionale