Confused about the Interface and Class coding guidelines for TypeScript

百般思念 提交于 2019-12-18 10:06:02

问题


I read through the TypeScript Coding guidelines

And I found this statement rather puzzling:

Do not use "I" as a prefix for interface names

I mean something like this wouldn't make a lot of sense without the "I" prefix

class Engine implements IEngine

Am I missing something obvious?

Another thing I didn't quite understand was this:

Classes

For consistency, do not use classes in the core compiler pipeline. Use function closures instead.

Does that state that I shouldn't use classes at all?

Hope someone can clear it up for me :)


回答1:


When a team/company ships a framework/compiler/tool-set they already have some experience, set of best practices. They share it as guidelines. Guidelines are recommendations. If you don't like any you can disregard them. Compiler still will compile your code. Though when in Rome...

This is my vision why TypeScript team recommends not I-prefixing interfaces.

Reason #1 The times of the Hungarian notation have passed

Main argument from I-prefix-for-interface supporters is that prefixing is helpful for immediately grokking (peeking) whether type is an interface. Statement that prefix is helpful for immediately grokking (peeking) is an appeal to Hungarian notation. I prefix for interface name, C for class, A for abstract class, s for string variable, c for const variable, i for integer variable. I agree that such name decoration can provide you type information without hovering mouse over identifier or navigating to type definition via a hot-key. This tiny benefit is outweighed by Hungarian notation disadvantages and other reasons mentioned below. Hungarian notation is not used in contemporary frameworks. C# has I prefix (and this the only prefix in C#) for interfaces due to historical reasons (COM). In retrospect one of .NET architects (Brad Abrams) thinks it would have been better not using I prefix. TypeScript is COM-legacy-free thereby it has no I-prefix-for-interface rule.

Reason #2 I-prefix violates encapsulation principle

Let's assume you get some black-box. You get some type reference that allows you to interact with that box. You should not care if it is an interface or a class. You just use its interface part. Demanding to know what is it (interface, specific implementation or abstract class) is a violation of encapsulation.

Example: let's assume you need to fix API Design Myth: Interface as Contract in your code e.g. delete ICar interface and use Car base-class instead. Then you need to perform such replacement in all consumers. I-prefix leads to implicit dependency of consumers on black-box implementation details.

Reason #3 Protection from bad naming

Developers are lazy to think properly about names. Naming is one of the Two Hard Things in Computer Science. When a developer needs to extract an interface it is easy to just add the letter I to the class name and you get an interface name. Disallowing I prefix for interfaces forces developers to strain their brains to choose appropriate names for interfaces. Chosen names should be different not only in prefix but emphasize intent difference.

Abstraction case: you should not not define an ICar interface and an associated Car class. Car is an abstraction and it should be the one used for the contract. Implementations should have descriptive, distinctive names e.g. SportsCar, SuvCar, HollowCar.

Good example: WpfeServerAutosuggestManager implements AutosuggestManager, FileBasedAutosuggestManager implements AutosuggestManager.

Bad example: AutosuggestManager implements IAutosuggestManager.

Reason #4 Properly chosen names vaccinate you against API Design Myth: Interface as Contract.

In my practice, I met a lot of people that thoughtlessly duplicated interface part of a class in a separate interface having Car implements ICar naming scheme. Duplicating interface part of a class in separate interface type does not magically convert it into abstraction. You will still get concrete implementation but with duplicated interface part. If your abstraction is not so good, duplicating interface part will not improve it anyhow. Extracting abstraction is hard work.




回答2:


Clarification regarding the link that you reference:

This is the documentation about the style of the code for TypeScript, and not a style guideline for how to implement your project.

If using the I prefix makes sense to you and your team, use it (I do).

If not, maybe the Java style of SomeThing (interface) with SomeThingImpl (implementation) then by all means use that.




回答3:


The type being an interface is an implementation detail. Implementation details should be hidden in API:s. That is why you should avoid I.

You should avoid bot prefix and suffix. These are both wrong:

  • ICar
  • CarInterface

What you should do is to make a pretty name visible in the API and have a the implemtation detail hidden in the implementation. That is why I propose:

  • Car - An interface that is exposed in the API.
  • CarImpl - An implementation of that API, that is hidden from the consumer.



回答4:


TypeScript's handbook says it all. Just pay attention to the examples there and be happy. <3



来源:https://stackoverflow.com/questions/31876947/confused-about-the-interface-and-class-coding-guidelines-for-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!