对TypeScript的接口和类编码指南感到困惑

Snæ*_*ørn 49 coding-style typescript

我阅读了TypeScript编码指南

而且我觉得这句话很令人费解:

不要使用"I"作为接口名称的前缀

我的意思是,没有"我"前缀,这样的事情就没有多大意义

class Engine implements IEngine
Run Code Online (Sandbox Code Playgroud)

我错过了一些明显的东西吗

我不太明白的另一件事是:

为保持一致性,请不要在核心编译器管道中使用类.请改用函数闭包.

这是否表明我根本不应该使用课程?

希望有人可以为我清理:)

Sta*_*kov 114

当团队/公司发布框架/编译器/工具集时,他们已经拥有一些经验,一组最佳实践.他们将其作为准则分享.指南是 建议.如果你不喜欢任何你可以忽视它们.编译器仍然会编译你的代码.虽然在罗马...

这就是我的愿景,为什么TypeScript团队建议不要使用I前缀接口.

原因#1 匈牙利符号的时间已经过去了

I-prefix-for-interface支持者的主要参数是前缀有助于立即grokking(peeking)type是否是接口.声明前缀有助于立即grokking(偷看)是对匈牙利表示法的吸引力.I接口名称的前缀,C类,A抽象类,s字符串变量,cconst变量,i整数变量的前缀.我同意这样的名称修饰可以为您提供类型信息,而无需将鼠标悬停在标识符上或通过热键导航到类型定义.匈牙利符号的缺点和下面提到的其他原因超过了这个微小的好处.匈牙利符号在当代框架中没有使用.C#有I前缀(在C#这唯一的前缀)为由于历史的原因(COM)接口.回想起来,.NET架构师之一(Brad Abrams)认为最好不要使用I前缀.TypeScript是COM-legacy-free,因此它没有I--prefix-for-interface规则.

Reason#2 I-prefix违反了封装原则

我们假设你得到一些黑盒子.您将获得一些类型引用,允许您与该框进行交互.你不应该关心它是一个接口还是一个类.你只需使用它的界面部分.要求知道它是什么(接口,特定实现或抽象类)是违反封装的.

示例:假设您需要在代码中修复API Design Myth:Interface as Contract,例如删除ICar接口并使用Car基类.然后,您需要在所有消费者中执行此类替换.I-prefix导致消费者对黑盒实现细节的隐式依赖.

原因#3防止错误命名

开发人员懒得正确思考名称.命名是计算机科学中的两件难事之一.当开发人员需要提取接口时,只需将字母添加I到类名中即可获得接口名称.禁止I接口的前缀迫使开发人员绞尽脑汁为接口选择合适的名称.选择的名称不仅应在前缀上有所不同,还应强调意图差异.

抽象情况:你应该不会没有定义的ICar接口和相关的Car类.Car是抽象,它应该是用于合同的抽象.实现应该具有描述性的,独特的名称,例如SportsCar, SuvCar, HollowCar.

很好的例子:WpfeServerAutosuggestManager implements AutosuggestManager,FileBasedAutosuggestManager implements AutosuggestManager.

不好的例子:AutosuggestManager implements IAutosuggestManager.

原因#4正确选择的名称为API Design Myth:Interface as Contract提供接种疫苗.

在我的实践中,我遇到了很多人,他们在一个具有Car implements ICar命名方案的独立界面中轻率地复制了一个类的接口部分.在单独的接口类型中复制类的接口部分并不会将其神奇地转换为抽象.您仍将获得具体实现,但具有重复的接口部分.如果您的抽象不太好,那么复制界面部分无论如何都不会改进它.提取抽象是一项艰苦的工作.

  • 我喜欢你关于命名比接口名称更具体的具体类的观点,但认为 `I` 前缀有助于立即了解类型是否有实现。使用接口的主要优点是不会将外部代码的实现细节与特定实现耦合。 (5认同)
  • @demisx 如果感觉尴尬,那么你不应该这样做。回答这个问题:你真的需要它们吗?它们是否有任何意义,或者您只是为了错误地进行正确的工程而使用它们? (3认同)
  • @jameslk我知道在没有"我"的情况下命名的东西和"Impl"很难("计算机科学中只有两个难题:缓存失效和命名事物" - Phil Karlton)但是可行. (3认同)
  • 我同意删除I通常会通过在实现中添加前缀或后缀来代替:DefaultFooService或FoodServiceImpl。使用前缀,您会感到困惑,而且合同与实现/抽象之间没有重叠的命名问题。同样,重复点是有效的,但是接口的点是具有契约,并且能够用其他东西代替实现。通常,这在单元测试中绝对至关重要……更不用说抽象和不变性的好处了。。 (3认同)
  • 虽然您的观点在理论上听起来不错,但实际情况是,在足够大的团队中,通常将“ I”前缀替换为“ Impl”后缀 (2认同)
  • 命名是困难的,而困难恰恰是不应该通过固执的哲学而任意限制和禁止而故意变得更加困难的事情。提出匈牙利符号幽灵是一个谬论:没有人会开始写“lpcstr”。拥有一个 99% 的时间都会使用的接口和参考实现是一种不应该去优化的常见模式。 (2认同)
  • 在 TypeScript 中,我们需要区分编译时和运行时。使用“I”前缀可以非常方便地知道您正在使用接口而不是实现它的类。此外,在整体存储库的大型代码库中,快速过滤您想要指定的必要接口非常方便。如果最终是在“Impl”后缀和“I”前缀之间进行选择,我们应该只坚持其中之一。就我个人而言,我不认为使用“I”前缀有什么害处,主要是因为它有很多好处。 (2认同)

Bro*_*cco 34

关于您参考的链接的说明:

这是有关TypeScript代码样式的文档,而不是如何实现项目的样式指南.

如果使用I前缀对您和您的团队有意义,请使用它(我这样做).

如果没有,那么SomeThing(接口)的Java风格SomeThingImpl(实现)可能会使用它.

  • 只是为了澄清.[Typescript handbook](http://www.typescriptlang.org/Handbook)仍然说:`通常,不要在I前缀接口(例如IColor).因为TypeScript中的接口概念比C#或Java中的接口要广泛得多,所以IFoo命名约定并不广泛有用.它并不严格,但看起来像强烈建议. (13认同)
  • `SomeThingImpl实现SomeThing`和`SomeThing实现ISomeThing`一样好.如果`SomeThing`是一个抽象,那么命名应该是`具体[Some] Thing实现SomeThing`. (3认同)
  • 同意.对于所有基于TypeScript的项目,它听起来像Microsoft的代码指南,而不仅仅是TypeScript本身.我们发现此指南非常混乱,并且仍然在所有接口前加上"I". (2认同)
  • 有一种情况我认为保持"我"是有意义的.在React项目中有`Card`,它是一个接口和一个名为`Card`的组件.在道具中我需要一个`Card`数组,但类型不是组件.我必须选择命名`ICard`或`CardComponent` ... (2认同)

小智 6

我发现@stanislav-berkov对于OP的问题来说是一个很好的答案。我只想分享我的 2 美分,并补充说,最终取决于您的团队/部门/公司/任何人达成共识并制定自己的规则/指南来遵循。

只要可能且需要,坚持标准和/或惯例是一种很好的做法,并且它使事情更容易理解。另一方面,我确实认为我们仍然可以自由选择编写代码的方式。

从情感的角度思考一下,我们编写代码的方式或编码风格反映了我们的个性,在某些情况下甚至反映了我们的情绪。这就是让我们人类(而不仅仅是编码机器)遵守规则的原因。我相信编码可以是一门手艺,而不仅仅是一个工业化过程。