WinForms应用程序的架构?

15

我几周前开始了一个WinForms项目,由于我不知道需要哪些功能,所以一直在添加。现在导致我的主窗体成为一个混乱的代码块,例如一些重要的状态更改由UI元素触发,以至于我必须调用控件的OnChange事件才能更改数据库中的某些状态。

简而言之:我刚开始一个新项目,想采取更好的方法,但我不知道哪种是“好”的。在ASP.net MVC中,我发现MVVM模式非常有用,但在桌面上,MVVM似乎只适用于WPF,而不是WinForms。

另一种方法是三层架构:我有一个Database-Class,目前直接与UI通信。我现在创建一个新的静态类(“ApplicationState”),它与数据库通信并触发事件告诉UI“嘿,有东西变了!” UI将操纵状态,状态将处理数据库持久性,并再次引发事件以更新UI。这里的重点是ApplicationState类从不直接修改UI,而是UI订阅事件。 这看起来像一种干净/“MVC”方式,但也许我在忽略什么?

基本上,我的最终目标是使UI完全独立于数据库层,以确保我不会再将业务逻辑嵌入到UI中。

7个回答

11
不要放弃在WinForms中使用MVVM - 这也是有效的。基本上,如果您使用数据绑定,您必须决定您的对象将绑定到什么。通常,特别是对于更复杂的UI,您不想直接绑定到您的域对象,而是要构建专门的类(有时是包装器),您的UI可以绑定到这些类提供了视图需要的所有内容(MVVM的本质),这种技术在Winforms中同样适用。
关于WinForms Model-View-Presenter方法的不错系列可以在以下链接找到: The Build Your Own CAB Series目录

6
NDepend文档附带了一些非常酷和高级的在线博客文章和白皮书,涉及.NET代码架构。 .NET程序集划分建议 控制组件依赖以获得清晰的架构 重构、重组和平衡成本 演化式设计和无环组件化

分层、水平指标和方法论话语

对抗制造出来的复杂性

此外,如果您想持续检查UI代码与数据库代码的独立性,您可以轻松编写一些Code Query Language规则,在Visual Studio中开发时实时检查:

保持代码结构清晰


6

我会优先选择分层应用程序的方式:

  • 表示层 (仅包含 UI 和数据绑定逻辑)
  • 接口层到业务层 (定义访问 BL 的合同)
  • 业务层实现 (实际逻辑、数据验证等...)
  • 接口层到数据访问层 (定义访问 DAL 的合同)
  • 数据访问层实现

这样可以极大地组织您的应用程序。然后我会寻找一些 MVC 类似的方法。我没有开发过 WinForms,更多的是使用 Asp.net 和一些 Java Desktop 客户端 (我在其中使用了 MVC)。WinForms 更多地使用 .Net 数据绑定方法 (DataSource、DataMember 等)。您应该选择这种方法而不是试图强制使用其他方法。我发现它并不匹配。

将我们的 UI 逻辑布局到不同的控件中 (如 Asp.net 中的 UserControls) 总是很有用的。这有助于重用。


我猜这就是.NET在层之间的奶酪吧? - Paul Williams
奶酪层放在哪里?我喜欢奶酪。 - Charlie Salts
1
奶酪是接口层,它将主要的组件连接在一起,依赖注入由MS Unity提供,获取BL等的正确实例化。 :) - Juri
我认为这种方法对于“大型”应用程序是有意义的,所以点赞。但我担心对于我的应用程序来说有些过度设计了。它只是一个简单的应用程序,有1个主要表单,1个数据库和3或4个不做太多事情的附加表单。因此,5层可能真的有点过度设计了。我更多地寻找在UI和数据库之间交换数据的最简单方法,而不必将所有业务逻辑都放在UI中,我不知道静态类是否是正确的选择。 - Michael Stum
@Michael:那么我会尝试使用MVC方法进行分离,就像我在帖子中链接的那个(虽然它是用Java编写的,但你可以很容易地“重新编程”)。您的控制器可以是一个单例类,执行“领域+业务逻辑”。 - Juri
有没有一些好的例子供学习者在实现这种架构时使用? - Zach Pedigo

1

1

开始为你能想到的一切编写单元测试。由于某些部分与WinForms紧密耦合而难以进行单元测试,因此将它们分离出来。清洁。洗涤。重复。


2
-1 是因为这基本上就是他第一次陷入大量混乱代码的情况,只不过没有单元测试。 - MusiGenesis
1
@MusiGenesis,“只是没有单元测试”——这可是天壤之别。缺乏单元测试才是导致代码混乱不堪的罪魁祸首。 - Andriy Volkov
1
单元测试并非万能药,这是我的经验。如果没有提前明确的计划,随意添加内容会导致代码变得混乱不堪。即使附带了一套测试用例,这些代码仍然是一团糟(有时测试用例本身也是一团糟)。 - MusiGenesis
我不同意这种方法应该是构建良好结构化解决方案的唯一途径。我同意单元测试确实会产生良好结构化的代码。如果你的代码没有达到这个效果,那么你就没有正确地进行单元测试。 - Sergey
+1 我正在研究与原始提问者相同的问题,而这个答案是唯一一个在你甚至开始之前就不会将你限制在复杂的架构模式中的答案。这个简单的答案表明我的开发Web应用程序的过程应该很好地适用于桌面应用程序。感谢您的安慰。 - G-Wiz
显示剩余3条评论

0
我们的经验规则是,由于Web的无状态特性,大多数网站都倾向于使用MVC。除非您试图提供非常丰富的Web体验并引入Silverlight,否则您应该选择MVVM。XAML与MVVM紧密相关,也可以成为您智能客户端选择的一种良好MVCP模式。
真正的MVC在任何其他情况下几乎不可能被维护,因为控制器应该处理所有输入。大多数非Web架构都有控件可以为您提供此功能。事实上,大多数人都说ASP.NET MVC是一种混合MVC,但在我的经验中非常好用。

0

好的,
我在上面找到了一些不错的答案,但根据我在winform方面4年以上的经验,我可以说你可以使用dotnet remoting来实现这个目的。简单来说,你需要为你的业务逻辑和客户端工作创建一个解决方案,另一个解决方案用于与数据库连接,你可以称之为服务器。两个解决方案都应该包含一些共同的项目,然后你就可以轻松地在应用程序上工作,而不必担心你的数据库。
我建议你阅读一下dotnet remoting的相关内容。

希望这个答案有所帮助。


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