为什么我们需要在C#中的UI,业务和数据访问之间的接口

我在许多地方看到,当c#程序员使用3轮胎架构时,他们倾向于使用每层之间的接口。 例如,如果解决方案是这样的

SampleUI Sample.Business.Interface Sample.Business Sample.DataAccess.Interface Sample.DataAccess 

这里UI通过接口调用业务层,业务以相同的方式调用数据访问。 如果这种方法是为了减少层之间的依赖关系,那么它已经与类库一起使用而无需额外使用接口。 代码示例如下,

Sample.Business

 public class SampleBusiness{ ISampleDataAccess dataAccess = Factory.GetInstance(); dataAccess.GetSampledata(); } 

Sample.DataAccess.Interface

 public interface IsampleDataAccess{ string GetSampleData(); } 

Sample.DataAccess

 public class SampleDataAccess:ISampleDataAccess{ public string GetSampleData(){ returns data;// data from database } } 
  1. 这之间的推断有什么好处?
  2. 如果我使用newSampleDataAccess()。SampleData()并删除完整的接口类库怎么办?

代码合同

使用接口作为设计过程的一部分有一个显着的优点:它是一个合同。

接口是合同的规范,在这个意义上:

  • 如果我使用(使用)界面,我限制自己使用界面公开的内容。 好吧,除非我想玩脏(reflection,等等)。

  • 如果我实现接口,我限制自己提供接口公开的内容。

以这种方式做事的优点是它可以简化开发团队之间的工作分工。 它允许层的开发者提供咳嗽界面咳嗽 ,下一层可以使用它来与之通信……甚至在实现这样的界面之前。

一旦他们同意了界面。 至少在可行的最小界面上。 他们可以开始并行开发层,知道其他团队将坚持他们的合同部分。


惩戒

以这种方式使用接口的一个副作用是,它允许模拟组件的实现。 这简化了unit testing的创建。 这样,您可以隔离地测试图层的实现。 因此当图层出现故障时,您可以轻松区分因为它有缺陷,并且当图层失败时,因为它下面的图层有缺陷。

对于由单个人开发的项目,或者由于在绘制清晰的线条以分离工作时没有太多困扰的组, 模拟的能力可能是他们实现接口的主要动机。

例如,考虑一下,如果您想测试您的表示层是否可以正确处理分页……但您需要请求数据来填充这些页面。 可能是这样的情况:

  • 下面的图层尚未就绪。
  • 数据库还没有要提供的数据。
  • 它失败了,他们不知道分页代码是否正确,缺陷来自代码中的更深层
  • 等等…

无论哪种方式,解决方案都是嘲弄。 此外,如果您有模拟接口,则模拟会更容易。


改变实施

如果由于某种原因,一些开发人员决定他们想要改变他们的层的实现,他们可以这样做信任接口强加的合同 。 这样,他们可以交换实现而无需更改其他层的代码。

什么理由?

  • 也许他们想测试一项新技术。 在这种情况下,他们可能会创建一个替代实现作为实验。 此外,他们希望两个版本都能正常运行,以便测试哪一个更好。

    附录:不仅可以测试两个版本,还可以轻松回滚到主版本。 当然,他们可以通过源版本控制实现这一目标。 因此,我不会考虑回滚作为使用接口的动机。 然而,对于任何不使用版本控制的人来说,这可能是一个优势。 对于任何不使用它的人……开始使用它!

  • 或许他们需要将代码移植到不同的平台或不同的数据库引擎。 在这种情况下,他们可能不想丢弃旧代码…例如,如果他们有运行Windows和SQL Server的客户端以及运行Linux和Oracle的其他客户端,那么维护这两个版本是有意义的。

当然,在任何一种情况下,您都希望能够通过尽可能少的工作来实现这些更改。 因此,您不希望更改上面的图层以定位不同的实现。 相反,您可能会有某种forms的工厂控制容器的反转 ,您可以配置为使用您想要的实现进行dependency injection


减少变化传播

当然,他们可能决定改变实际的界面。 如果在一个层上工作的开发人员需要在界面上添加一些额外的东西,他们可以将它添加到界面中(根据团队设置的任何方法来批准这些更改),而不会弄乱其他团队工作的类的代码上。 在源版本控制中,这将减少边际更改。


最后,使用层架构的目的是分离关注点。 这意味着分离变更原因……如果您需要更改数据库,您的更改不应传播到专用于向用户呈现信息的代码中。 当然,团队可以通过具体课程来实现这一目标。 然而,接口提供了良好且明显的,定义明确的语言支持,阻止了变化的传播。 特别是如果团队有关于责任的良好规则(不,我不是指代码问题,我的意思是,开发人员负责做什么)。

你应该总是使用图层的抽象来具备这种能力

  • 模拟unit testing中的接口
  • 使用虚假实现来加快开发速度
  • 轻松开发替代实现
  • 在不同的实现之间切换