这与我的最近的问题有关命名尴尬的域对象有关。许多答案表明我对域对象使用了错误的表示形式。总之,我选择使用枚举来表示某些域对象,这些对象用作查找中的键。
对于这个问题,我想回顾一下我使用枚举的决定,并找出替代方案。跳到我的问题的底部为TL;
域描述
我的应用程序负责执行一些涉及化学化合物的计算。
一些基本方程是:
这些方程可以作为Chemical类中的方法处理,如下所示:
Chemical.GetMolesFromMass(double mass_grams)或
Chemical.GetDensity(double concentration)
也可以将它们实现为泛型化学属性类之外的方法,如:
Chemical.GetMolesFromMass(Compound cmpd, double mass_grams)或
Chemical.GetDensity(Compound cmpd, double concentration)
我认为,从对象责任的角度来看,Chemical类之外的方法的第一个选项是更好的表示。
一些高级方程式包括:
在这些方程中,化合物是该方法的输入。
StorageTankCluster.Generate(Compound cmpd, double requiredVolume)
StorageTankCluster需要了解化学物质,因为星团内储罐的尺寸和间距将根据化学物质和所需体积而变化。储存的化学物质会影响储罐材料的选择,也会影响储罐之间的安全间隙。
目前,我正在考虑这些参数(间距,材料,.)作为查找项,而不是化合物负责了解的元素。
同样,配送优化受化学化合物的影响,但这些方面是否是化合物的责任是有争议的。
StorageTankCluster和交付优化组件都打算被应用程序的其他非化学方面重用。由于这个问题已经变得越来越复杂,我们只需将这些其他元素称为Foo和Bar。Foo和Bar都可以利用传递优化,但只有Foo可以与StorageTankCluster一起使用。
它现在不在应用程序中,但是到目前为止讨论的所有各种属性都需要存储在数据库/持久层中。我意识到这不应该影响一个好的设计,但我认为这是值得一提的。
我承认,我的一些决定是有偏见的,因为我正在从另一个来源移植这个应用程序,它强制以结构化的方式完成所有工作。写出这个问题突出了几个领域,我应该更好地检查哪些对象对该功能负有责任。
到目前为止,我的设计都是围绕查找表进行的,我使用枚举值作为这些表的键。正是它们作为密钥的使用,使我将它们作为程序中的命名对象来处理,而不是将它们作为系统将操作的对象。这几乎把化学化合物降到了二级等级,我想知道这是否是正确的决定。另一方面,我担心化学化合物类会变得过于臃肿。
TL;DR
我的实现是/必须在C#中。所以使用枚举是正确的选择,或者我应该做什么,为什么?
发布于 2012-12-22 00:28:20
我们希望代码尽可能简单。我们不希望它被程序员不需要知道的领域知识弄得乱七八糟。因此,只要有可能,我们都希望避免将某些特定于化学产品的领域放入代码中。这就是为什么我们认为将化学产品作为enum放入您的代码中可能是个坏主意,除非事实证明并非如此。
作为一个类似的案例,考虑一个课程注册制度。您不希望代码包含对人们应该参加的各种课程的任何引用。CSI101可能是“计算机图形学入门”,但在代码中根本不应该出现这种情况。该信息只应位于课程的数据库行中。课程注册系统代码对待所有类都是一样的,可能只考虑课程的名称、先决条件、学分等属性。
第一个问题是,你是否真的需要在你的代码中引用各种化合物。这与您是否使用查找表无关。无论Chemical.GetDensity(Compound cmpd, double concentration)是枚举、对象、字符串还是int,Compound都可以同样工作。StorageTankCluster.Generate(Compound cmpd, double requiredVolume),是相同的,函数的工作原理是相同的,不管这些化合物是否在代码中被命名为实体。这些事情都不需要你在代码中引用化合物。
当然,在某个地方你必须指定考虑哪种化合物。它不可能总是函数的参数。正是该规范的性质决定了您是否需要在代码中引用化学品。您的声明似乎表明业务流程决定了需要考虑哪些化合物。我认为业务流程是编写成代码的,这就是为什么您需要在代码中引用化学化合物。但问题是,业务流程是否真的需要在代码中实现。
为了明白我的意思,让我们回顾一下课程注册情况。假设您有一个类,对于是否允许您接受它,有一个复杂的规则。
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;
}如果我的理解是正确的,你需要一个枚举,因为你指的是你的过程中的各种化学产品,就像我在上面的课程中所做的那样。(我使用过字符串,但我也可以使用枚举。)但是,上面的代码不是一个好主意,因为它将太多的域信息投入到这个过程中。这将是一个痛苦的维持作为权力,是调整和调整的事情。所以我们想要做的是将前提信息存储在数据库中,如下所示:
Course Prereq Grade Required Alternate Grade Required
CSI250 CSI101 B
CSI250 CSI150 D CSI200 B现在,先决条件信息从代码移到数据库中。它可以由管理部门操作,代码更简单,等等。问题是您是否可以对您的业务流程做同样的操作。将代码中的类似内容移到数据中有很多好处。也许你做不到,但这是我想要做的。
即使您必须将这些实体放入代码中,我也可能避免使用enum。enums很蠢。我认为能说:Chemicals.SodiumPhosphate.GetMolesFromMass(1000)比说GetMolesFromMass(Chemicals.SodiumPhosphate, 1000)更好。它还为您提供了未来的灵活性,因为该方法可以做它想做的任何事情。它可以使用查找表,也可以将数据存储在其中,或者其他什么。
https://softwareengineering.stackexchange.com/questions/180335
复制相似问题