我正在开发我的第一个真正的mvc应用程序,我正在尝试遵循一般的oop最佳实践。我正在将控制器中的一些简单业务逻辑重构到我的域模型中。我最近读了一些东西,似乎很清楚我应该把逻辑放在域模型实体类中的某个位置,以避免“贫血的域模型”反模式。
该应用程序将允许人们购买停车位租赁。价格取决于地点的长度以及客户是否是商业园区的成员。
因此,我的域模型中有如下实体类(简化):
public class Customer
{
int ID { get; set; }
string Name { get; set; }
bool IsMember { get; set; }
}
public class ParkingSpace
{
int ID { get; set; }
int Length { get; set; }
}
public class ParkingSpaceLease
{
int ID { get; set; }
DateTime OpenDate { get; set; }
DateTime CloseDate { get; set; }
Customer Customer { get; set; }
ParkingSpace ParkingSpace { get; set; }
}
编辑:为了澄清leasequeote不是一个实体类,因为它只是用于向透视客户显示成本明细,并且不在任何地方持久化。
public class LeaseQuote
{
int SubTotal { get; set; }
int Discount { get; set; }
int Total { get; set; }
}
现在作为应用程序的一个特性,我需要能够为不同的客户和停车位组合生成报价。报价通常在实际创建租约的上下文之外访问,例如当客户打电话询问价格时。
那么,最好的办法是什么?在控制器中实例化一个新的ParkingSpaceLease对象来调用它的getQuote方法有意义吗?
var lease = new ParkingSpaceLease();
var quote = lease.GetQuote(length: 168, isMember: true);
return Json(quote);
或者leasequeote类应该有这个方法吗?
var leaseQuote = new LeaseQuote();
var quote = leaseQuote.GetQuote(length: 168, isMember: true);
return Json(quote);
把逻辑放在实际的ParkingSpaceLease类中感觉很奇怪。我想当我知道除了访问getQuote方法(看起来像是一个独立的服务)之外,我实际上不会对它做任何事情时,创建一个新的租约对象感觉有点“沉重”。
那么getQuote方法应该去哪里,为什么要去那里?
最佳答案
听起来你的leasequote并不是一个实体,更像是一个业务级的类。我是说,你不会把它放在任何地方的数据库里吧?它不是另一个数据对象的一部分。
当我看到这个
现在作为应用程序的一个特性,我需要能够为不同的客户和停车位组合生成报价。报价通常在实际创建租约的上下文之外访问,例如当客户打电话询问价格时。
我想到了这样一个方法签名
public LeaseQuote GetQuote(Customer customer, ParkingSpace parkingSpace, int length)
但考虑到这一点,我可能还想在
ParkingSpace
实体中存储有关停车位成本的信息,并(如果适用)在Customer
实体中存储客户折扣的信息。这些东西会去哪里?在访问实体并充当控制器提供程序的模型类(业务模型,而不是linq或实体模型)中。
现在我知道这并不像你写的那样使用你的模型。可能只是个人偏见。但当我考虑数据模型和数据实体时,除了从数据库返回的内容之外,它们不应该有任何附加方法。它们应该只表示数据库中显示的未更改的数据。如果对数据执行操作,则该数据属于数据实体之上的层。
更新:
我从您的示例中好奇的是,为什么只需要传递完整的实体对象(客户和停车位)而不只是执行计算所需的属性?
这取决于你的代码标准。如果正在使用的代码操纵实体,则公开实体本身可能是危险的。我喜欢传递实体,主要是因为我习惯了这样。但我也很小心不要在进去的路上操纵实体。我认为方法签名反映了getQuote方法的重点;它与客户和停车位有关。
我还可以假设,如果以后有更多的字段进入实体,从而影响getquote方法,那么方法签名就不必更改。在这种情况下,只有getquote的实现必须更改。
简而言之:偏好。