数据库访问的全局属性,而不是到处传递数据库?有人建议吗?

时间:2013-01-14 06:19:36

标签: database vb.net ms-access properties global-variables

全球是邪恶的吗?至少我读过的所有内容都是这样说的,因为某些东西可能随时改变全局的状态。

但是,我有一个DB对象,它在类参数方面有点流浪。下面的属性是一个自动在MS Access或SQL中工作的包装类的实例 - 因此它不是EF或其他ORM。

Public Property db As New DBI.DBI(DBI.DBI.modeenum.access, String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0} ;Persist Security Info=True;Jet OLEDB:Database Password=""lkjhgfds8928""", GetRpcd("c:\cms")))

代码本身确实有用于异常处理的PostSharp,所以我认为我可以通过记录它们来有条件地处理oledb错误,如果它是Null则重新初始化数据库。

到目前为止,解决方案一直是将db作为参数连续传递给需要它的每个类。大多数数据类都有一个共享的observablecollection,它是由单独实现inotifyproperty改变的结构构建的。其中一个是异步构建的。在触发私有Async buildCollection子类之前,collection属性会检查它是否为空。

鉴于我不需要使用依赖注入,因为我需要学习它;全球财产是不是很糟糕?在拉入或保存数据的任何地方都需要Db。我根本不需要它的唯一地方是View及其背后的代码。

这不是面向客户的项目,但确实需要坚实。

感谢任何建议!

1 个答案:

答案 0 :(得分:2)

将数据库连接作为参数传递到您的类中是使用依赖注入,也许您只是不认识它。对调用者中的连接字符串进行硬编码仍然是不依赖的代码,但至少您的数据库访问者本身不依赖于全局连接。

Globals不仅仅是邪恶的,因为它们会在没有通知的情况下发生变化 - 这只是因为糟糕的设计选择而导致的一种效果。它们是邪恶的,因为使用它们的设计是脆弱的。依赖于全局变量的代码需要在调用之前正确设置不可见的东西,这会导致不相关代码之间的相互依赖性。看不见的东西变成了至关重要的东西。只读取内部使用全局变量的模块的接口,我怎么知道在调用它之前我必须调用SetupGlobalThing()方法?如果我以不同的顺序调用IncrementGlobalThing()和DecrementGlobalThing()以及MultiplyGlobalThing()会发生什么情况,具体取决于用户选择的函数?

相反,更喜欢无状态方法,其中传递所有要更改和使用的东西:IncrementThing(整数事物)不依赖于隐藏的设置步骤。它显然做了一件事:它增加了传入的东西。

从单元测试的角度考虑它可能会有所帮助。如果你要编写一个单元测试来证明一个特定的代码模块工作,你需要传递一个真正的数据库连接(硬*),还是你能够传递一个虚假的数据库参考,轻松满足你的测试需求?

测试逻辑的最佳方法是对其进行单元测试。测试类接口和方法结构的最佳方法是编写调用它们的单元测试。如果这个类很难测试,那很可能是因为依赖于外部事物(全局,单例,数据库,不适当的成员变量等)。

  • 我使用真实数据库“硬”调用的原因是单元测试需要简单快速地运行。它不应该依赖缓慢或易碎或复杂的外部事物。考虑在总线上对您的软件进行单元测试,没有网络连接。想想创建虚拟数据库需要做多少工作:你必须添加用户,你必须拥有正确的模式版本,必须安装它,必须填写正确的测试数据,你需要网络连接,所有这些都会让你的测试变得不可靠。相反,在单元测试中,您传入一个模拟数据库,该数据库只返回执行测试代码的值。