你应该在什么命名空间中放置相对于它们的实现者的接口?

时间:2008-09-28 21:23:56

标签: oop interface namespaces

具体来说,当你创建一个接口/实现者对,并且没有重要的组织关注点(比如接口应该放在不同的程序集中,即按照s#体系结构的建议)你是否有一种默认的组织方式它们在您的命名空间/命名方案中?

这显然是一个基于意见的问题,但我认为有些人已经考虑过这个问题,我们都可以从他们的结论中受益。

9 个答案:

答案 0 :(得分:15)

答案取决于你的意图。

  • 如果您希望命名空间的使用者在具体实现上使用接口,我建议您将接口放在顶级命名空间中,并在子命名空间中使用实现
  • 如果消费者要同时使用它们,请将它们放在同一名称空间中。
  • 如果接口主要用于专门用途,例如创建新实现,请考虑将它们放在子命名空间中,例如Design或ComponentModel。

我确信还有其他选项,但与大多数命名空间问题一样,它归结为项目的用例,以及它包含的类和接口。

答案 1 :(得分:7)

我通常将接口保持在与具体类型相同的名称空间中。

但是,这只是我的观点,命名空间布局非常主观。

Animals
|
| - IAnimal
| - Dog
| - Cat
Plants
|
| - IPlant
| - Cactus

通过将一个或两个类型移出主命名空间,您实际上并没有获得任何好处,但是您确实需要添加一个额外的using语句。

答案 2 :(得分:6)

我通常做的是在我的层次结构中创建一个高级别的Interfaces命名空间并将所有接口放在那里(我不打算在其中嵌套其他命名空间,因为我最终会得到许多只包含一个接口的命名空间)。

Interfaces
|--IAnimal
|--IVegetable
|--IMineral
MineralImplementor
Organisms
|--AnimalImplementor
|--VegetableImplementor

这就是我过去做过的方式,而且我没有遇到过很多问题,不过可以肯定的是,对于那些坐在我的项目中的人来说,这可能会让人感到困惑。我很好奇看到其他人做了什么。

答案 3 :(得分:3)

我更喜欢将接口和实现类保存在同一名称空间中。在可能的情况下,我给实现类内部可见性并提供工厂(通常以委托给工人类的静态工厂方法的形式,使用允许在朋友程序集中进行单元测试的内部方法来替换不同的工作者产生存根)。当然,如果具体类需要公开 - 例如,如果它是一个抽象基类,那就没关系;我认为没有理由将ABC放在自己的命名空间中。

另外,我非常不喜欢使用字母'I'来表示接口名称的.NET约定。 (I)Foo界面模型的东西不是 ifoo ,它只是一个 foo 。那么为什么我不能称之为Foo?然后我具体命名实现类,例如,AbstractFoo,MemoryOptimizedFoo,SimpleFoo,StubFoo等。

答案 4 :(得分:1)

(。Net)我倾向于将接口保存在一个单独的“通用”程序集中,这样我就可以在多个应用程序中使用该接口,更常见的是,在我的应用程序的服务器组件中使用该接口。

关于名称空间,我将它们保存在BusinessCommon.Interfaces中。

我这样做是为了确保我和我的开发人员都不想直接引用这些实现。

答案 5 :(得分:1)

当我在同一名称空间/程序集中找到接口和实现时,我很讨厌。请不要这样做,如果项目进展,重构的麻烦就会很痛苦。

当我引用一个接口时,我想实现它,而不是实现它的所有实现。

我可以接受的是将接口与其依赖类(引用接口的类)放在一起。

编辑:@Josh,我正在读我的最后一句,这令人困惑!当然,依赖类和实现它的类都引用了接口。为了使自己清楚,我将举例说明:

可接受:

接口+实施:

namespace A;

   Interface IMyInterface
   {
       void MyMethod();
   }

namespace A;

   Interface MyDependentClass
   {
       private IMyInterface inject;

       public MyDependentClass(IMyInterface inject)
       {
           this.inject = inject;
       }

       public void DoJob()
       {
           //Bla bla
           inject.MyMethod();
       }
   }

实施班级:

namespace B;

   Interface MyImplementing : IMyInterface
   {
       public void MyMethod()
       {
           Console.WriteLine("hello world");
       }
   }

不可接受:

namespace A;

   Interface IMyInterface
   {
       void MyMethod();
   }

namespace A;

   Interface MyImplementing : IMyInterface
   {
       public void MyMethod()
       {
           Console.WriteLine("hello world");
       }
   }

请不要为你的界面创建项目/垃圾!示例:ShittyProject.Interfaces。你错过了这一点!

想象一下,您创建了一个为您的接口保留的DLL(200 MB)。如果您必须使用两行代码添加单个界面,则您的用户必须仅为两个哑名签名者更新200 MB!

答案 6 :(得分:0)

以某种方式分离接口(Eclipse中的项目等),以便只部署接口。这允许您在不提供实现的情况下提供外部API。这允许依赖项目以最少的外部构建。显然,这更适用于较大的项目,但在所有情况下这个概念都很好。

答案 7 :(得分:0)

我通常将它们分成两个独立的组件。接口的一个常见原因是让一系列对象看起来与软件的某个子系统相同。例如,我的所有报告都实现了IReport接口。 IReport不仅用于打印,还用于预览和选择每个报告的各个选项。最后,我在对话框中使用了一个IReport集合,用户可以选择要打印的报表(和配置选项)。

报告驻留在一个单独的程序集中,IReport,预览引擎,打印引擎,报告选择位于各自的核心程序集和/或UI程序集中。

如果使用工厂类返回报告程序集中的可用报告列表,则使用新报告更新软件只会将新报告程序集复制到原始报告上。您甚至可以使用Reflection API来扫描任何报告工厂的程序集列表,并以这种方式构建报告列表。

您也可以将此技术应用于文件。我自己的软件运行金属切割机,所以我们将这个想法用于我们与软件一起销售的形状和装配库。

同样,实现核心接口的类应该驻留在一个单独的程序集中,这样您就可以将其与其他软件分开更新。

答案 8 :(得分:0)

我给出了自己的经验,反对其他答案。

我倾向于将所有接口都放在他们所属的包中。这样就可以了,如果我在另一个项目中移动一个包,我就必须运行包而不做任何改动。

对我来说,作为类功能的一部分的任何辅助函数和操作符函数都应该与该类的命名空间相同,因为它们构成了该命名空间的公共API的一部分。

如果您在不同的包中共享相同的接口,则可能需要重构项目。

有时我发现项目中有很多接口可以在抽象实现中转换而不是接口。

因此,问问自己是否真的在建模类型或结构。