在不同的项目中与类实现分离的接口?
我们在一个中等规模的项目上工作(3个开发人员超过6个月),需要作出以下决定:我们希望将接口与具体的实现分离开来。 首先是将界面存储在一个单独的文件中。
我们希望进一步分离数据:我们希望在一个.CS文件中join一个带有接口的项目(CSPROJ)以及带有帮助类的另一个.CS文件(就像这个接口中使用的一些公共类一样,一些枚举等)。 然后,我们想要另一个工厂(CSPROJ)具有工厂模式,具体的接口实现和其他“工人”类。
任何想要创build实现这个接口的对象的类都必须包含第一个包含接口和公共类的项目,而不是实现本身。
这个解决scheme有一个很大的缺点:它将程序集数量乘以2,因为每个“正常”项目都有一个带有interace的项目,另一个带有实现。
你会推荐什么? 你认为把所有的接口放在一个独立的项目中,而不是在自己的项目中放置一个接口是个好主意吗?
我会区分这样的接口:
-
独立的接口,其目的是你可以描述,而不用谈论你的项目的其余部分。 把这些放在一个专用的“接口组件”中,这个接口组件可能是你项目中所有其他组件引用的。 典型的例子:
ILogger
,IFileSystem
,IServiceLocator
。 -
类耦合的接口 ,只有在项目类的上下文中才有意义。 把它们放在与它们耦合的类相同的程序集中。
举个例子:假设你的域模型有一个
Banana
类。 如果您通过IBananaRepository
界面获取香蕉,那么该界面与香蕉紧密结合。 在不知道香蕉的情况下实现或使用界面是不可能的。 因此,接口与Banana
位于同一个程序集中是唯一合理的。前面的例子有一个技术耦合,但耦合可能是合乎逻辑的。 例如,即使接口声明与
Monkey
没有技术上的联系,IFecesThrowingTarget
接口也只能作为Monkey
类的协作者。
我的答案取决于这样的概念,即可以有一些耦合类。 隐藏界面后面的所有内容都是一个错误。 有时候可以“新build”一个class级 ,而不是通过工厂注入或创build。
是的,我认为这是一个好主意。 实际上,我们一直在这里做,而且我们最终必须这样做,原因很简单:
我们使用Remoting来访问服务器function。 因此,服务器上的远程对象需要实现接口,客户端代码必须能够访问接口来使用远程对象。
一般来说,当你把接口放在一个单独的项目中时,我认为你更松散耦合,所以只需要去做就可以了。 有2个组件不是一个真正的问题,是吗?
加成:
我只是想:把接口放在一个单独的程序集中,如果其中一些接口足够普遍的话,还可以重用这些接口。
我认为你应该首先考虑ALL接口是否属于你的项目的“公共接口”。
如果他们是由多个项目,可执行文件和/或服务共享,我认为把它们放入一个单独的程序集是公平的。
但是,如果它们仅供内部使用,并且为了您的方便,您可以select将它们与实现保持在同一个程序集中,从而使程序集的总体数量相对较低。
我不会这样做,除非它为您的应用程序的体系结构提供了经证实的好处。
密切关注你正在创build的程序集的数量 。 即使一个接口和它的实现在同一个程序集中,你仍然可以通过一些训练来实现解耦。
如果一个接口的实现最终具有很多的依赖关系(在其他程序集等),那么在一个孤立的程序集中拥有接口可以简单地为更高层次的消费者生活。
他们可以引用接口而不会无意中依赖于特定实现的依赖关系。
我们以前在共享代码中有相当多的独立程序集。 随着时间的推移,我们发现我们几乎总是将这些分组引用。 这为开发人员做了更多的工作,我们不得不寻找一个类或接口是什么组合。我们结合了一些基于使用模式的程序集。 生活变得容易了。
这里有很多的考虑因素 – 你是为开发人员编写一个库,你是否将DLL部署到离线客户,你使用远程(感谢,Maximilian Mayerl)或者编写WCF服务等等。没有一个正确的答案 – 它依靠。
总的来说,我同意Jeff Sternal的观点 – 除非事实certificate,否则不要拆散集会。
这种方法有利有弊,而且还需要根据最适合您的架构方法来调整决策。
在“专业”方面,您可以实现一定程度的分离,以帮助实施接口的正确实施。 考虑一下,如果您的初级或中级开发人员正在从事实现工作,则可以在只有读取权限的项目中定义接口本身。 也许高级,团队领导或架构师负责接口的devise和维护。 如果在多个项目中使用这些接口,则可以帮助减轻仅在其中工作的其他项目发生意外中断更改的风险。 另外,如果您与分发API的第三方供应商合作,打包接口是一件非常好的事情。
显然,有一些不利的一面。 程序集不包含可执行代码。 在我工作过的一些商店里,不pipe是什么原因,他们都皱起了眉头,没有function。 肯定会有额外的开销。 根据您设置物理文件和名称空间结构的方式,可能会有多个程序集执行相同的操作(尽pipe不是必需的)。
在一个半随机的说明中,确保很好地logging你的接口。 从使用GhostDoc的接口inheritance文档是一件很美的事情。