Skip to content
This repository has been archived by the owner on Dec 4, 2017. It is now read-only.

discussion(style-guide) Drop _-prefix for private fields in TypeScript #1108

Closed
choeller opened this issue Apr 18, 2016 · 49 comments
Closed

Comments

@choeller
Copy link

choeller commented Apr 18, 2016

The first draft of the style-guide uses the _-prefix for private fields:

constructor(private _heroService: HeroService) {}

Microsoft clearly states that this is not recommended in their coding guidelines:

Do not use "_" as a prefix for private properties.
https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines

I personally think that a lot of people will start using TypeScript because of ng2 and it would be really bad to have conflicting guidelines for coding on both sides. I would assume that the Angular 2 style-guide mostly follows TypeScript recommendations.

@Foxandxss
Copy link
Member

Or maybe we should change Microsoft's guidelines :)

I like the underscore for this cases.

@bampakoa
Copy link
Contributor

bampakoa commented Apr 18, 2016

@wardbell states it very nice in this issue. Underscore is a good indicator during debugging and as @Foxandxss states also, it can be really helpful for developers that design directives for public consumption.

@Foxandxss
Copy link
Member

Problem with Microsoft guidelines is that they are good for their usage but could be not the case of Angular 2.

For example, you can do like:

<dir #dir></dir>
{{dir.foo}}
{{dir._bar}}

In the first case, you are using foo which is ok to use, but in the second case you are using _bar which is not ok to use.

Without the underscore, we have no way on telling "hey, you shouldn't use this, don't come later telling that I didn't warn you".

We can't prevent (at least that I know) people from accessing everything inside the component, even private stuff, so at least the underscore gives them a big hint.

See: http://plnkr.co/edit/FRqM6psseX9dJ9aHMfQh?p=preview

@zoechi
Copy link

zoechi commented Apr 18, 2016

I guess this is also for Dart "compatibility" where the _ actually makes members private.

@Foxandxss
Copy link
Member

That too.

@gkalpak
Copy link
Member

gkalpak commented Apr 18, 2016

I think it is also helpful for people using plain old JavaScript, where access modifiers aren't available.

@choeller
Copy link
Author

choeller commented Apr 19, 2016

Hi guys,

ok - I kind of understand some of your arguments, but to me it still seems, that most of them are only valid when thinking in "TypeScript is JavaScript" . I'm a little "scared" that by promoting underscore-prefix we would motivate people to just use their well-known patterns from JS-world just because they are used to it. So let me try to make my points:

Underscore is a good indicator during debugging

I really don't think that people writing TypeScript-applications are going to debug their applications in compiled JS. This is a total PITA and it's super easy to configure Source-Maps to debug in TypeScript.

{{dir.foo}} {{dir._bar}}

IMO this argument only persist as long as you don't use a good IDE. E.g. Webstorm already only shows the public fields of an object for auto-completion and I'm totally sure that tooling-support for ng2 and TypeScript will become even better in the future:

class CalendarEntry {
  private formatter: any;
  constructor(public startTime: string, public endTime?: string) {

  }
}

@Component({
  selector: 'calendar',
  ...
})
export class CalendarComponent {
  calendarEntry: CalendarEntry;
}

bildschirmfoto vom 2016-04-19 09 15 41

Also you don't ask people to prefix their interfaces with "I" like ITaskService only to add semantics - your IDE will tell you cannot use extends with the interface so their is no need to encode this into the naming.

I guess this is also for Dart "compatibility" where the _ actually makes members private.

In my opinion you should use Dart-conventions when writing your apps in Dart and you should use TypeScript-conventions when writing apps in TypeScript (So when writing apps in Plain old JS you should also use the underscore-prefix). You would never ask a Dart-Developer to name their files with dashes (e.g. customer-management.service.dart) as Dart uses underscores for filenames.

I think that the "mental model" should be, that it's a coincidence that TypeScript will become JS to be used in the browser, so IMO it's quite of bad to transfer old "JS-Hacks" in the shiny new TS-world ;)

Still I'm not 100% sure about it, but I think Angular should be really careful what to promote here, especially when violating the underlying languages rules.

/cc @johnpapa @wardbell

@zoechi
Copy link

zoechi commented Apr 19, 2016

In my opinion you should use Dart-conventions when writing your apps in Dart and you should use TypeScript-conventions when writing apps in TypeScript (So when writing apps in Plain old JS you should also use the underscore-prefix). You would never ask a Dart-Developer to name their files with dashes (e.g. customer-management.service.dart) as Dart uses underscores for filenames.

This would make ts2dart more complicated because names would need to be changed. In your application, if you don't intend to make your packages available to Dart or JS, then you are free to not use _ anyway.
If this style guide should also apply for contributions to Angular, then I think requiring _ for private fields is valid.

@choeller
Copy link
Author

@zoechi I see that this is true for the development of angular itself (the framework) but I just don't see the use-case to compile my own app to Dart, or am I missing something here?

if you don't intend to make your packages available to Dart or JS, then you are free to not use _ anyway. If this style guide should also apply for contributions to Angular, then I think requiring _ for private fields is valid.

I think you really hit the point here: contributing to angular has kind of special requirements because of the ts2dart thing etc. but for at least 99% of the people out there this is irrelevant. IMO the style-guide should be meant for the developers out there getting up and running with the platform - for Contributors there already is a detailed documentation on what to pay attention (https://github.com/angular/angular/blob/master/CONTRIBUTING.md#rules)

@gkalpak
Copy link
Member

gkalpak commented Apr 20, 2016

While it's not important for apps, when developing re-usable "3rd-party" modules/widgets/libraries that are meant to be consumed by people which might not use TypeScript (i.e. consume the compiled code), it is much better to preserve some semantics that can't be otherwise communicated in "plain" JS.

Like I said, for an app (that is not meant to be consumed as a dependency by another product), it doesn't make a difference. But it would be very confusing to have a guideline that says: "Use this naming convention when developing a 3rd-party module, but use another naming convention when developing your app".

Not to mention that not all people are using IDEs 😛

Anyway, it's a less than ideal situation because of the fragmentation (different languages, differents IDEs/editors, different tools), but (for the time being) the _ should stay.

m2c

@choeller
Copy link
Author

Like I said, for an app (that is not meant to be consumed as a dependency by another product), it doesn't make a difference. But it would be very confusing to have a guideline that says: "Use this naming convention when developing a 3rd-party module, but use another naming convention when developing your app".

I think this is the main point where our opinions differ. When creating a public API you always need to think about the target-system. E.g. when creating a JSON/REST-Interface in Ruby you would not define the fields with snake_case, but you would also not write all your ruby code in camelCase just because of an API you need to provide.

Looking at all major blogs and resources writing about Angular 2 you can see that people are already embracing the new language features. E.g. @PascalPrecht's toughtram (http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html) @vsavkin's blog (http://victorsavkin.com/post/137821436516/managing-state-in-angular-2-applications) @gsans's medium articles (https://medium.com/google-developer-experts/angular-2-introduction-to-redux-1cf18af27e6e#.94p98vo6x), the ionic-blog (http://blog.ionic.io/ionic-2-and-auth0/). @jashmenn's ng-book (https://www.ng-book.com/2/), all of the currently available popular starter kits, the egghead and udemy video courses. etc. etc. I really don't think that all of them did that accidentally, so this shows, that people "like" the new TypeScript features and use them.

I would really love to hear the opinions of more people then the ones already involved in the decision here johnpapa/angular-styleguide#703. Maybe I overrate the namings, but now asking developers to stick with their old habits (and violate microsofts guidelines for TS) just because of some JS-Backwards-compability things, to me seems like a big step backwards...

@CaptainCodeman
Copy link

Languages that don't have public / private accessors need a convention such as _ to "suggest" what is and isn't safe to use.

When accessors are available the convention is no longer required and can actually become unhelpful because it can now be wrong and misleading. Suppose you have private _config:Config and then need to make it public - why should you need to rename the variable vs just change the accessor to public? What does public _config:Config mean?

There should never be that many variables in a class or such a big block of code that being able to see what is an isn't public is a major undertaking IMO.

@NoNameProvided
Copy link

I would really love to hear the opinions of more people then the ones already involved in the decision

I have been using ts for a while (not with angular) and a week ago we started using ng2 in our new projects, and one of my colleague used '_variable' names for private variables and he told us that it's in the recommendation. I just didn't want to believe him so that is how I ended up here. I find it very weird and unnecessary to prefix private variables with an underscore when we code in typescript.

In my opinion you should use Dart-conventions when writing your apps in Dart and you should use TypeScript-conventions when writing apps in TypeScript

I think this is the point, the style guide itself is written in typescript, so it should embrace good practices in typescript not best practices in plain js or dart.

@wardbell
Copy link
Contributor

wardbell commented Apr 22, 2016

My $0.02.

I'm starting to regret my support for _ prefix and think that we should drop it.

The best argument I've seen here is cross-language support ... both in code and the style guide.

@choelle is convincing w/r/t the direction of the TypeScript ecosystem and the dubious need to cater to people debugging TS in JS (people like me ;-)).

IMO, it is not possible to write a cross-language StyleGuide. While many of the recommendations makes sense everywhere ("Avoid data access code in components; delegate to a data access service"), many are language specific. One simply does not write components in JS the way one would in TS.

Our first Style Guide is a TS Style Guide. We have the ability to reuse, share, and swap guidelines for Style Guides versioned in other language tracks.

Therefore, I vote for dropping the _ prefix in all TS samples.

Let's see what @johnpapa thinks.

p.s.: I think Microsoft guidelines are an important source. They are based on deep experience of talented developers. We should be reluctant to depart from them and not do so casually. But, IMO, they are not determining factors either.

@johnpapa
Copy link
Contributor

I 100% agree with no underscores. It's already in my revised draft. You will see it in the next week or so.

This is a typescript style guide. So we will use what makes the most sense for Ts

@johnpapa
Copy link
Contributor

BTW - keep in mind that this guide is very very very very early and not publicly linked to in the menu. This is on purpose. Once we feel there is gold here, we will add it to the menu. But right now, it's placeholders and thus not ready for public consumption.

That all said, I'll repeat I 100% agree in removing the _. And I invite and welcome all constructive and respectful feedback on the guide now and moving forward.

Thanks for the conversation.

@mirkonasato
Copy link

It's not just the style guide. The tutorial on angular.io says:

We prefix private variables with an underscore (_) to warn readers of our code that this variable is not part of the component's public API.

@Foxandxss
Copy link
Member

That is not a problem. Once the styleguide is in and we have our conventions stablished, we will update all the doc.

@wardbell
Copy link
Contributor

ONE EXCEPTION. I still like _ for the backing field of a defined property.

private _foo:string;
get foo() {return _foo;} // foo is read-only to consumers

@Foxandxss
Copy link
Member

Oh, forgot about that one too. Here we have no choice I think, the modifiers won't work in this case so underscore is needed.

@johnpapa
Copy link
Contributor

@Foxandxss that's fine. PRs work :)

@choeller
Copy link
Author

Cool, glad to hear this! Thanks a lot for the feedback! I guess I should close this one now...

@wardbell wardbell reopened this Apr 23, 2016
@wardbell
Copy link
Contributor

wardbell commented Apr 23, 2016

Re-opening so that we remember to sweep the docs and samples!

Jesus - if you are up to it and want to start the process, please do!

@flyingsky
Copy link

I like underscore prefix, because it's easy to know it's private when I just read the code. Not everybody has or likes WebStorm. Readable code should not depends on some special IDE.

I don't think all typescript guidelines from MS is good, such as

"Use double quotes for strings.",
"else goes on a separate line from the closing curly brace."
"Use 4 spaces per indentation."

So I like @Foxandxss words:

"Or maybe we should change Microsoft's guidelines :)"

@wardbell
Copy link
Contributor

We opted to drop the _ prefix and are sweeping the docs to conform.

@thilehoffer
Copy link

If I have a property like
private _foo :boolean
get foo(){ return _foo;}

If I drop the underscore? How do I name the private property different than the get operator?

@thilehoffer
Copy link

Thanks. How to tell Resharper this :)

@NoNameProvided
Copy link

I have never used ReSharper but in Webstorm you can create snippets with predefined jump locations in the snippet. That could be a solution for you. :)

@CSchulz
Copy link

CSchulz commented Oct 20, 2016

The referenced coding guidelines are used for the TS code base and they are not a recommendation for other projects, see microsoft/TypeScript#11227

@bmingles
Copy link

@johnpapa I'm curious if there is a specific design reason why _ prefixing is not desired for private members? Honestly not disputing the decision, just want to understand if there are specific design reasons vs preference.

@Foxandxss
Copy link
Member

because private is enough "private", you don't need anything extra.

underscore was used in the past with javascript because there was no private, but there is no need nowadays.

@bmingles
Copy link

@Foxandxss Thanks. Definitely makes sense that it isn't necessary. I just want to understand if there is anything inherently bad in using _ or any gotchas I'm not thinking of if it is a convention I decide to use.

@Foxandxss
Copy link
Member

There is no problem at all if you do that. The most important thing is being consistent. Either you do it or you don't. But not in certain files only and not in others.

@wardbell
Copy link
Contributor

wardbell commented Dec 21, 2016

NB I still find it handy for backing fields as in

private _foo;
get foo() { return this._foo; }
set foo(value: any) { 
  console.log(`${this._foo} changed to ${value}`);
  this._foo = value;
}

@denu5
Copy link

denu5 commented Jan 12, 2017

I see it problematic not to use underscores in this case:

private myVar;

...
..
get myVar(){
    return this.myVar;
}

this will cause a duplicate entry error. having an underscore as a prefix would have solved this issue 😒

@NoNameProvided
Copy link

@denu5 As the above comment says, its desired to use the underscore when a getter/setter is defined.

@josersleal
Copy link

Am I wrong and the founding fathers already ad this disscussion long time ago and that's (LONG TIME) maybe why the question keeps coming up?
To me, the fact that there is a doubt, it's a smell.

To me it seems that this is so unimportant that once you read the book (from the founding fathers) you just follow up and forget about it...
PS: do as you feel better, however if teaming up with me, you're going to drop any prefix to indicate what a variable is: the compiler already know it, the developer gets confused (read the book)... private var lowCase, public var InitialCaser (thats a camel for you that did not read the book)
welcome to OOP done right

https://en.wikipedia.org/wiki/Hungarian_notation
PS: my 5c, don't lynch me because you don't like reading romance..

@denu5
Copy link

denu5 commented Mar 16, 2017

@josersleal ok, so you never use the new cool es6 getters/setter. what will you do in this situation?

private _myVar;

...
..
get myVar(){
    return this._myVar;
}

Ps. which book? i'm interested to improve oop skills 😄

@isometriq
Copy link

Just thinking ..is there any way to add the underscore automatically for private members during compilation? ..a compiler option could even allow to decide if it is used. Is that impossible?

@isometriq
Copy link

isometriq commented Apr 8, 2017

For getter/setter, it would be nice the compiler to understand this, like in Java:

private myVar;
getMyVar() { return myVar; }
setMyVar(val) { myVar = val; }
...
myObj.myVar = value;

@isometriq
Copy link

isometriq commented Apr 8, 2017

Another of my head... readonly keyword covers a lot of cases when only getter is needed

private readonly myVar1; // getter only
myVar2; // getter and setter

EDIT: nevermind this, only useful in constructor...

@NoNameProvided
Copy link

NoNameProvided commented Apr 9, 2017

For getter/setter, it would be nice the compiler to understand this, like in Java

Plain JS already have getter/setter methods:

class MyClass {
  let num = 5
  get specialNumber() {
    return this.num + 2;
  }
  
  set specialNumber(value) {
    this.num = value;
  }
}

@josersleal
Copy link

josersleal commented Apr 9, 2017

private myVar;
.
get MyVar(){
return this.myVar;
}
.
imo what the compiler should get (kkk) is
MyVar {get; set}

readonly is supported, also if you define a get and no set readonly is inferred (I just googled it... kidding, I read the book)

On what book:
Its a decoy... the book that we right (pun intended) is the only book, said that, it does not matter if we use '_' or not..
what matters is that we all use the same, because then we know how to read each other code.
However, since this was discussed long time ago, the original request or question should never had been answered.. we reached a conclusion on how to write this long ago and that is all we need, who cares about a letter more or less? I personally only care that if its going to be there, than, that its always going to be there so I dont loose time searching for it or wondering what am I trying to read and understand.
PS: the compiler already knows (like it knows about string, numbers and others), I just dont care, theless I have to do the better, I am that lazy...
Happy coding...

@isometriq
Copy link

Plain JS already have getter/setter methods:
Yes I know that

What I mean is that if the TS compiler can understand the prefix "getVarname" and "setVarname", we would not be tempted to use a private with an underscore, but instead just "varname".

The compiler could automatically translate this (in TypeScript):

private varname = '';
getVarname() = {return varname;}
setVarname(val) = {varname = val;}

to this (in JavaScript):

var _varname = '';
get varname() = {return _varname;}
set varname(val) = {_varname = val;}

Maybe it's not possible, but that way seems like it would the best of both worlds.

@zoechi
Copy link

zoechi commented Aug 31, 2017

@ShinDarth what exactly are the inconsistencies?
Please consider creating a new issue, this one is closed.

@eun-ice
Copy link

eun-ice commented Nov 2, 2017

See #3137

@Justus-Maier
Copy link

Neither link explains or hints that the _privateProperty with underscore behind a Getter is an execption to the convention not to use underscore property names.
The handbook should explain and could link to the Styleguide, and the styleguide could link here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests