This is related to my recent question regarding naming awkward domain objects. A number of answers indicated I was using the wrong representation for the domain objects. To summarize, I chose to use an enum to represent some domain objects used as keys in lookups.
For this question, I want to review my decision to use an enum and identify alternatives. Jump to the bottom of my question for the TL;DR.
Domain Description
My application is responsible for performing some calculations involving chemical compounds.
Some basic equations are:
- calculating the number of moles of a compound
- calculating the specific gravity or density of a compound at various concentrations
These equations could be handled as methods within a Chemical
class like:
Chemical.GetMolesFromMass(double mass_grams)
or
Chemical.GetDensity(double concentration)
or they could be implemented as methods off of a generic chemical properties class like:
Chemical.GetMolesFromMass(Compound cmpd, double mass_grams)
or
Chemical.GetDensity(Compound cmpd, double concentration)
I think from an object responsibility point of view, the first option of methods off of the Chemical
class would be a better representation.
Some advanced equations involve:
- calculating quantities of a compound consumed by a business process
- calculating storage requirements of compounds
- optimizing deliveries based upon standard container sizes
In these equations, the chemical compound is an input to the method.
StorageTankCluster.Generate(Compound cmpd, double requiredVolume)
The StorageTankCluster
needs to know about the chemical because the dimensions and spacing of the tanks within the cluster will change based upon the chemical and required volume. The chemical being stored can affect tank material selection as well as impacting safety clearances between tanks.
At the moment, I'm considering those parameters (spacing, material, ...) as lookup items instead of elements that the compound is responsible for knowing about.
Likewise, the delivery optimization as affected by the chemical compound but it's arguable on whether or not those aspects are the compound's responsiblity.
Both the StorageTankCluster
and the delivery optimization components are intended to be reused by other non-chemical aspects of the application. As this question is already getting complicated, we can just call those other elements Foo
and Bar
. Both Foo
and Bar
could utilize the delivery optimization, but only Foo
can be used with the StorageTankCluster
.
It's not in the application now, but all of the various properties discussed so far will need to be stored within a database / persistence layer. I realize that shouldn't affect a good design, but I thought it was worth mentioning.
I'll admit that some of my decisions have been biased because I'm porting this application from another source that forces everything to be done in a structured manner. Writing out this question has highlighted a few areas where I should have better examined what object had responsibility for that functionality.
My design so far has been oriented around lookup tables and I'm using the enum values as the keys to those tables. It is their use as keys that causes me to treat them as named objects within the program instead of treating them as objects the system would operate upon. This has pretty much relegated the chemical compounds to 2nd-tier class status, and I'm wondering if that was the right decision. On the other hand, I'm concerned about the chemical compound class becoming bloated beyond usefulness.
TL;DR
My implementation is / must be in C#. So was using an enum the right choice, or what should I have done and why?