Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prohibition against prefixing interfaces with "I" #121

Closed
scottmmjackson opened this issue Dec 2, 2015 · 31 comments
Closed

Prohibition against prefixing interfaces with "I" #121

scottmmjackson opened this issue Dec 2, 2015 · 31 comments

Comments

@scottmmjackson
Copy link

@scottmmjackson scottmmjackson commented Dec 2, 2015

The Typescript Handbook tells the developer not to prefix interfaces with I. This needs more detail. Lots of .NET developers are familiar with I-prefixed interfaces. Simply stating that the concept is broader is not sufficient. If it's an antipattern, let's describe why. If it's not an antipattern, then let's say "it is not necessary to prefix interfaces with I, and Typescript Contributors do X"

@RyanCavanaugh

This comment has been minimized.

Copy link
Member

@RyanCavanaugh RyanCavanaugh commented Dec 2, 2015

I'm not entirely sure what more to write. .NET is the one with the rule (always prefix interfaces with I), not TypeScript. TypeScript code also generally shouldn't write names like lpcstrName like Win32 C code does. It's just a statement of "You shouldn't bring in this other framework's naming rules just because the keyword for the declaration is the same".

Any constructive ideas on how to phrase this?

@scottmmjackson

This comment has been minimized.

Copy link
Author

@scottmmjackson scottmmjackson commented Dec 2, 2015

"It is not necessary to prefix interfaces with 'I', as is done in C#."

Otherwise, what it sounds like you mean is that prefixing with I is a great way to encounter the ancient demons of code collision or bad coding practices. Right now it says "Do not", which is prohibitory language, not advisory language.

If there is a recommended style (like postfixing with Interface or Type or the like), that would be even better to note, rather than the discouraged prefix.

@mhegazy

This comment has been minimized.

Copy link
Contributor

@mhegazy mhegazy commented Dec 3, 2015

not to sound pedantic, but necessary/not necessary is not the right word, i do not think it is necessary to add I in C# nor is it in TS. i would say "you shouldn't use 'I'" is more accurate.

@DanielRosenwasser

This comment has been minimized.

Copy link
Member

@DanielRosenwasser DanielRosenwasser commented Dec 3, 2015

Agreed with @mhegazy.

DanielRosenwasser added a commit that referenced this issue Dec 5, 2015
Fix wording of interface naming conventions, fix #121
@robgha01

This comment has been minimized.

Copy link

@robgha01 robgha01 commented Oct 6, 2016

@mhegazy prefixing namespaces with I in c# is common sense how would you else like your code written using I distinguishes interfaces and abstracted classes ex: CarBase describes a abstract base for cars and the interface IAccelerate describes the method which incises the speed of the car not prefixing this with I means it could be anything i would never in the world work with code that dont prefix interfaces with I in c# its absurt.

@mhegazy

This comment has been minimized.

Copy link
Contributor

@mhegazy mhegazy commented Oct 6, 2016

@robgha01 this is a style choice. you are free to write C# code with no I prefixes, as well as TS code with them. This is a style recommendation we make, and one we use in our internal code base. the compile does not enforce any rules regarding names of interfaces or classes.

@hedss hedss mentioned this issue Feb 20, 2017
@JonathanYates

This comment has been minimized.

Copy link

@JonathanYates JonathanYates commented Mar 2, 2017

I 'IS' for Interface. Nothing to do with .Net (although common sense prevails there).

Reasons are obvious and I fail to understand why anyone would not prefix an interface with 'I'.

  1. Clearly identifies that it IS an interface.
  2. Clearly distinguishes between an interface and an implementation.
  3. What are you going to call the implementation if the interface is not prefix with I.
    e.g. Interface Foo. Err FooImpl as they do in Java. Please no!! IFoo and Foo makes it very clear.

I kind of feel the world has gone a little mad and lost it's marbles! Please prefix ALL interfaces with 'I' because 'I' IS for Interface.

@RyanCavanaugh

This comment has been minimized.

Copy link
Member

@RyanCavanaugh RyanCavanaugh commented Mar 6, 2017

Everyone knows to follow C++ naming conventions, so the class will be called CFoo thus there is no conflict. 🙄

@aleung aleung mentioned this issue Aug 1, 2017
7 of 8 tasks complete
@Raketar

This comment has been minimized.

Copy link

@Raketar Raketar commented Aug 1, 2017

Most complete answer for this topic I found in this stackoverflow answer:
https://stackoverflow.com/a/41967120/4676238

@UTGuy

This comment has been minimized.

Copy link

@UTGuy UTGuy commented Oct 28, 2017

I just ran across this issue and read @Raketar stackoverflow link. The first response is a very logical and reasoned answer. The ability to decipher an interface from an abstraction or implementation by simply seeing an "I" in front of it will speed up anybody trying to process what they are reading (instead of having to go to the file). In Berkov's post he says 'choose appropriate name for abstraction and concrete implementation' but then uses the implementation example 'FileBasedAutosuggestManager' and interface 'AutosuggestManager', yet 'FileBasedAutosuggestManager' could just as easily been an interface also... which seems to be overlooked here.

It appears this whole thread boils down to preference not correctness. Whether someone wants to write Async at the end of their methods to denote async/await is preference, or Base at the end of an abstraction. Languages borrow conventions all the time. It's what people get used to. If that helps speed up learning and development then use it, unless something better comes along. But this is one of the cases for me at least, there's not clear evidence that dropping the 'I' as a convention is more beneficial.

@RyanCavanaugh

This comment has been minimized.

Copy link
Member

@RyanCavanaugh RyanCavanaugh commented Oct 30, 2017

I don't understand the confusion. Classes should always start with a three-letter prefix:

Your own classes should use three letter prefixes. These might relate to a combination of your company name and your app name, or even a specific component within your app. As an example, if your company were called Whispering Oak, and you were developing a game called Zebra Surprise, you might choose WZS or WOZ as your class prefix.

@scottmmjackson

This comment has been minimized.

Copy link
Author

@scottmmjackson scottmmjackson commented Oct 30, 2017

@UTGuy

This comment has been minimized.

Copy link

@UTGuy UTGuy commented Oct 31, 2017

@RyanCavanaugh Theres no confusion, context is important. If someone is writing a pull request into typescript, you should be using typescript convention, .Net use "I" for interface.... etc. Cavanaugh is just establishing a convention for the library which is fine.

The whole "what about" argument for the three-letter prefix boils down to context IMO. If its the convention of the library to prefix three-letters (albeit a terrible one IMO for numerous reasons), that's the end of it. So you could either have a argument over the correctness of the pattern or you could state it's the preference for the library.

The difference between "I" for interface and the three-letter argument (for correctness sake), is the context in which the variables/classes exist. If the company "Whispering Oak" creates a game called "Zebra Surprise", the the resulting package would typically be name "zerbra-surprise.exe" (or w/e) under the "Whispering Oaks" directory... and one could make the argument that three-letter prefixes are unnecessary due to the context its in. Redundancies can and probably should be removed, that would be my argument, at least. Contrary to this, you cannot infer that an interface is an interface by using context clues, therefor adding an "I" would be a reasonable response.

@stasberkov

This comment has been minimized.

Copy link

@stasberkov stasberkov commented Nov 25, 2017

@UTGuy
In my post on stackoverflow I just mentioned possible reasons why TypeScript team has guideline do not use I-prefix for interfaces.
When my team started using TS we also used I-prefix for interfaces. C# influence, I assume.
Then I read TypeScript team's guideline about not using I-prefix. It took me several weeks to realize it. I was eagerly searching for information why they have such rule.
After a time I realized: I-prefix for interfaces is a flaw (at least in TypeScript), it causes more problems than provides benefits.

There is one more reason for not using I-prefix. I call it "when in Rome..." rule (play by the rules of a used framework). TypeScript team has such guideline, Angular2+ has such guideline, rxjs is written in such manner.

@eyalsk

This comment has been minimized.

Copy link

@eyalsk eyalsk commented Dec 16, 2017

The prefix in the .NET world was never necessary it only added confusion, some people reads the prefix as if it is the pronoun I which is wrong.

@JonathanYates

Clearly distinguishes between an interface and an implementation.

In practice an interface name in the .NET world shouldn't match the implementation name.

Interfaces in the .NET world should be small and implementations should be composed of multiple interfaces and if you have a single interface that describes an implementation and you want to distinguish between them a better convention could have been something like this Engine (interface) and DefaultEngine (Implementation) even though it doesn't say much but I find it a lot better than IEngine and Engine, however, today some people do this IEngine and DefaultEngine where the prefix is really redundant.

Consumers shouldn't know whether Engine is an interface or an abstract class because this should be an implementation detail, you can always start with an interface and transition to an abstract class but because of the naming convention you can't do it and this is part of the reason we're going to have Default Interface Members but it is what it is. :)

That said, I still use the prefix I in .NET because I don't want to be the only one to break the rules and most importantly I don't want consumers to get confused so I follow what everyone does but I do think it was a mistake.

@fahad19 fahad19 mentioned this issue Jan 14, 2018
1 of 1 task complete
@santhony7

This comment has been minimized.

Copy link

@santhony7 santhony7 commented Jan 23, 2018

I have been struggling with this as well. When I was a C# and ActionScript developer we always prefaced our interfaces with I and it was one of the first things I learned about TypeScript. I do understand the arguments "against" it but then I run into community standards like adding a $ at the end of observables. Obviously, we do seem to desire instant gratification in identifying things. I'm curious as to how often I am going to start writing "new Thing()" only to find out it is an interface and I can't do that. :-)

@Flamenco

This comment has been minimized.

Copy link

@Flamenco Flamenco commented Mar 17, 2018

Ideally, you should always use an interface, and so dropping the prefix makes sense to me. Let the abstract and implementation classes be explicit with verbose prefix and/or suffix, and let the interfaces be the pure function name.

@milewski milewski mentioned this issue May 5, 2018
8 of 9 tasks complete
@atodd-geoplan

This comment has been minimized.

Copy link

@atodd-geoplan atodd-geoplan commented Aug 13, 2018

The world has gone mad. Why wouldn't you choose to identify interfaces in code just be looking at them?

I would say something like "the custodians of typescript suggest not to identify interfaces easily by prefixing with an 'I', but this is not our in-house coding standard, so please do it."

A case when this gets really confusing is the angular HttpClient which returns observables of interfaces - it doesn't magically cast them to a concrete class, but this is not obvious by just looking at the code.

@stasberkov

This comment has been minimized.

Copy link

@stasberkov stasberkov commented Aug 14, 2018

@atodd-geoplan what you are suggesting is called Hungarian notation. It is past stage of programming languages development. 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.

@leoskyrocker

This comment has been minimized.

Copy link

@leoskyrocker leoskyrocker commented Aug 14, 2018

People here have been suggesting that we shouldn't need to distinguish interfaces and abstract classes.

However, it is important to distinguish the above from actual implementations. Are we making this clearer by just removing the I in the naming? If we name interfaces/abstract classes similarly, how do we avoid other developers from blurring the line of actual implementation and abstraction?

@leoskyrocker

This comment has been minimized.

Copy link

@leoskyrocker leoskyrocker commented Aug 14, 2018

@stasberkov Brad Abrams in retrospect regretted using I prefix, he would have rather used the "Interface" suffix.

The only prefix used is “I” for interfaces (as in ICollection), but that is for historical reasons. In retrospect, I think it would have been better to use CollectionInterface as the name—it is clearer and follows the guidelines.

I think you two are talking about different things.

@atodd-geoplan

This comment has been minimized.

Copy link

@atodd-geoplan atodd-geoplan commented Aug 14, 2018

@stasberkov a really poor argument for against. sorry.

@stasberkov

This comment has been minimized.

Copy link

@stasberkov stasberkov commented Aug 14, 2018

@leoskyrocker

how do we avoid other developers from blurring the line of actual implementation and abstraction

-- clear naming? Actual implemenation must have in name what particular implemenation of abstraction it is. E.g. SportsCar->Car. Forbidding I prefix forces developers choosing distingished names. Not just Car -> ICar.

@atodd-geoplan

This comment has been minimized.

Copy link

@atodd-geoplan atodd-geoplan commented Aug 14, 2018

@stasberkov its personal

i prefer

SportsCar extends AbstractCar implements ICar

To me "I" stands for contract. It's what I'm used to as a C# developer. I couldn't give two hoots when it started or when you think it should have ended.

forbidding personal is really Draconian and also behaviour from the past

fortunately this isn't forced by the linting

@stasberkov

This comment has been minimized.

Copy link

@stasberkov stasberkov commented Aug 14, 2018

@atodd-geoplan If you are a C# lover then you will like this post from .net architect Krzysztof Cwalina API Design Myth: Interface as Contract. Interface is not contract, it is just syntax. Every class has interface part. There is no need in monkey-work of duplicating interface part.

Interfaces separate syntax from implementation, which is not that useful, and the myth provides a false sense of doing the right engineering.

-- Krzysztof Cwalina

@atodd-geoplan

This comment has been minimized.

Copy link

@atodd-geoplan atodd-geoplan commented Aug 14, 2018

@stasberkov that is just one one-sided view. I am sure you can find arguments that promote the use of Design by Contract as a design pattern.

@leoskyrocker

This comment has been minimized.

Copy link

@leoskyrocker leoskyrocker commented Aug 14, 2018

@stasberkov Even in the above article he suggested using Contracts (via abstract class).
In the naming he actually used the "Contract" prefix.... I think every articles you posted are suggesting some prefixes/suffixes in their own naming schemes...

When thinking more about your example of SportsCar -> Car, in typescript it becomes:

class Car {
    startEngine(): void;
}

class SportsCar implements Car {
    startEngine() {
        console.log('Engine Starting...');
    }
}

While other develops can start coming in and use this car class by extending it:

class CoolerSportsCar extends Car { }

and he changes Car to be:

class Car {
    startEngine(): void {
        console.log('I have a default implementation');
    };
}

In this case, as people add additional behavior in the interface, how do we avoid breaking the original contract that other callers depend on?

(I am not even coming from the C# community but I just didn't see how removing the I in the name would solve any problems.)

@stasberkov

This comment has been minimized.

Copy link

@stasberkov stasberkov commented Aug 14, 2018

@leoskyrocker

I am not even coming from the C# community but I just didn't see how removing the I in the name would solve any problems

  1. Name decoration is not needed in contemporary dev environments. It is atavism. 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.
  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 (I from SOLID principle). Demanding to know what is it (interface, specific implementation or abstract class) is a violation of encapsulation.
  3. Protection from bad naming. It forces developers to choose distinguished names that emphasize implementaion differences. Naming things is hard. It is one of two hard things in Computer Science. Developers are lazy. If they can use Car->ICar scheme they will use it.
  4. Conformance. When in Rome principle. Major ts-based frameworks like Angular discorage using I prefix for interfaces. Rxjs also do not use I prefix.
@leoskyrocker

This comment has been minimized.

Copy link

@leoskyrocker leoskyrocker commented Aug 14, 2018

It is necessary to come to a realization that the violation of encapsulation doesnt lie in the naming itself, but on the languages' restrictions. For example, in Java, there's no way to implements a class and you can only implements an interface. The violation of encapsulation automatically happens when someone tries to use an interface.

Yet, I have arrived at a unanswered question for myself: does it necessarily mean something is bad as soon as we coin it as a violation of some rules? In this case, we have seen no problems of having these language restrictions.

@giovannipds

This comment has been minimized.

Copy link

@giovannipds giovannipds commented Dec 14, 2018

If you came here looking for answers as I did, just check TypeScript's handbook <3.

@fis-cz

This comment has been minimized.

Copy link

@fis-cz fis-cz commented Jan 29, 2020

@RyanCavanaugh I know it is bit old, could you maybe tell us why your team decided not to prefix interfaces with I? I mean, what was the reason?

I think thats because in TypeScript the interface is not just an pure object interface but it can be used to define interface to ctors, call signatures, indexable objects and maybe more I can't imaigine right now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.