0

全球人是邪恶的,对吧?至少我读到的所有内容都是这样说的,因为某些事情可能会在任何时候改变全局的状态。

但是,我有一个关于类参数的 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,所以我认为我可以通过记录它们并在它为 Null 时重新初始化 DB 来有条件地处理 oledb 错误。

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

鉴于我们还没有使用依赖注入,因为我需要学习它;全球财产有那么糟糕吗?数据被拉入或保存的任何地方都需要 Db。我根本不需要它的唯一地方是视图及其背后的代码。

这不是一个面向客户的项目,但它确实需要可靠。

任何建议都感激不尽!!

4

1 回答 1

2

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

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

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

从单元测试的角度考虑它可能会有所帮助。如果您要编写单元测试来证明特定的代码模块有效,您是否需要传递真实的数据库连接(硬*),或者您是否能够轻松传递满足您的测试需求的假数据库引用?

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

  • 我之所以称使用真正的数据库为“硬”,是因为单元测试需要简单快速地运行。它不应该依赖于缓慢、易碎或复杂的外部事物。考虑在没有网络连接的情况下在总线上对您的软件进行单元测试。想想创建一个虚拟数据库需要做多少工作:您必须添加用户,您必须在其中拥有正确版本的模式,必须安装它,必须填充正确类型的测试数据,您需要与它的网络连接,所有这些都会使您的测试不可靠。取而代之的是,在单元测试中,您传入一个模拟数据库,该数据库仅返回执行您正在测试的代码的值。
于 2013-01-16T17:28:44.493 回答