0

我正在开发膳食计划应用程序。我有一个 MealSchedule,其中列出了我想在不同日子吃的东西。那个 MealSchedule 最终会变成一个 MealPlan,它是一个产品和食谱的杂货清单,这些清单将创建我每天想吃的东西。

由于 MealPlan 是从 MealSchedule 创建的,因此我想为 MealPlan 创建一个构造函数,该构造函数接受 MealSchedule。不幸的是,这个过程相当复杂,我觉得这会导致创建过于复杂的构造函数的反模式。

另一方面,如果我使用构建器来创建 MealPlan,那么 MealPlan 将成为一个相当贫乏的对象,并且不包含与 MealPlan 密切相关的逻辑。哪一个是两个邪恶中最小的一个,或者更有可能的是,我错过了什么?

4

2 回答 2

1

MealPlan可以修改并且必须跟踪其状态的完整实体,还是可以将其设为值对象?如果可以,那么您不必担心它会贫血,并且可以将其构造委托给某种MealPlanBuilder.

无论如何,我要做的就是尝试改进无处不在的语言并与领域专家交谈,看看像膳食计划生成器这样的东西在商业方面是否有意义。如果答案是肯定的,那么你就有了你的对象。我认为这也是非常实用的,因为您将能够以非常精确、清晰表达的方式与利益相关者讨论膳食计划生成过程,例如

“我们需要更改膳食计划生成器,以允许用户在每周和每日膳食计划之间进行选择......”

如果生成膳食计划的概念本身并不是那么重要,那么您可以考虑将其逻辑留在MealPlan构造函数中。

作为旁注,我要补充一点,贫血不是一种反模式,您应该在每个域对象中系统地跟踪和消除。当然,当您的对象确实具有行为时会更好,并且您应该尽可能每次都尝试这样做,但对于某些对象来说这是不可能的。仅仅因为完全贫血的域层不好并不意味着您需要为偶尔的贫血对象鞭打自己。

于 2012-09-17T09:43:09.960 回答
1

这只是在某些(不是所有,只是一些)类似情况下对我有用的方法的粗略“草图”。过去,当面对这些选择时,我会退后一步,因为我喜欢那个小小的 KISS——保持简单软件工程师。

从一个基本的(贫血的?)基类开始。开始将这些复杂选项建模为(多态)子类。很高兴拥有多层次的共性,它将获得长期回报(在更复杂的应用程序中,也许不是膳食调度程序)。一个例子; 如果你有一个数据字段,你可以有一个“字段”类:“数字”/“文本”/“布尔”/“URI”。退一步:URI:URL、Email、Wget;文本:TextField、TextArea、Literal、...

它必须对您的应用程序有意义。你可以看看:

  • 用餐:坐着/点心
  • 坐:午餐/早餐/晚餐
  • 小吃:早茶/下午茶/晚餐/冰箱

这个想法是要求编译器和类关系逻辑强制您的代码非常愚蠢,因为静态选择可以在定义中“开发”。一旦你知道这是星期四的午餐...... EAT = new Lunch( Thursday ) ... 如果你让你的构造函数变得聪明;将一路向下。

我第一次“尝试”做这种事情是一团糟!我放弃了。下一次我只是想更多,尝试一些课程(铅笔和纸会有所帮助),直到你有足够好的东西开始。然后试用班级家庭-然后充满激情地进行重构。

祝你好运 :-)

于 2012-09-17T13:09:26.370 回答