繁体   English   中英

ASP.NET MVC:这个业务逻辑应该在哪里?

[英]ASP.NET MVC: Where should this business logic go?

我正在研究我的第一个真正的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; } 
}

编辑:只是为了澄清LeaseQuote不是实体类,因为它仅用于向透视客户显示成本细分,并且不会在任何地方持久存在。

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);

或者LeaseQuote类应该有方法吗?

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方法关注的内容; 它与客户和停车位有关。

我还可以证明,如果稍后有更多字段进入Entity会影响GetQuote方法,那么方法签名不必更改。 在这种情况下,只需要更改GetQuote的实现。

简答:偏好。

只需将GetQuote设置为ParkingSpaceLease中的静态方法即可。

我认为你的对象模型可能略有歪斜,这会导致你担心租约是错误的地方,从中得到报价。 在我看来,租约将完全由租赁的停车位组成,并且仅与购买租赁的客户有关。 IOW:

public class ParkingSpace
{
    int ID { get; set; }
    int Length { get; set; }
    IEnumerable<ParkingSpaceLease> Leases { get; set; }
    LeaseQuote GetQuote(Customer customer/*, other relevant parameters */) { ... }
}

public class ParkingSpaceLease
{
    int ID { get; set; }
    DateTime OpenDate { get; set; }
    DateTime CloseDate { get; set; }
    Customer Customer { get; set; }
}

public class LeaseQuote
{
    //Properties
    ParkingSpaceLease GetLease();
}

编辑我错过了关于LeaseQuote是一个单独的课程的部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM