Domanda

Una classe TimeSheetActivity ha una raccolta di allocazioni. Un'allocazione è un oggetto valore utilizzato anche da altri oggetti nel dominio, simile a questo:

public class Allocation : ValueObject
{
    public virtual StaffMember StaffMember { get; private set; }
    public virtual TimeSheetActivity Activity { get; private set; }
    public virtual DateTime EventDate { get ... }
    public virtual TimeQuantity TimeSpent { get ... }
}

Allocazioni duplicate per la stessa Allocation.EventDate non sono consentite. Pertanto, quando un client tenta di effettuare un'allocazione a un'attività, viene eseguito un controllo per verificare se esiste già un'allocazione nella raccolta per la stessa Allocation.EventDate. In caso contrario, la nuova allocazione viene aggiunta alla raccolta, ma in tal caso, l'allocazione esistente viene sostituita da quella nuova.

Attualmente sto usando un dizionario per mantenere la raccolta, con Allocation.EventDate come chiave. Funziona bene per il dominio, ma mi chiedo se il fatto che la chiave sia già parte del valore non sia esso stesso un "cattivo odore".

Inoltre non ho motivo di persistere se non i valori del dizionario. Poiché sto usando NHibernate, potrei aver bisogno di scrivere un tipo personalizzato per farlo, e mi chiedo se anche questo sia un indizio che dovrei usare un diverso tipo di raccolta. (Questo è anche il motivo delle proprietà virtuali nella classe Allocation).

L'alternativa principale a cui sto pensando sarebbe un HashSet con un EqualityComparer dedicato.

Cosa ne pensi?

Saluti, Berryl

È stato utile?

Soluzione

Se si utilizza un comparatore esterno per eseguire un HashSet<Allocation>, si dovrebbe fare molta attenzione a non modificare la data senza digitare nuovamente il valore nel dizionario. Hai questo problema in entrambi i casi, ma è esacerbato dalla mutabilità (almeno con Dictionary<,> sarà comunque in grado di tracciare le proprie chiavi e valori). Con un valore modificabile come parte della chiave, rischi di non vederlo mai più ...

Quando in passato ho lavorato su sistemi di pianificazione, in realtà ho usato SortedList<,> per questo - simile, ma utile se desideri generalmente i dati in sequenza e consente la ricerca binaria se i dati sono abbastanza uniformi.

Altri suggerimenti

Non credo che il fatto che la chiave faccia parte del valore sia necessariamente un problema. Nella mia esperienza questo è abbastanza spesso il caso dei dizionari. Un HashSet con un comparatore di uguaglianza appropriato funzionerebbe sicuramente, purché non sia mai stato necessario raggiungere l'oggetto corrente con un particolare EventDate. Sembra una cosa utile da fare, potenzialmente ...

Al momento sei solo preoccupato in un modo un po 'vago o hai un concreto sospetto su come questo potrebbe morderti?

Usando le librerie standard, non esiste una soluzione migliore che io conosca. Tuttavia, ho anche pensato che questo tipo di codice fosse un & Quot; cattivo odore & Quot ;, ma è a causa delle classi di raccolta nel BCL e non del tuo codice.

Non so perché MS non abbia creato insiemi generici <TKey, TData> where TData: IKeyed<TKey> o giù di lì invece di dizionari, perché ciò consentirebbe l'implementazione di tali strutture di dati in cui la chiave fa parte dei dati. KeyValuePair<TKey, TValue>: IKeyed<TKey> sarebbe solo una struttura di supporto che implementa questa interfaccia e consente quindi di creare funzionalità di dizionario identiche a quelle che abbiamo ora.

Inoltre (per continuare con il piccolo rant) mi chiedo perché non abbiano aggiunto la nozione di tipi immutabili dichiarativi e rendere questo un possibile vincolo di tipo generico, perché ciò consentirebbe di assicurarsi che una chiave non cambi il suo codice hash durante il runtime (che può accadere attualmente se si implementano GetHashCode() e Equals() su alcuni oggetti mutabili).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top