2009-06-14 42 views
4

我最近在为我的主要个人项目寻找一些依赖关系图,并且我注意到我在嵌套命名空间中的对象之间存在相互依赖关系。例如,我在MyNamespace.Foo中有一个对象,它在MyNamespace.Foo.Interfaces中实现了一个通用接口,该对象作为接口中的通用参数。相互依赖的子/父命名空间代码味道?

namespace MyNamespace.Foo 
{ 
    internal class Foo : MyNamespace.Foo.Interfaces.IFoo<Foo> 
    { } 
} 

在这种情况下。依赖分析工具(VS2010 beta)合理地将接口的通用“实例化”(出于讨论的缘故,我知道这不是C++)作为Interfaces命名空间的成员,然后依赖于它的父命名空间。

经过我的一些考虑后,我或多或少地得出结论,我的现有设计在我的特殊情况下是一种代码味道。我应该将Interfaces命名空间合并到父Foo命名空间中。 (如果我希望它们通过IFoo使用Foo,要求客户端向接口命名空间钻取额外的图层是愚蠢的。)然而,在一般情况下,这是否正确?

应如何管理内部名称空间依赖关系?应该“更广泛”的命名空间(如MyNamespace.Foo一般依赖于“窄”的命名空间(如MyNamespace.Foo.Interfaces),还是应该窄些命名空间依赖于更加广泛的问题?或者是有一些更好的,更微妙的答案吗?

回答

2

在特定的情况下,关于你的榜样,我会合并Interfaces命名空间到父命名空间

一般来说,我认为狭窄的命名空间应该依赖于更广泛的类或接口,或者是共享父命名空间的子类。通常情况下,如果您安排了命名空间,以便模型名称空间具有共享的类或接口,以描述您的代码尝试解决的问题的模型,请参阅

我还应该注意到,我不认为这些规则必然适用于第三方依赖项。例如,取决于代码中来自Spring.NET中狭窄名称空间的代码不会构成代码异味。

2

如果你想从实现中分离接口,可能会并行MyNamespace.Foo.Interfaces和MyNamespace.Foo.Implementation命名空间。

默认似乎是一个命名空间相当于一个包或组件:如此FooBar将分别为foo.dllbar.dll的命名空间。

如果我想要更高级别的分组,我会向名称空间添加前缀:例如,MyCorp.Server.Foo是由MyCorp生成的服务器端foo.dll的名称空间。

请注意,我要添加前缀,而不是后缀:所以MyCorp.Server.Foo而不是Foo.Server.MyCorp。这些结构化命名空间对应于包含源代码和项目的文件夹/目录结构。

默认情况下,包中的所有文件都具有相同的名称空间(例如foo.dll中的所有代码都属于MyCorp.Server.Foo名称空间)。如果我添加了一个后缀,这就会从程序集的其余部分隐藏该代码。例如,MyCorp.Server.Foo.EditorTransactions名称空间中的代码存在于foo.dll中,但foo.dll中的大多数其他代码都看不到(除了明确使用MyCorp.Server.Foo.EditorTransactions的代码外)。