重构服务层类

Bee*_*eep 7 c# refactoring unit-testing

我的公司正在进行单元测试,我在重构服务层代码方面遇到了一些麻烦.这是我写的一些代码的例子:

public class InvoiceCalculator:IInvoiceCalculator
{
   public CalculateInvoice(Invoice invoice)
   {
      foreach (InvoiceLine il in invoice.Lines)
      {
          UpdateLine(il);
      }
      //do a ton of other stuff here
   }

   private UpdateLine(InvoiceLine line)
   {
      line.Amount = line.Qty * line.Rate;
      //do a bunch of other stuff, including calls to other private methods
   }
}
Run Code Online (Sandbox Code Playgroud)

在这个简化的情况下(它减少了1000行有1个公共方法和~30个私有方法),我的老板说我应该能够分别测试我的CalculateInvoice和UpdateLine(UpdateLine实际上调用了3个其他私有方法,并执行数据库调用).但是我该怎么做呢?他建议的重构对我来说似乎有点令人费解:

//Tiny part of original code
public class InvoiceCalculator:IInvoiceCalculator
{
   public ILineUpdater _lineUpdater;

   public InvoiceCalculator (ILineUpdater lineUpdater)
   {
      _lineUpdater = lineUpdater;
   }

   public CalculateInvoice(Invoice invoice)
   {
      foreach (InvoiceLine il in invoice.Lines)
      {
          _lineUpdater.UpdateLine(il);
      }
      //do a ton of other stuff here
   }
}

public class LineUpdater:ILineUpdater
{
   public UpdateLine(InvoiceLine line)
   {
      line.Amount = line.Qty * line.Rate;
      //do a bunch of other stuff
   }
}
Run Code Online (Sandbox Code Playgroud)

我可以看到依赖关系现在如何被破坏,我可以测试这两个部分,但是这也会从我的原始类中创建20-30个额外的类.我们只在一个地方计算发票,所以这些碎片实际上不可重复使用.这是进行此更改的正确方法,还是您建议我做一些与众不同的事情?

谢谢!

枷锁

Mik*_*nty 5

这是功能羡慕的一个例子:

line.Amount = line.Qty * line.Rate;
Run Code Online (Sandbox Code Playgroud)

应该看起来更像是:

  var amount = line.CalculateAmount();
Run Code Online (Sandbox Code Playgroud)

许多小课程都没有任何问题,它不是关于可重用性,而是关于适应性.如果您有许多单一责任类,则可以更轻松地查看系统的行为,并在需求发生变化时进行更改.大班有交互的责任,这使得改变变得非常困难.


Chr*_*iso 1

在我看来,这一切都取决于 UpdateLine() 方法的“重要性”。如果它只是一个实现细节(例如,它可以很容易地内联到CalculateInvoice() 方法中,并且唯一会损害的是可读性),那么您可能不需要将其与主类分开进行单元测试。

另一方面,如果 UpdateLine() 方法对业务逻辑有一定的价值,如果您可以想象需要独立于类的其余部分更改此方法的情况(因此单独测试它),那么您应该去继续将其重构为单独的 LineUpdater 类。

您可能不会以这种方式得到 20-30 个类,因为大多数私有方法实际上只是实现细节,不值得单独测试。