我有一个ASP.NET Web应用程序,它有一个UI项目和BL项目。 BL项目处理所有业务逻辑和数据访问部分。我通过简单地调用实例上的方法从我的UI调用BL方法。
Public Class User
Public Property UserID As Integer
Public Property FirstName As String
//rest of the properties for user
Public Sub Save()
//save the details to the database
End sub
End Class
并从我的UI(在C#中)我这样做。
User objUser=new User();
objUser.FirstName="Happy";
objUser.Save();
一切正常。由于项目正在增长,我考虑尝试添加某种单元测试/依赖注入测试。用Google搜索并看到每个示例都使用Interfaces。我读了很多关于接口但不知道如何在我的编码中包含接口并使其遵循更好(可扩展和可测试)的模式。除了可测性之外,它会给我一些其他优势吗?
有人可以为我提供样品吗?
答案 0 :(得分:2)
查看Model-View-Controller设计模式和asp.net mvc framework。有一个很好的概述here可以解释这种设计策略的好处。
摘录在这里:
MVC模式可以帮助您创建分离的应用程序 应用程序的不同方面(输入逻辑,业务逻辑和 UI逻辑),同时提供这些元素之间的松散耦合。 该模式指定了每种逻辑应该位于何处 应用程序。 UI逻辑属于视图。输入逻辑属于 在控制器中。业务逻辑属于模型。这个 分离可帮助您在构建应用程序时管理复杂性, 因为它使您能够专注于实施的一个方面 一时间例如,您可以在不依赖的情况下专注于视图 业务逻辑。
MVC的三个主要组件之间的松散耦合 应用程序也促进并行开发。例如,一个 开发人员可以在视图上工作,第二个开发人员可以工作 控制器逻辑,第三个开发人员可以专注于业务 模型中的逻辑。
答案 1 :(得分:1)
编码到接口提供了很多优势,更好的可测试性是与主要优势相关的一个副作用:将对象与其依赖关系解耦。
假设我有一个A类,并且在它的实现中它使用了B类。如果你没有为B提供接口,那么你将A和B的设计紧密结合在一起(你如果没有B的具体实现,就不能考虑A,因为它使用了具体的实现方式。)
如果你写一个B接口(比如IB)并在A中使用它而不是直接使用B,那么你解耦设计,并使它们独立。 A现在能够独立于特定的实施B运行,它只知道它的接口(IB)以及它需要在其上运行的方法。所以,如果以后,你决定你的B实现不好,或者你想让A能够根据上下文在两个不同的IB上工作,你可以用B替换B,也可以实现IB ,因此您根本不必修改A.
通过在运行时注入IB的实现来创建A的操作:
A myA = new A(new B()); // this could also be new A(new B2()); or anythign else that implements IB
被称为依赖注入,并且是实现OO编程的理想特征的最佳方式:控制反转(它不是控制其行为的A依赖关系,它是一个独立的类 - 工厂 - 控制注入A的内容。
对于可测试性目的,您可以对B进行单元测试而不对B 进行假设(显然需要单独测试)。所以在你的测试中,你可以注入一个存根或模拟的B实现,这将帮助你测试你想要的行为。
(对不起,没有实际的代码示例,因为我是一名Java开发人员,对C#的语法不是很好)
答案 2 :(得分:1)
接口是类的功能描述。任何实现接口的类都必须实现接口的属性,方法,索引器和/或事件。接口不包含任何实现,只包含接口提供的功能的签名。
使用接口有一些优点。其中一个重要的是,它允许您解决.NET中缺少多重继承的问题。您不能从.NET中的多个类继承,但可以实现多个接口。
其他好处包括松耦合,更易于维护,并且由于实现与接口分离,因此可以更容易地访问代码。
以下是代码如何使用界面(使用VB.NET)的简单示例:
Public Interface iPerson
Property FirstName As String
Property LastName As String
'Rest of properties for a person
Sub Save()
End Interface
Public Class User
Implements iPerson
Public Property UserId As Integer
Public Property FirstName As String Implements iPerson.FirstName
Public Property LastName As String Implements iPerson.LastName
Public Sub Save() Implements iPerson.Save
'Add code to save user
End Sub
End Class
然后,您可以从用户界面执行操作:
Dim objUser as iPerson = New User
objUser.FirstName = "Bob"
objUser.LastName = "Mckenzie"
ctype(objUser, User).UserId = 12345
如果您决定创建一个实现iPerson的新类(即--SuperUser),您UI中的大部分代码都可以保持不变:
Dim objUser as iPerson = New SuperUser
objUser.FirstName = "Bob"
objUser.LastName = "Mckenzie"
'The next line would throw a runtime error since object is not of type user
ctype(objUser, User).UserId = 12345
答案 3 :(得分:0)
您可以添加图层来桥接UI和BL。我不是UI的粉丝,对BL有所了解。这可以通过接口来完成,但不需要使用它们。