【问题标题】:How to come up with clearer interface names?如何想出更清晰的接口名称?
【发布时间】:2011-07-13 02:53:54
【问题描述】:

我在一个应用程序中看到它具有以下接口:

IHasContent
IHasValue
IHasMesh
IHasGeometry
IHasTransformation

他们不应该吗?:

IHaveContent
IHaveValue
...

或者?:

IIncludeContent
IIncludeValue
...

就我个人而言,我倾向于制作它们:

IContent
IValue
IMesh
IGeometry
ITransform

因为不是ISomething 已经暗示它有那个something

至于最后一个,我应该改成ITransformable吗?

我认为使用I + (Has/Have/Include/Exist, etc) + Name 会使接口名称更加混乱。

关于如何提出更好的界面名称,不会让人感到尴尬,切中要害,并传达含义的任何想法?

【问题讨论】:

    标签: c# .net interface naming


    【解决方案1】:

    其中一些名称(内容、值等)含糊不清,几乎无法描述项目的内容/行为。通常,名称应尽可能具体和不同 - IScriptParameter 可能比 IValue 更具描述性。随着项目的发展,具有更多描述性的名称将使您的类型更容易区分(如果您不小心,最终可能会使用 IValue 和 INumber 和 IAmount 来处理“值”的变化!)

    如果您的界面(例如 IMesh)的意思是“提供网格的属性”,那么 IMesh 是一个完美的名称 - 它描述了您可以将对象视为网格的事实。

    如果您的界面用于应用动作(例如,将对象渲染为网格,或对对象应用变换),则考虑使用动词/形容词而不是名词命名(例如,IRenderable、ITransformable) - 这是 .net 中的常见模式(例如,IEnumerable(动词/形容词)而不是 ICollection(名词))

    对我来说,“IHasMesh”听起来更像是 IMeshContainer - 即它是一个包含网格的对象,并且界面允许我“获取网格”。所以它不允许我对网格中的数据进行操作或查询,而只是通过接口获取整个网格对象。

    所以我会使用:

    • ITransformable 如果对象可以通过接口转换
    • ITransform 如果对象可以像 它是一个 Transform 一样直接使用
    • IHasTransform/ITransformContainer/ITransformProvider 如果对象是容器,可以通过查询来提取 Transform 对象

    【讨论】:

      【解决方案2】:

      就个人而言,我喜欢 IHas+Word,因为接口名称描述了实现它们的类的属性。 例如:

      public class Lolcat : IHasCheezburger
      

      当我读到这句话时,我很容易理解笑笑猫里面有芝士汉堡。

      另一方面,

      public class Lolcat : ICheezburger
      

      让我想知道 lolcats 是 HAVE 芝士汉堡还是 ARE 芝士汉堡(这是解释继承时使用的传统动词)。

      【讨论】:

      • 我不知道该笑还是同意...:)
      • 谢谢,但 Stargazer 还说I 不是指代词I,而只是一个前缀。但我不确定这是否被普遍接受。
      • @Joan Venge,我不是说它被普遍接受,我是说它是一个普遍的已知命名标准(与已知但永远相同) -讨厌的匈牙利符号)。
      • @Joan 是的。我认为您无法在 System 命名空间中找到很多可以将 I 解释为代词的接口。 I 是“接口”的缩写,用于区分接口和常规类(参见msdn.microsoft.com/en-us/library/8bc1fexb(v=vs.71).aspx
      【解决方案3】:

      首先你要明白,名字中的“I”不是指代词“I”,而是遵循接口以大写字母“I”开头的命名标准。

      从这个意义上说,接口实际上被命名为“HasContent”、“HasValue”等,因此不要将其更改为“HaveContent”和“HaveValue”,因为那样会很尴尬。

      话虽如此,我无法确切了解这些接口的用途。一个接口(根据定义)旨在对所有实现它的类强制一个条件,我不确定这些接口在强制什么——所有类都有一个名为HasContent()的函数?

      我认为您应该专注于具有is a 关系的接口。当你声明一个实现接口IList的类时,你并不是暗示你的类一个列表,而是你的类是一个列表。

      例如,其中之一是IHasGeometry...嗯,这使我能够检查它是否具有几何形状,但实际上我只想处理 的数字几何图形,因此我将创建一个名为 IGeometricFigure 的接口,从而将其使用限制为任何对几何图形进行操作的对象。

      我同意这些名称听起来很尴尬,但我认为这更多是因为这些接口被用于尴尬的目的,而不是因为它们的名称不正确。

      【讨论】:

      • “一个接口(根据定义)旨在对所有实现它的类强制一个条件,我不确定这些接口在执行什么” - 我认为推测它有点毫无意义或在不了解底层域模型的情况下判断标识符选择。
      • @O.R.Mapper ...这很重要...为什么?
      • 好吧,由于您不了解底层域模型,因此您“不确定这些接口在执行什么”这一事实是无关紧要的,并不意味着接口命名不当。
      • @O.R.Mapper 这正是我所说的。当我说“我不确定这些接口在执行什么”时,您还认为我的意思是什么?对我来说,很明显我是在说我不知道​​“底层域模型”是什么。
      【解决方案4】:

      您最初的接口名称列表听起来完全正确。接口名称应描述合同。例如,这是我最近遇到的一个我很喜欢的界面:

      public interface IDeterminesEmptyValue
      {
          bool IsEmpty { get; }
      }
      

      完美!这个名字说明了一切。 “I”是指它是一个接口,其余的描述合约将要实现的内容。

      如果接口被称为IEmptyValue,这意味着接口保证实现者是一个空值。它不是 - 它有能力来确定一个值是否为空。

      (可能)不会调用任何类DeterminesEmptyValue。但是可能有一千个类都有能力判断不同类型的值是否为空,而这个接口让它们都可以以一种通用的方式调用。

      接口应该清楚地描述实现它的类的特定特征。在IContent 的情况下 - 实施者 HAVE 内容,还是实施者 ARE 内容?

      【讨论】:

      • 但是如果是IEmptyValue不是更好吗?
      • 因为在其中一个回复中,Carra 说“名称的不同之处仅在于接口名称上的字母 I 前缀。”所以如果这是一门课,没人会叫它class DeterminesEmptyValue,对吧?
      • @Joan IEmptyValue 意味着接口保证实现者是一个空值。它不是——它有能力确定一个值是否为空。没有类会被称为DeterminesEmptyValue,但可能有一千个类都能够确定不同类型的值是否为空,并且这个接口让它们都可以以一种通用的方式调用。
      • @Joan 这还不错,但它的描述性不太好——它可能是空的,但它并没有告诉我们这个类也有能力告诉我们。
      • 在我看来,这个答案中提到的接口是一个 role 接口,与 Udi Dahan 在 [Making Roles Explicit] ( infoq.com/presentations/Making-Roles-Explicit-Udi-Dahan)。
      【解决方案5】:

      我喜欢认为ISomething 意味着它某物,就像扮演某物的角色,而不是它“拥有”或“包含”某物。所以,IFather 的意思是“我扮演父亲的角色”,或者我是父亲。 IDispatcher 表示“我扮演调度员的角色”或“我是调度员”等。

      有些人喜欢命名接口来回答“我该怎么做?”这个问题。 :IListenForEventsILogExceptionsLike in this post

      【讨论】:

      • 或者回答“你是什么?”的问题:IEventListener, IEventLogger
      【解决方案6】:

      接口用于多种用途,具有不同的混乱命名约定。在担心名称之前,最好先决定如何分离功能。不幸的是,Microsoft 的集合具有太少的不同接口,最大的遗漏是 IReadableList 和 IAppendable,这两者都可以由 IList 继承,但支持逆变和协变支持[因此可以将 IList(of Cat) 传递给期望 IReadableList(of Animal ) 或 IAppendable(Of SiameseCat)]。另一方面,也有可能将事物拆分得太细,因此任何有用的类都必须实现数十个接口。

      如果不知道应用程序和界面中使用了哪些类型的功能,就很难判断它们的设计是否具有良好的粒度级别。听起来他们分得太细了,但我真的说不出来。一旦功能被适当地分组,那么担心名称是有意义的。

      【讨论】:

      • 感谢 supercat,这是一个有趣的想法。您认为 MS 这样做是出于性能原因吗?就像如果您有 5 个接口而不是 1 个,那可能会减慢初始化等速度?
      【解决方案7】:

      “我”不代表“我”。它只代表接口。

      但微软有他们的own guidelines 用于命名接口。

      名称应仅相差 接口名称的字母 I 前缀。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-01-26
        • 2011-08-24
        • 2020-06-22
        • 1970-01-01
        • 1970-01-01
        • 2014-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多