【问题标题】:Interface naming convention [closed]接口命名约定[关闭]
【发布时间】:2010-10-15 11:11:18
【问题描述】:

这当然是一个主观的事情,但我认为在接口名称前加上“I”没有任何积极意义。对我来说,Thing 实际上总是比IThing 更具可读性。

我的问题是,为什么这个约定存在呢?当然,它更容易将接口与其他类型区分开来。但是这个论点难道不会延伸到保留现在受到广泛谴责的匈牙利符号吗?

对于那个尴尬的“我”,你的论据是什么?或者,更重要的是,微软的可能是什么?

【问题讨论】:

  • 改用语法怎么样? Fruit在英语中是一个Object,所以在编程中应该是一个Class。 Iterable 和 Comparable 显然是接口。在水果示例中,您可以使用 Sliceable、JuiceExtraction 等

标签: c# interface naming-conventions


【解决方案1】:

约定(以及对它们的批评)都有其背后的原因,所以让我们总结一下约定背后的一些原因

  • 接口前缀为 I 以区分接口类型和实现 - 例如,如上所述,需要一种简单的方法来区分 Thing 和它的接口 IThing 所以公约就是为了这个目的。

  • 接口以 I 为前缀以区别于抽象类 - 当您看到以下代码时会有歧义:

    public class Apple: Fruit

    如果没有约定,我们将无法知道 Apple 是否继承另一个名为 Fruit 的类,或者它是否是名为 @ 的接口的实现 987654327@,而IFruit 会很明显:​​

    public class Apple: IFruit

    适用最小意外原则。

  • 并非所有匈牙利符号的使用都受到谴责 - 匈牙利符号的早期使用表示一个前缀,该前缀表示对象的类型,然后是变量名,有时是变量名之前的下划线。这对于某些编程环境(想想 Visual Basic 4 - 6)很有用,但随着真正的面向对象编程越来越流行,指定类型变得不切实际和多余。当涉及到智能感知时,这变得尤为重要。

    如今,匈牙利符号可用于区分 UI 元素与实际数据和类似的相关 UI 元素,例如,txtObject 用于文本框,lblObject 用于与该文本框关联的标签,而文本框的数据是只需Object

    我还必须指出,匈牙利表示法的最初用途不是用于指定数据类型(称为 System Hungarian Notation),而是指定变量名称的语义使用(称为 Apps Hungarian Notation)。在wikipedia entry on Hungarian Notation 上阅读更多信息。

【讨论】:

  • 另外,接口可能感觉很糟糕,因为它们实际上并没有做任何事情。添加 I 通过让他们感觉更酷来弥补这一点。 iPod、IMac、iPhone 等也是如此。I 让它们看起来更酷。
  • 哈哈!当然,接口的作用远不止于此,Svish。
  • +1 表示“让他们感觉更酷”
  • I 也是大多数接口所代表的 HAS-A 属性的有用记号 - IHasDataIHasCookieIHasCheezburger...
  • 哈哈,这变成了一个笑话。一天的精彩插曲。
【解决方案2】:

我这样做的原因很简单:因为这是惯例。我宁愿只是遵循它,也不愿让我的所有代码看起来都不同,从而使其更难阅读和学习。

【讨论】:

  • 在您的代码中遵循all 中的I-less 约定怎么样? (我想我会在下一个项目中做到这一点。)
  • 如果我在你的项目中寻找接口并且比需要的时间长了十分钟,我会非常生气。
  • 你可以这样做,但我希望我的所有代码看起来都像其他人的代码(包括 MS)。大家都知道“I”是interface的意思,这样别人就更容易理解我的代码了。
  • 这是循环逻辑乔恩。 “因为它就是这样做的”对于很多人来说可能是足够好的理由,但我们中的一些人喜欢相信我们所做的事情。
  • @ted - 我的逻辑是你应该遵循这个约定,因为它会提高代码的可读性和可维护性。我不认为这是循环的。
【解决方案3】:

嗯,一个明显的考虑是(非常常见的)IFooFoo 对(当抽象 Foo 时),但更一般地说,知道某物是接口还是类通常是基本的。是的,它部分是多余的,但 IMO 与 sCustomerName 之类的不同 - 在这里,名称本身 (customerName) 应该足以理解变量。

但是CustomerRepository - 它是一个类,还是抽象接口?

又作: 期望;事实是,无论对错,这都是人们所期望的。这就是几乎足够的理由。

【讨论】:

  • "但是使用 CustomerRepository - 它是一个类,还是抽象接口?"好吧,至少在 Visual Studio 中,只需将鼠标悬停在它上面。这难道不是编码工具可以比冗余约定更好地帮助我们的情况吗?匈牙利符号不是也被 Visual-Studio-hover 杀死了吗?
  • @Frederick - 我是用眼睛而不是鼠标来阅读的……如果我无法通过查看一行来理解它,那么该行就自动出错了。
  • 那么你为什么要关心它是一个接口还是一个类,尤其是在你编写客户端代码的时候?不在乎:这不正是抽象的目的,因此也是 OOP?
  • 好的,如果 Visual Studio 颜色编码的界面与类不同怎么办?这还不足以使区别明显吗?如果是这样,那不是微软应该首先提供的,而不是传播阻碍通信的约定吗?
  • 我认为我们永远不会在这里达成一致。我没有看到“阻碍交流的约定”...
【解决方案4】:

ThingIThing 更易读。我来自认为我们应该针对接口而不是特定实现进行编程的学派。所以一般来说,接口应该优先于实现。我更喜欢为接口而不是实现提供更易读的名称(即,我的接口的命名不带“I”前缀)。

【讨论】:

  • 让我们把I作为实现前缀! ;)
【解决方案5】:

我确信您的问题是 Microsoft 团队中许多长期讨论的主题,该团队致力于 .NET Framework 及其标准。

我认为最有说服力的例子来自源本身。下面,我抄录了我强烈推荐的一本书Framework Design Guidelines 的摘录。

来自 CLR 项目经理 Krzysztof Cwalina:

接口使用的唯一前缀是“I”(如ICollection),但这是出于历史原因。回想起来,我认为使用常规类型名称会更好。例如,在大多数情况下,开发人员并不关心某个东西是接口而不是抽象类。

来自 Brad Abrams,CLR 和 .NET Framework 项目经理:

另一方面,接口上的“I”前缀清楚地认识到 COM(和 Java)对 .NET Framework 的影响。 COM 使接口以“I”开头的符号普及,甚至制度化。尽管我们讨论了与这种历史模式不同的问题,但我们决定继续沿用这种模式,因为我们的许多用户已经熟悉 COM。

来自顾问兼作家 Jeffrey Richter:

就个人而言,我喜欢“I”前缀,我希望我们有更多这样的东西。小的单字符前缀对保持代码简洁和描述性大有帮助。 [...] 我为我的私有类型字段使用前缀,因为我发现这非常有用。

我的意思是,它在讨论桌上。我看到的一个优点是它有助于避免类和接口之间的名称冲突,因此您的名称可以是描述性的和紧凑的

就个人而言——也许出于习惯——我喜欢I 前缀,因为它简洁地标记了接口,允许我与实现类型进行一对一的命名对应。这在您想要提供 base 实现的情况下会大放异彩:IThing 是接口,Thing 是基本(可能是 abstract)类型。派生类型可以是SomeThing。我喜欢能够使用如此清晰的速记符号。

【讨论】:

    【解决方案6】:

    我认为这比在具体类上添加“Impl”后缀要好。它是一个单一的字母,而且这个约定已经很成熟了。当然,您可以随意使用任何您喜欢的名称。

    【讨论】:

    • 一个可能的例外是接口类暴露在外部而实现是内部的。例如在 WCF 中。在这种情况下,我更喜欢公开服务“MyService”并拥有一个“MyServiceImpl”类,而不是向外部公开调用“IMyService”的东西
    • @Rob Walker - 你可以在 [ServiceContract(Name="MyService)] 中做到这一点
    • 我认为“Impl”是一种 Java 约定,而不是 C#,但有些商店确实将它带到了 C# 中。不过,这不是一个坏主意,只要它是一致的。
    • 我喜欢 Impl 约定,因为在我实际使用我的界面的所有地方,*Impl 在我的 ioc 设置中使用的唯一地方。
    【解决方案7】:

    在我看来,这个“我”只是视觉上的噪音。 IDE 应该以不同的方式显示类和接口名称。幸运的是,Java 标准库不使用这种约定。

    【讨论】:

    • 以“我认为”开头的回复并不是很好的回复。在许多情况下都需要遵循官方指南,例如 .NET 和 Microsoft。 msdn.microsoft.com/en-us/library/8bc1fexb(v=vs.71).aspx
    • “Impl”后缀不只是 Java 中的视觉噪音吗? @Isaac 关于官方指南是正确的。
    • 幸好不是,“Impl”后缀比“I”前缀好很多... /s
    【解决方案8】:

    不对接口使用 I 约定并没有错 - 只要保持一致并确保它不仅适用于您而且适用于整个团队(如果有的话)。

    【讨论】:

      【解决方案9】:

      因为你通常有一个事物一个事物。因此,与其让人们为这种反复出现的情况制定自己的“约定”,不如选择一个统一的、万能的约定。与其他人所说的相呼应,事实上的标准足以使用它。

      【讨论】:

        【解决方案10】:

        这只是一个旨在防止名称冲突的约定。 C# 不允许我有一个名为 Client 的类和一个接口,即使文件名分别是 Client 和 IClient。我很乐意使用约定;如果我必须提供不同的约定,我建议使用“合同”作为后缀,例如客户合同。

        【讨论】:

          【解决方案11】:

          命名一个界面应该比你是否在名称前面加上“I”有更深层次的意义。

          “Fruit”和“IFruit”作为界面对我来说都没有很大的意义。这是因为它看起来更像一个类。类定义事物,而接口应该定义功能。

          “I”命名约定确实有助于区分类和接口,从而使开发更容易一些。虽然它不是必需的,但它肯定有助于避免常见的面向对象编码问题。 C# 和 Java 一样,只允许从单个基类继承。但是您可以实现任意数量的接口。需要注意的是,如果您从一个类继承并实现一个或多个接口,则必须首先命名基类(即类 Trout: Fish、ISwimmer、IDiver ...)。

          我真的很喜欢根据接口提供的功能以及接口类型(即动画或非动画接口)来命名我的接口。

          如果您专注于界面提供的功能,您可以快速确定界面的名称。它还可以帮助您快速查看您的界面是否定义了不相关的功能。

          定义无生命对象的接口(即不能自行行动的事物)... 我喜欢在最后用 ...able 来命名它们 IPrintable(如文档、发票) IPlayable(如 Instrument、MediaPlayer) ISavable(如 Document、Image) 可食用(如水果、牛肉) 可驱动(如汽车) IFlyable(如Plane)

          定义动画对象的接口(即自行作用的事物)... 我喜欢在最后用 ...er 命名它们 ISwimer(例如 Fish、Dog、Duck) IDiver(如鱼、鸭) IFlyer(例如 Pilot) IDriver(如 NascarDriver)

          最后,“I”命名约定有助于区分接口和类。但除了开头的“I”之外,添加额外的命名逻辑可能是有意义的。

          【讨论】:

            【解决方案12】:

            Do prefix interface names with the letter I to indicate that the type is an interface.

            该指南没有解释为什么您应该使用I 前缀,但现在这是一个既定的约定应该是足够的理由。

            删除I 前缀有什么好处?

            【讨论】:

            • "去掉 I 前缀有什么好处?"可读性。
            • @Frederick,删除 I 会失去可读性。您不再一眼就能看出某个东西是接口还是类。
            • 您需要知道某个东西是否是接口的唯一原因是您是否要尝试new 一些东西。当然,如果您遵守依赖倒置原则和/或使用依赖注入,那么某个东西是否是接口并不重要,因为您不会newing 很多东西。除此之外,IDE 能够很好地告诉您某物是否是接口。
            【解决方案13】:

            我不知道他们为什么选择这个约定,可能部分是想用“I”来赋予班级以“我是可枚举的”中的感觉。

            更符合框架其余部分的命名约定是将类型合并到名称中,例如 xxxAttribute 和 xxxException 类,使其成为 xxxInterface。不过这有点冗长,毕竟接口是独立的,而不仅仅是另一组类。

            【讨论】:

              【解决方案14】:

              我知道 Microsoft 指南建议使用“I”来将其描述为一个界面。但这来自 IBM 命名约定,如果我没记错的话,接口的初始“I”和实现的后续 *Impl。

              但是,在我看来,Java 命名约定是比 IBM 命名约定更好的选择(不仅在 Java 中,对于 C# 和任何 OO 编程语言也是如此)。接口描述了一个对象如果实现了接口可以做什么,并且描述应该是动词形式。即 Runnable、Serializable、Invoiceable 等。恕我直言,这是对接口所代表内容的完美描述。

              【讨论】:

                【解决方案15】:

                在我看来,它看起来像 Hungarianish。匈牙利语通常被认为是强类型语言的威胁。

                由于 C# 是 Microsoft 的产品,而匈牙利符号是 Microsoft 的发明,我可以看到 C# 可能会受到其影响。

                【讨论】:

                • 在强类型语言中使用匈牙利符号表示数据类型是毫无用处的。然而,匈牙利符号的初衷甚至不是用来表示数据类型,而是用来表示数据的其他更重要的属性,比如水平坐标与垂直坐标。 :)
                • 由于除了new 语句外,类和接口在语法上是可以互换的,我认为语言是强类型的说法站不住脚。除了 new 语句之外,您几乎希望在任何地方都使用接口类型(否则您的接口类型是多余的),但如果不清楚哪个是哪个,则很容易出错并使用实现类。
                【解决方案16】:

                操作系统 GUI 对文件和文件夹使用不同的图标很流行。如果它们都共享相同的图标,但文件夹以“F”为前缀,则使用相同的图标是可以接受的。但是,由于人类的图像识别速度比文字识别速度快,所以我们选择了图标。

                像 IDE 这样的计算机程序完全能够使文件的界面特性变得明显。这将释放以相同名称发生的不同抽象级别的命名空间。例如。在“ICare”中,“I”描述了实现,“Care”描述了接口的功能。

                我猜“I”约定之所以如此流行,是因为我们无法想到更好的方法,但它的存在很重要,因为它指出了我们需要了解此类信息。

                【讨论】:

                  【解决方案17】:

                  将接口与类分开。

                  此外(这更多是个人观察,而不是从高处决定的),接口描述了类的作用。 “我”很适合这一点(我确信这是语法中的一个结构,现在可以很好地抽出);描述验证类的接口将是“IValidate”。描述匹配行为的一种是“IMatch”。

                  【讨论】:

                  • 即使一个接口描述了一个类“做什么”,它也不应该被描述为一个动词。它仍然是一回事。它是 IValidatable 或 IMatchable。
                  • 嗯,适合自己。但是,如果您查看 .NET Framework,您就会知道 IMean 是什么。
                  • IUnderstand 和 IcouldDoThisAllDay
                  【解决方案18】:

                  事实上,每个人都理解它,编写更好的代码的一部分是使其易于阅读和理解。

                  【讨论】:

                    【解决方案19】:

                    我不太喜欢这种约定。我知道当您有一个具有相同名称的接口和一个实现时,它有助于解决这种情况,但我觉得它很难看。当然,如果这是我工作的惯例,我仍然会遵循它。一致性是约定俗成的重点,一致性是一件非常好的事情。

                    我希望有一个接口以尽可能通用的方式描述接口的作用,例如Validator。验证特定事物的特定实现将是ThingValidator,而具有Validators 共享的一些抽象功能的实现将是AbstractValidator。即使Thing 是唯一的……嗯……我正在验证的东西,我也会这样做,而Validator 将是通用的。

                    在只有一个具体类对接口有意义的情况下,我仍然尝试描述有关该特定实现的特定内容,而不是对接口进行不同的命名以防止名称冲突。毕竟,我会更频繁地输入接口的名称而不是实现的名称。

                    【讨论】:

                      【解决方案20】:

                      您可以将单词“Interface”作为后缀添加到您的自定义界面,例如“SerializerInterface”。对于抽象类“Fruit”,例如“FruitAbstract”或者你可以将其设为“AbstractFruit”,只要始终保持一致即可。这足够可读,或者遵循通常的命名约定。

                      【讨论】:

                        【解决方案21】:

                        只要我的 2 美分:

                        我个人之所以附加“接口”后缀是因为它比“I”前缀更容易阅读,并且因为系统中的文件是“分组”列出的。例如:

                        不太好:

                        Alien.php
                        Host.php
                        IAlien.php
                        IHost.php
                        IXenomorph.php
                        Xenomorph.php
                        

                        更好:

                        Alien.php
                        AlienInterface.php
                        Host.php
                        HostInterface.php
                        Xenomorph.php
                        XenomorphInterface.php
                        

                        但这只是个人喜好。我认为只要在整个项目中使用一致的命名约定,就没有什么可以反对使用自己的命名约定。

                        【讨论】:

                        • 是的,但按照这个概念,你不会命名类/文件 AlienClass 和 AlienClass.php ;)
                        猜你喜欢
                        • 2023-04-11
                        • 2010-12-18
                        • 2016-12-15
                        • 2010-10-29
                        • 1970-01-01
                        • 2016-12-25
                        • 2011-10-21
                        • 2014-07-25
                        • 2013-01-06
                        相关资源
                        最近更新 更多