.net 如何提供更清晰的接口名称?[closed]

huwehgph  于 2023-01-27  发布在  .NET
关注(0)|答案(8)|浏览(121)

已关闭。此问题为opinion-based。当前不接受答案。
**想要改进此问题吗?**请更新此问题,以便editing this post可以用事实和引文来回答。

3天前关闭。
Improve this question
我在一个应用程序中看到过这样的界面:

IHasContent
IHasValue
IHasMesh
IHasGeometry
IHasTransformation

他们不应该吗?:

IHaveContent
IHaveValue
...

或者?

IIncludeContent
IIncludeValue
...

就我个人而言,我倾向于直接制造它们:

IContent
IValue
IMesh
IGeometry
ITransform

因为ISomething不是已经暗示了它有something吗?
至于最后一个,我应该改为ITransformable吗?
我认为使用I + (Has/Have/Include/Exist, etc) + Name会使接口名称更加混乱。
关于如何想出更好的接口名称,使其不感到尴尬,切中要害,并得到含义的想法?

hc8w905p

hc8w905p1#

其中一些名字(内容、值等)是模糊的,几乎不描述项的内容/行为。通常,名称应尽可能具体和明确- IScriptParameter可能比IValue更具描述性。随着项目的增长,具有更多描述性的名称将使类型更容易区分(如果不小心,可能会使用IValue、INumber和IAmount来处理“值”的变化!)
如果你的接口(例如IMesh)意味着“提供网格的属性”,那么IMesh是一个非常好的名字-它描述了这样一个事实,即你可以把对象当作网格来对待。
如果你的界面被用来应用一个动作(例如,把对象渲染成一个网格,或者对对象应用一个变换),那么考虑使用动词/形容词而不是名词命名(例如IRenderable,ITransformable)-这是.net中的一个常见模式(例如,IEnumerable(动词/形容词)而不是ICollection(名词))
对我来说,“IHasMesh”听起来更像是IMeshContainer -IidoEe.它是一个包含网格的对象,接口允许我“获取网格”。因此,它不允许我操作或查询网格内的数据,而只是通过接口获取整个网格对象。
所以我会用途:

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

w6mmgewl

w6mmgewl2#

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

public class Lolcat : IHasCheezburger

当我读到这一点,我很容易理解,lolcats有奶酪汉堡在他们。
另一方面,

public class Lolcat : ICheezburger

这让我想知道lolcatsHAVE奶酪汉堡包还是ARE奶酪汉堡包(这是解释继承时使用的传统动词)。

ldfqzlk8

ldfqzlk83#

首先你要明白的是名字中的“I”并不是指代词“I”,而是遵循接口以大写字母“I”开始的命名标准。
从这个意义上讲,接口实际上被命名为“HasContent”、“HasValue”等,所以不要将其更改为“HaveContent”和“HaveValue”,因为那样会很尴尬。
话虽如此,我还是不能确切地看到这些接口的用途,接口(根据定义)旨在对实现它的所有类强制一个条件,我不确定这些接口强制的是什么--所有类都有一个名为HasContent()的函数?
我认为你应该把注意力放在有is a关系的接口上,当你声明一个实现IList接口的类时,你并不是在暗示你的类 * 有 * 一个列表,而是你的类 * 是一个 * 列表。
例如,其中一个接口是IHasGeometry......这使我能够检查它是否具有几何形状,但实际上我只想处理 * 是 * 几何图形的图形,因此我将创建一个名为IGeometricFigure的接口,从而将其使用限制在任何操作几何图形的对象上。
我同意这些名称听起来很别扭,但我认为这更多的是因为这些接口被用于一个别扭的目的,而不是因为它们的名称不恰当。

e5nszbig

e5nszbig4#

你最初的接口名称列表听起来完全正确。接口名称应该描述契约。例如,这是我最近遇到的一个我非常喜欢的接口:

public interface IDeterminesEmptyValue
{
    bool IsEmpty { get; }
}

太完美了!名字说明了一切。“我”指的是它是一个接口的事实,其余的描述了合同将履行什么。
如果接口名为IEmptyValue,这意味着接口保证了实现者的IS是一个空值,但事实并非如此--它有能力确定一个值是否为空。
(很可能)没有类会被称为DeterminesEmptyValue,但是可能有一千个类都有能力判断不同类型的值是否为空,这个接口让它们都能以一种通用的方式被调用。
接口应该清楚地描述实现它的类的一个特定特征。在IContent的情况下-实现者 HAVE 内容,还是实现者 ARE 内容?

a6b3iqyw

a6b3iqyw5#

我喜欢认为ISomething意味着它 * 是 * 某物,就像扮演某物的角色一样,而不是它'拥有'或'包含'某物。所以,IFather意味着'我扮演父亲的角色',或者我是父亲'。IDispatcher意味着'我扮演调度员的角色',或者'我是调度员',等等。
有些人喜欢通过命名接口来回答“我该做什么?”的问题:IListenForEventsILogExceptionsLike in this post

qvsjd97n

qvsjd97n6#

接口有很多用途,有着不同的混乱的命名约定。在担心名称之前,最好先决定如何分离功能。不幸的是,微软的集合中没有太多不同的接口,最大的遗漏是IReadableList和IAppendable。这两种方法都可以被IList继承,但支持逆变和协方差支持[因此可以传递IList(Cat的)转换为期望IReadableList(Animal的)或IAppendable(SiameseCat的)的代码]。另一方面,也有可能将东西分割得太细,因此任何有用的类都必须实现几十个接口。
如果不知道应用程序和界面中使用了什么类型的功能,就很难判断它们是否是以良好的粒度级别设计的。听起来它们划分得太细了,但我真的不能判断。一旦功能被适当地分组,那么担心名称就有意义了。

plupiseo

plupiseo7#

“I”并不代表“我”,它只是代表接口。
但是微软有他们的own guidelines来命名接口。
名称的区别应该仅在于接口名称中的字母I前缀。

q9rjltbz

q9rjltbz8#

在.Net库中搜索不同的接口名称前缀,IWith似乎是最好的选择。
考虑的备选办法:

可以使用以下代码验证结果:

const intervalID = setInterval(() => {
  const moreButton = document.querySelector(".more-button")
  if (moreButton && document.querySelector(".api-search-results tr:last-child td:first-child span").innerText.trim() == "Interface") {
    moreButton.click()
  } else {
    clearInterval(intervalID)
    console.log([...document.querySelectorAll(".api-search-results tr td:first-child span")].filter(el => el.innerText.trim() == "Interface").length)
  }
}, 100)

相关问题