假设您不是在寻找一个模拟框架,因为它们无处不在且易于查找,因此需要注意以下几点:
- 您永远不会“做”任何事情。
包装第三方库并不总是最好的。如果您的应用程序本质上依赖于一个库,或者它实际上是围绕一个或两个核心库构建的,请不要浪费您的时间来打包它。如果库发生更改,则您的应用程序仍将需要更改。
- 可以使用集成测试。
在稳定的边界,应用程序固有的边界或无法轻松模拟的边界周围尤其如此。如果满足这些条件,则包裹和嘲弄将是复杂且乏味的。在那种情况下,我会避免两种情况:不要包装也不嘲笑;只需编写集成测试。(如果自动测试是目标。)
- 工具和框架无法消除逻辑上的复杂性。
原则上,工具只能在样板上切割。但是,并没有采用自动化算法来采用复杂的界面并使之变得简单-更不用说采用界面X并对其进行调整以适应您的需求了。(只有您知道该算法!)因此,毫无疑问,虽然可以生成精简包装器的工具,但我建议它们尚无处不在,因为最终您仍然需要智能地进行编码,因此需要手动进行编码,接口,即使它隐藏在包装器后面。
这就是说,有战术,你可以在许多语言使用,以避免直接引用的类。在某些情况下,您可以“伪装” 实际上不存在的接口或精简包装。例如,在C#中,我会选择以下两种方法之一:
- 使用工厂和隐式类型。
您可以避免用这个小组合完全包装一个复杂的类:
// "factory"
class PdfDocumentFactory {
public static ExternalPDFLibraryDocument Build() {
return new ExternalPDFLibraryDocument();
}
}
// code that uses the factory.
class CoreBusinessEntity {
public void DoImportantThings() {
var doc = PdfDocumentFactory.Build();
// ... i have no idea what your lib does, so, I'm making stuff but.
// but, you can do whatever you want here without explicitly
// referring to the library's actual types.
doc.addHeader("Wee");
doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
return doc.exportBinaryStreamOrSomething();
}
}
如果你能避免存储这些对象的成员,无论是通过一个更加“实用”法或将它们存储在一个字典(或什么),这种方法有编译时类型检查的好处没有你的核心业务实体需要知道确切他们正在上什么课。
所需要做的就是在编译时,工厂返回的类实际上具有您的业务对象正在使用的方法。
- 使用动态类型。
这与使用隐式类型是一样的,但是涉及另一个折衷方案:您将丢失编译类型检查,并且能够匿名地将外部依赖项添加为类成员并注入您的依赖项。
class CoreBusinessEntity {
dynamic Doc;
public void InjectDoc(dynamic Doc) {
Doc = doc;
}
public void DoImortantThings() {
Doc.addHeader("Wee");
Doc.getAllText().makeBiggerBy(4).makeBold().makeItalic();
return Doc.exportBinaryStreamOrSomething();
}
}
使用这两种策略,当需要进行模拟时ExternalPDFLibraryDocument
,就像我之前提到的那样,您需要做一些工作-但是,无论如何,这是您需要做的工作。而且,通过这种构造,您避免了繁琐地定义100个瘦小的包装器类的麻烦。在大多数情况下,您只是简单地使用了库而无需直接查看它。
综上所述,我仍然会考虑三个主要理由来明确包装第三方库-没有一个可以暗示使用工具或框架:
- 特定的库不是应用程序固有的。
- 如果不打包就进行交换将非常昂贵。
- 我不喜欢API本身。
如果我在所有这三个领域中都没有任何关注点,那么您无需付出任何大的努力就可以完成它。而且,如果您在所有这三个方面都存在担忧,那么自动生成的薄包装实际上并没有帮助。
如果您决定包库时,最有效和最有效地利用你的时间是建立你对你的界面应用需要 ; 不针对现有的API。
换句话说,请遵循经典建议:推迟所有可能的决定。首先构建应用程序的“核心”。对代码的接口,这将最终你想要什么,这将最终通过“周边的东西”是不存在兑现。缩小差距。
这种努力可能不会觉得像时间保存的; 但是,如果您觉得需要包装纸,这是安全进行包装的最有效方法。
这样想吧。
您需要在代码的某些暗处针对该库进行编码- 即使已包装好。如果您在测试过程中对库进行了模拟,那么那里就不可避免地要进行手动操作- 即使已将其打包。但是,这并不意味着您需要在应用程序的大部分内容中直接按名称确认该库。
TLDR
如果该库值得包装,请使用策略来避免对第三方库的广泛直接引用,但不要采用捷径来生成精简包装。首先建立您的业务逻辑,仔细考虑您的接口,然后根据需要有机地出现您的适配器。
而且,如果涉及到这一点,请不要害怕集成测试。它们有点模糊,但是它们仍然提供了工作代码的证据,并且仍然可以很容易地制作它们以阻止回归。