Representing domain objects

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?

We want to code to be as simple as possible. We don’t want it cluttered up with domain knowledge that the programmer shouldn’t need to know. Thus, whenever possible, we want to avoid putting something as domain specific as chemical products into the code. That’s why we think that putting chemical products as an enum into your code is probably a bad idea unless proven otherwise.

As a similar case, consider a course registration system. You wouldn’t want the code to contain any references to various courses that people should be taking. CSI101 may be “Introduction to Computer Graphics”, but that should not be in the code at all. That information should only be in a database row for the course. The course registration system code treats all classes the same, only perhaps considering properties of the course such as name, prerequisites, credit hours, etc.

So the first question is whether you actually need to have references to the various chemical compounds in your code. This is independent of whether or not you are using lookup tables. Chemical.GetDensity(Compound cmpd, double concentration) can work just the same whether Compound is a enum, object, string, or int. StorageTankCluster.Generate(Compound cmpd, double requiredVolume), is the same, the function works the same whether or not the Compounds are actually named entities in the code. None of these things remotely require you to reference compounds in your code.

Of course, somewhere you have to specify which compound is being considered. It can’t always be a parameter to your function. It is the nature of that specification that determines whether or not you need to have reference to the chemicals in your code. Your statements seem to indicate that the business process determines which compounds need to be considered. I gather that the business process is written into code, and that’s why you need to refer the chemical compounds in code. But the question is whether the business process really needs to be implemented in code.

To see what I mean, lets look back at the course registration. Suppose that you’ve got a class with a complicated rules for whether you are allowed to take it.

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;
}

If I understand correctly, you need an enum because you are referring to various chemical products in your process like I’ve done for courses above. (I’ve used strings, but I could have done enums just as well.) But the above code wouldn’t be a good idea, because it puts too much domain information into the process. It’ll be a pain maintaining it as the powers that be tweak and adjust things. So what we’d rather do is store the prerequisite information in the database, something like:

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

Now the prerequisite information is moved from the code into the database. It can be manipulated by the administration, the code is simpler, etc. The question is whether you can do the same for your business processes. There are many benefits to be had by moving something like that out of the code into data. Maybe you can’t, but its what I’d look to do.

I’d probably avoid enum even if you have to put these entities into the code. enums are pretty stupid. I think it’d be better to be able to say: Chemicals.SodiumPhosphate.GetMolesFromMass(1000) than to say GetMolesFromMass(Chemicals.SodiumPhosphate, 1000). It also gives you future flexibility because the method can do whatever it wants. It can use a lookup table, or store the data inside, or whatever.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật