该系统有一个页面,用户可以通过指定起始日期和结束日期来搜索项目。这些是普通日期(没有时间组件)。对于用户来说,最直观的方式是将结束日期包含在内(因此也包括该结束日期的所有项目)。
然而,这些项目的CreateDate在数据存储中包含时间组件。实际上,这意味着我们需要将这个无时间概念的结束日期转换为第二天的0:00:00小时日期。这样我们就可以写出以下查询:
将此结束日期转换的方法就像编写以下代码一样简单:
我的问题是:这段代码的最后一行应该被视为业务逻辑并放置在业务层中,还是应该将其视为“模型绑定逻辑”并将其放置在表示层中?
如果将其放置在BL中,则意味着BL知道表示层,因为提供值的方式是特定于接口的。另一方面,由于操作在业务层中定义为DTO,我也可以将此对象视为对表示层有用的接口。
这个问题可能是哲学性质的,因为可能有多种看待它的方法,而实际的转换代码是微不足道的。我很想听听您为什么认为它应该放在一个层中而不是另一个层中。
我不认为应用程序的架构对这个问题的答案有任何影响。但为了更全面地说明,该架构基于命令和查询,演示层创建一个查询对象,由业务层处理。PL代码通常如下所示:
然而,这些项目的CreateDate在数据存储中包含时间组件。实际上,这意味着我们需要将这个无时间概念的结束日期转换为第二天的0:00:00小时日期。这样我们就可以写出以下查询:
SELECT *
FROM Items
WHERE CreateDate >= @STARTDATE
AND CreateDate < @ENDDATE
将此结束日期转换的方法就像编写以下代码一样简单:
endDate.Date.AddDays(1);
我的问题是:这段代码的最后一行应该被视为业务逻辑并放置在业务层中,还是应该将其视为“模型绑定逻辑”并将其放置在表示层中?
如果将其放置在BL中,则意味着BL知道表示层,因为提供值的方式是特定于接口的。另一方面,由于操作在业务层中定义为DTO,我也可以将此对象视为对表示层有用的接口。
这个问题可能是哲学性质的,因为可能有多种看待它的方法,而实际的转换代码是微不足道的。我很想听听您为什么认为它应该放在一个层中而不是另一个层中。
我不认为应用程序的架构对这个问题的答案有任何影响。但为了更全面地说明,该架构基于命令和查询,演示层创建一个查询对象,由业务层处理。PL代码通常如下所示:
public Action Filter(DateTime start, DateTime end)
{
var query = new GetItemsByStartEndEndDateQuery
{
StartDate = start.Date,
EndDate = end.Date.AddDays(1)
}
var items = this.queryProcessor.Handle(query);
return this.View(items);
}
或者,尽可能使用(MVC)模型绑定来简单地将命令和查询对象进行模型绑定(非常方便):
public Action Filter(GetItemsByStartEndEndDateQuery query)
{
var items = this.queryProcessor.Handle(query);
return this.View(items);
}
如果涉及多个用户(例如WCF层和MVC层),你的答案会改变吗?