在C#中分离UI和逻辑

18

有没有关于如何避免在GUI类中加入逻辑的建议?我试图使用良好的类设计尽可能地保持分离,但我的表单类通常会包含比我想象中更多的非UI内容,这往往会使维护变得非常痛苦。

(Visual Studio 2008 Professional,C#,Windows应用程序)。

非常感谢。

8个回答

16

将您的逻辑放入单独的程序集中;并且在构建该程序集时不引用任何GUI包(例如System.DrawingSystem.Windows.Forms等)。


谢谢 - 我认为这是一个不错的实际起点,可以帮助我正确思考。 - Andy

10

这其实只是一个练习和自律的问题。我是说,我们都做过这样的事情。而且在错误的条件下(经理/客户大喊让我们“立刻”完成某事,而不是“正确”的时间),我们都会不时地继续这样做。

在编写驱动UI的代码时(更多是针对web方面,但同样适用),我会问自己每个代码单元(一行代码、一个条件、一个循环等)是否依赖于UI的存在。如果我要写入文本框,那么就是依赖于UI的,所以代码就放在那里。但如果我正在计算将放入该文本框的结果,那么这可能是业务逻辑。

另一种方法(正如ChrisW在我打字时所提到的)是先在非UI类库中开发逻辑。在其中尽可能多地放置不依赖于基于UI的库的逻辑(根据您定义“逻辑”的标准判断即可),然后构建UI以利用该逻辑。有不同的方法可以同时开发这两个部分,例如通过接口类来处理逻辑程序集并仅将UI部分编码到这些接口中(然后使用依赖注入将程序集类插入接口中)等。


6
您需要的是3层架构。您需要构建两个可重用的层:

  • 数据访问层(DAL),它仅包含从数据库读/写所需的代码
  • 业务逻辑层(BLL),它使用DAL,包含业务规则、验证,并为UI提供外观

然后,在您的UI项目中,您引用可重用的层并处理仅与UI相关的内容。UI项目仅与BLL通信,而不直接连接到DAL:

UI <---> BLL <---> DAL

您可以拥有多个UI层来使用您的可重用组件,以及多个可互换的DAL,如果您想支持多个数据库类型。


5

您需要了解设计模式,例如:

模型-视图-控制器(MVC),通常用于网站(ASP.NET)
模型-视图-视图模型(MVVM),通常用于WPF

通过遵循其中一种模式,您应该能够将应用程序的各个部分保持分离。

还有其他类似的模式可供选择。

此外,使用WPF进行开发可以帮助您,因为UI由XAML定义,而执行工作的代码是C#。这可以提供基本的分离程度。如果您发现自己编写的C#代码仅操作UI,则可以退后一步并思考“我应该在XAML中完成这项工作吗?”显然,可能有些事情必须在代码后面完成,但这是一个开始。


2

学习如何编写控制器类,使其可以绑定到表单并执行数据绑定。 在WinForms中,这主要涉及控制器类上的INotifyPropertyChanged和IDataErrorInfo接口以及在表单类上使用BindingSource实例。

然后,您可以编写一个包含所有UI和逻辑数据的控制器类,并将其简单地绑定到UI类。您的UI类变得非常轻巧,而您的UI逻辑(保存在控制器中)变得非常易于测试(当针对UI类运行时,单元测试会很棘手,但是当针对控制器类运行时,单元测试会容易得多)。

这是所有MVC/MVVM设计的基础。

Herbie


1
通常在这种情况下,我会创建一个帮助方法类来完成所有繁重的工作。
至于保持逻辑分离,要确定关键组件,并将其重构到该帮助方法类中。例如,如果我正在处理 GridView 来根据是否选择记录来更新记录;如果是,则更新 ShipDate,在表单中;我会首先确定行是否被选中;然后提取 Id 字段,然后提取 ShipDate,然后将 Id 和 ShipDate 传递到我的帮助类上的一个方法中,该方法完成所有工作。
单元测试可以成为您的朋友;基本上,如果您有任何执行“逻辑”类型操作的代码,则应该进行单元测试。如果它在 GUI 类中,则很难测试;但是一旦您将其重构出来,单元测试应该是微不足道的。

1

您应该关注以下模式:

MVC(模型-视图-控制器) MVVM(模型-视图-视图模型)- 在具有丰富数据绑定支持的 WPF 中使用最多。 MVP(模型-视图-展示者)- 经常用于 WinForms 和 Web 应用程序(因为视图是无状态的)

查看这篇博客文章,其中提供了如何使用 MVP 为 Web 和 WinForms 视图都提供动力的示例: http://www.cerquit.com/blogs/post/MVP-Part-I-e28093-Building-it-from-Scratch.aspx

此外,这篇博客文章介绍了使用 MVP 模式对业务逻辑进行单元测试的方法: http://www.cerquit.com/blogs/post/Model-View-Presenter-Part-II---Unit-Testing.aspx


1

一句话,这被称为重构

将代码放入UI中只有几个原因:

  1. 与表单上的控件交互
  2. 验证(虽然可以放在业务逻辑层中,但我通常会在UI中添加一个帮助方法(更容易)

所有其他“业务逻辑”代码都进入另一个称为业务逻辑类的类中。 所有数据库交互代码都进入不同的称为数据访问类的类中。

当您在UI中编写代码时,请问自己该代码是否正在与表单上的控件交互。 如果不是,它可能属于其他两个类。

查看Martin Fowler关于重构的一些书籍,例如“Refactoring: Improving the Design of Existing Code”。 另一个流行词是责任分离。 我知道您可以在一个类中完成所有这些内容,但是当代码按照上述方式分开时,它变得更加易读和更易于调试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接