2013-03-13 63 views
2

我正在使用C#为我们的应用程序构建一个公共API。我有一组与WCF客户端一起使用的DTOs外观类。它允许API消费者从数据库应用程序中获取,更新,创建等等。标准材料:客户拥有订单集合,订单中包含行项目集合等。不允许任意实现时使用接口隐藏实现细节

外观类都来自公共基类,并覆盖验证,读取/写入DTO和其他管道的方法东西,全部使用各种内部类型。我正在使用工厂创建新对象并获取现有对象。

现在的问题是如何最好地通过API公开类,同时最大限度地减少实现细节的暴露。

接口看起来像是一种明显的方法,因为它是限制暴露内容的最简单方法(并且最终可能是必需的,因为COM兼容接口正在考虑之中)。接口方法的问题是内部我的代码将取决于接口的特定实现。

假设我有一个ICustomer接口暴露了我的CustomerFacade,IOrder暴露了OrderFacade。在外部,ICustomer拥有一系列IOrders。但在内部,CustomerFacade有一个OrderFacades集合。如果客户端应用程序向客户添加一个新的IOrder,我必须检查IOrder是否真的是一个先前从我的工厂创建的OrderFacade,而不是我的控制之外实现IOrder的其他对象。那是因为在内部,我需要一个能够比IOrder做得更多的命令。

实际上,这并不重要 - API的用户不会尝试创建自己的Order实现。但对我来说,这感觉不雅,就像滥用界面合同应该是什么意思一样。

直接暴露外观类并不是很好,因为整个类层次结构必须暴露,以及受保护方法使用的内部类型,并且使用消费者不会使用的类型将API混淆并不需要知道。

我能想到的另一种选择是另一层封装:一个订单包含一个私有的OrderFacade,并且只公开应该公开的成员。但是这看起来像是很多额外的代码来获得有限的好处。

我认为是抽象基类,但由于继承结构的原因,这并不比暴露外观类更好。例如,如果我有一个从CatalogItem继承的ServiceItem,在它们之间引入一个抽象的ServiceItemBase仍然需要我公开CatalogItem中的所有受保护的方法。

对这些方法的任何建议,或者我没有看过的替代方案?

+2

您始终可以将OrderFacade实现为可用OrderId构造,并且完全忽略接口。您的客户不会重塑您的订单工作方式,他们只想输入数字并获得答案。看一下微软自己的C#API--很少有接口,它们只在需要的时候才出现,比如COM,而且你仍然不知道或者不在乎它们是如何工作的。所有你想要的是给Word API一个文件名并获得一个Word文档,而不是自己实现IDocument – 2013-03-13 14:27:23

+0

@StenPetrov谢谢,但我不明白这是如何解决如何最好地隐藏内部细节我不知道不想泄漏到API中。 – William 2013-03-13 16:24:29

+0

你已经有了服务 - 这就是大多数(如果不是全部的话)魔术应该发生的地方。 API的客户端应主要用于调用服务(验证,配置处理等)。我所说的并不是跳入抽象的过程(界面,抽象类,工厂等)。 – 2013-03-13 16:53:42

回答

0

这似乎很复杂。我不知道你想解决的业务问题,所以我不知道为什么需要各种外墙。如果用户将使用您的api进行数据操作,您可以考虑使用命令修改数据,并查询返回仅包含客户端所需数据的DTO。

http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613

这是一个伟大的书,可能的帮助。

+0

看起来像一个很好的参考。我会看看是否有什么我可以申请的东西。 – William 2013-03-13 16:37:44

0

您也可以使用公共构造函数而不是接口公开构造函数暴露抽象类。这还有另外一个好处,就是抽象类可以作为一个不间断的变化来扩展,这对于接口来说是不正确的。

使用内部访问修饰符可以隐藏不应该在实现程序集中可见的成员。

+0

我应该在问题中提到该选项;我已更新以解决这个问题。抽象基础在我这里不起作用,因为它们仍然继承自其上面的类(并因此暴露了受保护的成员)。 – William 2013-03-13 16:34:19

+0

这不就是为什么提供内部访问修饰符? – 2013-03-13 16:36:30

+0

好点。我可以将所有受保护的成员更改为内部。这暴露了大会之外的一些事情,但在这种情况下这不是一个大问题。 – William 2013-03-13 17:45:32