我正在制定膳食计划申请表。我有一份MealSchedule,这是我想在不同的日子里吃的东西的清单。 MealSchedule最终将变成一个MealPlan,这是一个产品和食谱的杂货清单,将创造我想要在每一天吃的东西。
由于MealPlan是从MealSchedule创建的,我想为MealPlan创建一个MealSchedule的构造函数。不幸的是,这个过程相当复杂,我觉得这会导致创建过于复杂的构造函数的反模式。
另一方面,如果我使用构建器来创建MealPlan,那么MealPlan将变成一个相当贫血的对象,并且不包含与MealPlan密切相关的逻辑。哪个是两个邪恶中最少的,或者更可能的是,我错过了什么?
答案 0 :(得分:1)
MealPlan
是一个完整的实体,可以修改并且必须跟踪其状态,还是可以将其作为值对象?如果可以,那么你不必担心它是贫血的,你可以将它的构造委托给某种MealPlanBuilder
。
无论如何,我要做的是尝试改进无处不在的语言,并与领域专家交谈,看看膳食计划生成器这样的东西在商业术语中是否有意义。如果答案是肯定的,那么你有了自己的对象。我认为这也非常实用,因为您能够以非常精确,明确表达的方式与利益相关者讨论膳食计划生成过程,如
“我们需要更改膳食计划生成器,以允许用户在每周和每日膳食计划之间进行选择......”
如果生成膳食计划的概念本身并不重要,那么您可以考虑将其逻辑留在MealPlan
构造函数中。
作为旁注,我要补充一点,贫血不是一种反模式,你应该系统地跟踪和根除域对象的每个。当然,当你的对象确实有行为时你会更好,你应该每次都这样做,但是对于某些对象来说这是不可能的。仅仅因为完全贫血的领域层是坏的并不意味着你需要为自己的偶尔的贫血对象鞭打自己。
答案 1 :(得分:1)
这只是一种粗略的“草图”,对我来说在一些(不是每一个,只是一些)类似的情况下都适用。在过去遇到这些选择时,我退后一步,因为我喜欢那个小小的KISS - 保持简单的软件工程师。
从基础(贫血?)基类开始。开始将这些复杂选项建模为(polymorph)子类。很高兴拥有多层共性,它将获得长期回报(在更复杂的应用程序中,也许不是膳食调度程序)。一个例子;如果你有一个数据字段,你可以有一个'Field'类:'Numerics'/'Text'/'Boolean'/'URI'。退一步:URI:URL,Email,Wget;文字:TextField,TextArea,Literal,......
它必须对您的应用程序有意义。你可以看看:
这个想法是要求编译器和类关系逻辑强制你的代码真的很愚蠢,因为静态选择可以在定义中“开发”。一旦你知道它是星期四的午餐... EAT =新午餐(星期四)...如果你让你的建设者聪明;将一路下来。
我第一次'尝试'做这种事情是一团糟!我放弃了。下一次我只是想更多,尝试一些课程(铅笔和纸帮助),直到你有足够好的东西开始。然后审判班级家庭 - 然后充满激情的REFACTOR。
祝你好运: - )