包装现有库的正确设计是什么?

发布于 2024-12-14 06:35:18 字数 1725 浏览 1 评论 0原文

我在 .NET 中完成了几个小型个人项目,并遵循 SO 的建议,决定做一些更高级的事情,以便我可以边学习边做。

目前,我正在编写一个项目来增强现有的第三方库,以便我将编写的另一个应用程序可以更轻松地使用它的对象。

在第三方库中,我专注于一个对象,我们将其称为DataSource,它又包含与数据库相关的结果。对于一个小例子(这里的对象有更多未显示的方法和属性),它有一个属性“树”,如下所示:

A_DataSet -> A_结果-> A_Dimensions() -> A_Dimension -> A_SetDisplayType(DisplayAs)

这里,Result 对象有一个名为 Dimensions 的属性,其中包含 Dimension 的集合。最后,每个Dimension 都有一个名为SetDisplayType 的方法,该方法控制Dimension 中另一个属性中包含的数据的显示。这些元素以 A_ 为前缀只是为了本示例的目的。

现在,由于第三方库的方法和属性有时使用起来很混乱,而且性质众多,我想为这个库创建一个“包装器”,以便简化它的使用和结构。在对如何更逻辑地对元素进行相当多的深思熟虑之后,我考虑了结构的以下方向:

B_DataSet -> B_Dimensions() -> B_维度-> B_DisplayProperties-> B_SetDisplayType(DisplayAs)

在这个例子中,我在对象前面加上了 B_ 前缀只是为了将它们与上面现有的元素区分开来,当然这不是最终的命名约定(实际上命名并不对于这个问题的目的来说确实很重要)。

我所坚持的一点是我应该如何从包装类中正确引用第三方对象(A_*)。例如,如果我想使用B_SetDisplayType,那么这将在内部调用A_SetDisplayType。但是,由于 A_SetDisplayType 属于 A_Dimension,因此我需要在 B_DisplayProperties 中引用 A_Dimension。 创建对象时可以在构造函数中向它们传递对其“父级”的引用吗?我正在考虑类似以下代码的内容:

Public Class DataSetDisplayProperties

    Private _A_Dimension as A_Dimension

    Public Sub New(MyDimension as A_Dimension)

        _A_Dimension = MyDimension

    End Sub

    Public Sub B_SetDisplayType(DisplayAs as Integer)

        Call _A_Dimension.A_SetDisplayType(DisplayAs)

    End Sub

End Class

这看起来不错,还是有更好的方法?

我正在考虑使用外观,但当我尝试将不同“级别”的方法引用到现有结构时,不确定这将如何工作。

请注意,我不能继承任何第三方类,也不能更改它们的代码。

如果上面的内容看起来有点混乱,我很抱歉,我想我可能不知道如何表达我的问题的正确术语。谢谢你!

I have done a couple of small personal projects in .NET and following the advice on SO have decided to do something a bit more advanced so that I can learn as I go.

At the moment I am writing a project to enhance an existing third-party library so that its objects may be consumed easier by another application that I will write.

In the third-party library, I am concentrating on one object, let's call it DataSource and this in turns contains results pertaining to a database. For a small example (the objects here have a lot more methods and properties not shown), this has a "tree" of properties as follows:

A_DataSet -> A_Result -> A_Dimensions() -> A_Dimension -> A_SetDisplayType(DisplayAs)

Here the Result object has a property called Dimensions which contains a collection of Dimension. Finally each Dimension has a method called SetDisplayType which controls the display of the data contained within another property in Dimension. The elements are prefixed with A_ just for the purposes of this example.

Now, as the third-party library's methods and properties are sometimes confusing to use and numerous in nature, I wanted to create a "wrapper" to this library so that I simplify its use and structure. After quite a bit of deliberation on how to more logically group elements, I thought about going in the following direction with the structure:

B_DataSet -> B_Dimensions() -> B_Dimension -> B_DisplayProperties -> B_SetDisplayType(DisplayAs)

In this example, I prefixed the objects with B_ just to distinguish them from the existing elements above, of course this is not the final naming convention (actually naming doesn't really matter for the purposes of this question).

The point that I am stuck on is how I should properly reference the third-party objects (A_*) from the wrapper class. For example, if I wanted to use B_SetDisplayType then this would internally call A_SetDisplayType. However, since A_SetDisplayType belongs to A_Dimension then I would need a reference to A_Dimension in B_DisplayProperties.
Is it okay when creating objects to pass them a reference to their "parent" in their constructor? I was thinking about something like the following code:

Public Class DataSetDisplayProperties

    Private _A_Dimension as A_Dimension

    Public Sub New(MyDimension as A_Dimension)

        _A_Dimension = MyDimension

    End Sub

    Public Sub B_SetDisplayType(DisplayAs as Integer)

        Call _A_Dimension.A_SetDisplayType(DisplayAs)

    End Sub

End Class

Does this seem fine, or is there a better method?

I was thinking about using a facade, but was unsure of how this would work when I am trying to reference methods at different "levels" to what the existing structure is.

Please note that I cannot inherit from any of the third-party classes and cannot change the code of them.

Apologies if the above seems a bit confused, I think I perhaps don't know the correct terminology for how to express my issue. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最单纯的乌龟 2024-12-21 06:35:18

这似乎不是这个问题的答案,当然不是直接的答案,但请听我说。首先,我认为当你说你想构建一个外观时,你是对的。我可以建议您使用测试驱动开发方法来开发此外观的接口,然后您可以专注于如何使用第三方库来实现该接口。这将使您清除第三方库的特性和命名约定,并专注于想要提供的接口以及您希望它实现的目标。它还将产生围绕您的 Facade 实现的单元测试套件。

如果您以前没有使用过 TDD,那么您将需要经历相当长的一段时间,但我可以向您保证,这是非常值得的投资。就工具而言,我推荐 NUnit 和 MOQ。您可能还需要一个 IoC 容器,例如 Unity 2.0。

祝你好运!

This may not seem like an answer to this question, certainly not a direct one, but stay with me. First of all I think you are right when you say you want to build a Facade. Can I suggest that you use a Test Driven Development approach to develop the interface for this facade and then you can focus on how to implement that interface using the third party library. This will enable you to clear your mind of the idiosyncrasies and naming conventions of the third party library and focus purely the interface that want to provide and what you want it to achieve. It will also result in a unit test suite around your Facade implementation.

If you havn't used TDD before then you have quite a curve to go through, but I can assure you it is well worth the investment. In terms of tools I recommend NUnit and MOQ. You may also need an IoC container, like Unity 2.0.

Good Luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文