加入收藏 | 设为首页 | 会员中心 | 我要投稿 成都站长网 (https://www.028zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 网站设计 > 教程 > 正文

.Net中的AOP系列之构建一个汽车租赁应用

发布时间:2016-10-28 22:47:23 所属栏目:教程 来源:站长网
导读:副标题#e# 返回《.Net中的AOP》系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看。 本系列的实验环境:VS 2013 Update 5(建议最好使用集成了Nuget的VS版本,VS Express版也够用

虽然审计积分事务还不是一个需求,但是为了安全起见,最好还是记录每个请求,至少是为了QA(质量保证)的目的。在生产环境,可能会限制或减少日志,但是现在我们要放一些简单的日志帮助开发者重现QA找到的bugs。

现在,当累积积分和兑换积分时,添加日志,其余代码和之前的一样。

  /// <summary>
  /// 该方法包含了积分系统累积客户积分的逻辑和规则
  /// </summary>
  /// <param name="agreement">租赁协议实体</param>
  public void Accrue(RentalAgreement agreement)
  {

      Console.WriteLine("Accrue:{0}",DateTime.Now);
      Console.WriteLine("Customer:{0}",agreement.Customer.Id);
      Console.WriteLine("Vehicle:{0}",agreement.Vehicle.Id);
      var rentalTimeSpan = agreement.EndDate.Subtract(agreement.StartDate);
      var numberOfDays = (int)rentalTimeSpan.TotalDays;
      var pointsPerDay = 1;
      if (agreement.Vehicle.Size >=Size.Luxury)
      {
          pointsPerDay = 2;
      }
      var points = numberOfDays*pointsPerDay;
      //调用数据服务存储客户获得的积分
      _loyaltyDataService.AddPoints(agreement.Customer.Id,points);
      Console.WriteLine("Accrue Complete:{0}",DateTime.Now);
  }

public void Redeem(Invoice invoice, int numberOfDays)
{
    Console.WriteLine("Redeem:{0}",DateTime.Now);
    Console.WriteLine("Invoice:{0}",invoice.Id);
    var pointsPerDay = 10;
    if (invoice.Vehicle.Size>=Size.Luxury)
    {
        pointsPerDay = 15;
    }
    var totalPoints = pointsPerDay*numberOfDays;
    invoice.Discount = numberOfDays*invoice.CostPerDay;
    _loyaltyDataService.SubstractPoints(invoice.Customer.Id,totalPoints);
    Console.WriteLine("Redeem Complete:{0}",DateTime.Now);
}

现在还不是很糟糕,只不过在每个实现中添加了几行代码而已。咱们继续往下走!

防御性编程

因为我们的业务逻辑没有对传入的参数进行控制,因此必须要检查一下是否是最坏的情景。比如,如果Accrue方法传入一个null会怎样?我们的业务逻辑不能处理这个,所以会抛异常,但我们希望它能调用我们的API处理这个异常,如果处理不了,就提醒UI开发者或QA发生了一些错误的东西。这种哲学就叫防御性编程,只是为了减少危险场景的风险。

下面我们使用防御性编程检查传入参数为null的无效场景:

 public void Accrue(RentalAgreement agreement)
 {
     //防御性编程
     if (agreement==null)
     {
         throw new Exception("agreement为null!");
     }
     //日志
     Console.WriteLine("Accrue:{0}",DateTime.Now);
     Console.WriteLine("Customer:{0}",agreement.Customer.Id);
     Console.WriteLine("Vehicle:{0}",agreement.Vehicle.Id);
     var rentalTimeSpan = agreement.EndDate.Subtract(agreement.StartDate);
     var numberOfDays = (int)rentalTimeSpan.TotalDays;
     var pointsPerDay = 1;
     if (agreement.Vehicle.Size >=Size.Luxury)
     {
         pointsPerDay = 2;
     }
     var points = numberOfDays*pointsPerDay;
     //调用数据服务存储客户获得的积分
     _loyaltyDataService.AddPoints(agreement.Customer.Id,points);
     Console.WriteLine("Accrue Complete:{0}",DateTime.Now);
 }

我们也可以检查RentalAgreement的属性,但现在上面的就足够了。Redeem的实现也有相同的问题,numberOfDays参数的值不能小于1,Invoice参数也不能为null,因此也必须使用防御性编程:

 public void Redeem(Invoice invoice, int numberOfDays)
 {
     //防御性编程
     if (invoice==null)
     {
         throw new Exception("invoice为null!");
     }
     if (numberOfDays<=0)
     {
         throw new Exception("numberOfDays不能小于1!");
     }
     //logging
     Console.WriteLine("Redeem:{0}",DateTime.Now);
     Console.WriteLine("Invoice:{0}",invoice.Id);
     var pointsPerDay = 10;
     if (invoice.Vehicle.Size>=Size.Luxury)
     {
         pointsPerDay = 15;
     }
     var totalPoints = pointsPerDay*numberOfDays;
     invoice.Discount = numberOfDays*invoice.CostPerDay;
     _loyaltyDataService.SubstractPoints(invoice.Customer.Id,totalPoints);
     Console.WriteLine("Redeem Complete:{0}",DateTime.Now);
 }

现在我们的代码开始变得具有防御性了,如果在核心逻辑的控制之外发生了错误,也不会影响到我们了。

在添加了日志和防御性代码之后,AccrueRedeem方法开始变得有点长了,也有点重复,但继续看一下事务和重试逻辑。

使用事务和重试

(编辑:成都站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读