Rappresenta oggetti di dominio

3

Questo è legato alla mia domanda recente riguardante la denominazione di oggetti di dominio awkward. Un numero di risposte indicava che stavo usando la rappresentazione errata per gli oggetti del dominio. Per riassumere, ho scelto di utilizzare un enum per rappresentare alcuni oggetti di dominio utilizzati come chiavi nelle ricerche.

Per questa domanda, voglio rivedere la mia decisione di usare un enum e identificare alternative. Vai alla fine della mia domanda per il TL; DR.

Descrizione del dominio
La mia applicazione è responsabile dell'esecuzione di alcuni calcoli che riguardano composti chimici.

Alcune equazioni di base sono:

  • calcolo del numero di moli di un composto
  • calcolo del peso specifico o della densità di un composto a varie concentrazioni

Queste equazioni potrebbero essere gestite come metodi all'interno di una classe Chemical come:
Chemical.GetMolesFromMass(double mass_grams) o
Chemical.GetDensity(double concentration)
oppure potrebbero essere implementati come metodi fuori da una classe di proprietà chimiche generiche come:
Chemical.GetMolesFromMass(Compound cmpd, double mass_grams) o
Chemical.GetDensity(Compound cmpd, double concentration)

Penso che dal punto di vista della responsabilità degli oggetti, la prima opzione di metodi fuori dalla classe Chemical sarebbe una rappresentazione migliore.

Alcune equazioni avanzate riguardano:

  • calcolo delle quantità di un composto consumato da un processo aziendale
  • calcolo dei requisiti di memoria dei composti
  • ottimizzazione delle consegne in base alle dimensioni standard dei contenitori

In queste equazioni, il composto chimico è un input per il metodo.
StorageTankCluster.Generate(Compound cmpd, double requiredVolume)

Il StorageTankCluster deve conoscere la sostanza chimica perché le dimensioni e la spaziatura dei serbatoi all'interno del cluster cambieranno in base al volume chimico e richiesto. La sostanza chimica immagazzinata può influire sulla scelta del materiale del serbatoio e sull'impatto delle distanze di sicurezza tra i serbatoi.

Al momento, sto considerando quei parametri (spaziatura, materiale, ...) come elementi di ricerca invece di elementi di cui il composto è responsabile per la conoscenza.

Allo stesso modo, l'ottimizzazione della consegna è influenzata dal composto chimico, ma è discutibile sul fatto che tali aspetti siano o meno la responsabilità del composto.

Sia il StorageTankCluster che i componenti di ottimizzazione della consegna sono destinati ad essere riutilizzati da altri aspetti non chimici dell'applicazione. Poiché questa domanda si sta già complicando, possiamo semplicemente chiamare quegli altri elementi Foo e Bar . Sia Foo che Bar potrebbero utilizzare l'ottimizzazione della pubblicazione, ma solo Foo può essere utilizzato con StorageTankCluster .

Non è nell'applicazione ora, ma tutte le varie proprietà discusse finora dovranno essere archiviate all'interno di un database / livello di persistenza. Mi rendo conto che non dovrebbe influire su un buon design, ma ho pensato che fosse degno di nota.

Ammetto che alcune delle mie decisioni sono state distorte perché sto trasferendo questa applicazione da un'altra fonte che forza tutto in modo strutturato. Scrivere questa domanda ha evidenziato alcune aree in cui avrei dovuto esaminare meglio quale oggetto aveva la responsabilità di tale funzionalità.

Il mio progetto finora è stato orientato intorno alle tabelle di ricerca e sto usando i valori enum come chiavi per quelle tabelle. È il loro uso come chiavi che mi induce a trattarli come oggetti con nome all'interno del programma invece di trattarli come oggetti su cui il sistema opererebbe. Questo ha praticamente relegato i composti chimici allo status di classe di secondo livello, e mi chiedo se sia stata la decisione giusta. D'altra parte, sono preoccupato per la classe dei composti chimici che diventa gonfia oltre l'utilità.

TL; DR
La mia implementazione è / deve essere in C #. Quindi usare un enum è la scelta giusta, o cosa avrei dovuto fare e perché?

    
posta GlenH7 21.12.2012 - 20:21
fonte

1 risposta

1

Vogliamo codice per essere il più semplice possibile. Non vogliamo che ingombra la conoscenza del dominio che il programmatore non dovrebbe aver bisogno di sapere. Pertanto, quando possibile, vogliamo evitare di inserire nel codice qualcosa di specifico come prodotti chimici. Ecco perché pensiamo che inserire prodotti chimici come enum nel tuo codice sia probabilmente una cattiva idea se non dimostrato diversamente.

Come caso simile, considera un sistema di registrazione del corso. Non vorresti che il codice contenga riferimenti a vari corsi che le persone dovrebbero prendere. CSI101 potrebbe essere "Introduzione alla grafica per computer", ma non dovrebbe essere incluso nel codice. Quella informazione dovrebbe essere solo in una riga del database per il corso. Il codice del sistema di registrazione del corso tratta tutte le classi allo stesso modo, forse considerando solo le proprietà del corso come nome, prerequisiti, ore di credito, ecc.

Quindi la prima domanda è se effettivamente hai bisogno di avere riferimenti ai vari composti chimici nel tuo codice. Questo è indipendente dal fatto che tu stia usando o meno le tabelle di ricerca. Chemical.GetDensity(Compound cmpd, double concentration) può funzionare allo stesso modo se Compound è un enum, oggetto, stringa o int. StorageTankCluster.Generate(Compound cmpd, double requiredVolume) , è lo stesso, la funzione funziona allo stesso modo indipendentemente dal fatto che i composti siano effettivamente denominati entità nel codice. Nessuna di queste cose richiede in remoto di fare riferimento a composti nel codice.

Ovviamente, da qualche parte devi specificare quale composto viene considerato. Non può sempre essere un parametro per la tua funzione. È la natura di tale specifica che determina se è necessario o meno avere riferimenti alle sostanze chimiche nel codice. Le tue affermazioni sembrano indicare che il processo aziendale determina quali composti devono essere considerati. Considero che il processo aziendale è scritto in codice, ed è per questo che è necessario fare riferimento ai composti chimici nel codice. Ma la domanda è se il processo aziendale debba davvero essere implementato nel codice.

Per vedere cosa intendo, guardiamo indietro alla registrazione del corso. Supponiamo che tu abbia una classe con regole complicate per decidere se puoi prenderla.

boolean CSI250::MayTake(Student student)
{
    // if the student has special permission, he can always take the course
    if( student.HasOverrideForCourse("CSI250") ) return true;

    // Student must have taken 101 first
    if( !student.HasTaken("CSI101") ) return false;

    // Student must have at least a B in CSI 101
    if( student.GetGrade("CSI101") < Grades.B) return false

    // Student must have taken either CSI150 or CSI201
    if( !student.HasTaken("CSI150") || !student.HasTaken("CSI201") ) return false;

    return true;
}

Se ho capito bene, hai bisogno di un enumerico perché ti stai riferendo a vari prodotti chimici nel tuo processo come ho fatto per i corsi di cui sopra. (Ho usato le stringhe, ma avrei potuto fare anche enumerazioni.) Ma il codice di cui sopra non sarebbe una buona idea, perché mette troppe informazioni sul dominio nel processo. Sarà un dolore mantenerlo come i poteri che si adattano e regolano le cose. Quindi quello che preferiremmo fare è memorizzare le informazioni dei prerequisiti nel database, ad esempio:

Course   Prereq    Grade Required   Alternate    Grade Required
CSI250   CSI101    B
CSI250   CSI150    D                CSI200       B

Ora le informazioni sui prerequisiti vengono spostate dal codice nel database. Può essere manipolato dall'amministrazione, il codice è più semplice, ecc. La domanda è se si può fare lo stesso per i processi aziendali. Ci sono molti benefici da ottenere spostando qualcosa del genere dal codice in dati. Forse non puoi, ma è quello che mi piacerebbe fare.

Probabilmente eviterei enum anche se devi inserire queste entità nel codice. enum s sono abbastanza stupidi. Penso che sarebbe meglio poter dire: Chemicals.SodiumPhosphate.GetMolesFromMass(1000) che dire GetMolesFromMass(Chemicals.SodiumPhosphate, 1000) . Ti dà anche flessibilità futura perché il metodo può fare tutto ciò che vuole. Può utilizzare una tabella di ricerca o memorizzare i dati all'interno o qualsiasi altra cosa.

    
risposta data 22.12.2012 - 01:28
fonte

Leggi altre domande sui tag