Questa domanda è in realtà una serie di problemi con il modello di dati raggruppati in uno. Devi iniziare a districarli, uno alla volta. Soluzioni più naturali e intuitive cadranno mentre provi a semplificare ogni pezzo del puzzle.
Problema 1: non è possibile dipendere dall'ordine DB
Le descrizioni dell'ordinamento dei dati non sono chiare.
- Il potenziale problema più grande è che non stai specificando un ordinamento esplicito nel tuo database, tramite una
ORDER BY
clausola. Se non lo sei perché sembra troppo costoso, il tuo programma ha un bug . I database possono restituire risultati in qualsiasi ordine se non ne specifichi uno; non puoi dipendere dal fatto che i dati vengano restituiti casualmente nell'ordine solo perché hai eseguito la query più volte e sembra così. L'ordine potrebbe cambiare perché le righe vengono riorganizzate sul disco o alcune vengono eliminate e ne vengono sostituite di nuove o viene aggiunto un indice. È necessario specificare una ORDER BY
clausola di qualche tipo. La velocità è inutile senza correttezza.
- Inoltre, non è chiaro cosa si intende per ordine di inserzione importante. Se si parla del database stesso, è necessario disporre di una colonna che effettivamente tiene traccia di questo, e deve essere incluso nella
ORDER BY
clausola. Altrimenti, hai dei bug. Se tale colonna non esiste ancora, è necessario aggiungerne una. Le opzioni tipiche per colonne come questa sarebbero una colonna data / ora di inserimento o una chiave auto-incrementante. La chiave auto-incrementante è più affidabile.
Problema 2: rendere efficiente l'ordinamento in memoria
Una volta che hai la certezza che è garantito per essere la restituzione di dati nell'ordine che ci si aspetta, è possibile sfruttare questo fatto per fare in memoria comando ordina molto più efficiente. Basta aggiungere una colonna row_number()
odense_rank()
(o equivalente del database) al set di risultati della query. Ora ogni riga ha un indice che ti darà un'indicazione diretta di ciò che dovrebbe essere l'ordine, e puoi ordinarlo banalmente in memoria. Assicurati solo di dare all'indice un nome significativo (come sortedBySomethingIndex
).
Viola. Ora non è più necessario dipendere dall'ordine del set di risultati del database.
Problema 3: hai anche bisogno di eseguire questa elaborazione nel codice?
SQL è in realtà molto potente. È un fantastico linguaggio dichiarativo che ti consente di fare molte trasformazioni e aggregazioni sui tuoi dati. Oggigiorno la maggior parte dei DB supporta anche operazioni a file incrociate. Si chiamano funzioni finestra o analitiche:
Hai anche bisogno di mettere i tuoi dati in memoria in questo modo? O potresti fare tutto il lavoro nella query SQL usando le funzioni della finestra? Se riesci a fare tutto (o forse anche solo una parte significativa) del lavoro nel DB, fantastico! Il tuo problema con il codice scompare (o diventa molto più semplice)!
Problema 4: stai facendo cosa data
?
Supponendo che non puoi fare tutto nel DB, fammi capire bene. Stai prendendo i dati come mappa (che è chiave per cose che non vuoi ordinare), quindi stai iterando su di esso in ordine di inserimento , e modificando la mappa in atto sostituendo il valore di alcune chiavi e aggiungendo nuovi?
Mi dispiace, ma che diamine?
I chiamanti non dovrebbero preoccuparsi di tutto questo . Il sistema che hai creato è estremamente fragile. Ci vuole solo un errore stupido (forse anche fatto da te, come abbiamo fatto tutti) per fare un piccolo cambiamento sbagliato e il tutto collassa come un mazzo di carte.
Ecco forse un'idea migliore:
- Chiedi alla tua funzione di accettare a
List
.
- Esistono un paio di modi in cui è possibile gestire il problema di ordinazione.
- Applica Fail Fast. Generare un errore se l'elenco non è nell'ordine richiesto dalla funzione. (Nota: è possibile utilizzare l'indice di ordinamento dal Problema 2 per sapere se lo è.)
- Crea tu stesso una copia ordinata (usando nuovamente l'indice dal problema 2).
- Scopri un modo per costruire la mappa stessa in ordine.
- Costruisci la mappa di cui hai bisogno internamente alla funzione, in modo che il chiamante non debba preoccuparsene.
- Ora ripeti tutto ciò che hai in ordine di rappresentazione e fai quello che devi fare.
- Restituisci la mappa o trasformala in un valore di ritorno appropriato
Una possibile variazione potrebbe essere quella di costruire una rappresentazione ordinata e quindi creare una mappa della chiave da indicizzare . Ciò ti consentirebbe di modificare la copia ordinata in atto, senza creare accidentalmente duplicati.
O forse questo ha più senso: sbarazzarsi del data
parametro e far processData
effettivamente recuperare i propri dati. Puoi quindi documentare che lo stai facendo perché ha requisiti molto specifici sul modo in cui i dati vengono recuperati. In altre parole, rendere la funzione proprietaria dell'intero processo, non solo di un suo pezzo; le interdipendenze sono troppo forti per dividere la logica in blocchi più piccoli. (Cambia il nome della funzione nel processo.)
Forse questi non funzioneranno per la tua situazione. Non lo so senza tutti i dettagli del problema. Ma conosco un design fragile e confuso quando ne sento uno.
Sommario
Penso che il problema qui sia in definitiva che il diavolo sta nei dettagli. Quando inizio a incorrere in problemi come questo, di solito è perché ho una rappresentazione inappropriata dei miei dati per il problema che sto cercando di risolvere effettivamente. La soluzione migliore è trovare una rappresentazione migliore , e quindi il mio problema diventa semplice (forse non facile, ma diretto) da risolvere.
Trova qualcuno che capisca questo punto: il tuo compito è ridurre il tuo problema a un insieme di semplici e chiari. Quindi puoi creare un codice robusto e intuitivo. Parla con loro. Un buon codice e un buon design ti fanno pensare che qualsiasi idiota avrebbe potuto pensarli, perché sono semplici e diretti. Forse c'è uno sviluppatore senior che ha quella mentalità con cui puoi parlare.