Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Do we still have a chance to stop private fields (with #)? #142

Closed
SCLeoX opened this issue Oct 12, 2018 · 125 comments
Closed

Do we still have a chance to stop private fields (with #)? #142

SCLeoX opened this issue Oct 12, 2018 · 125 comments

Comments

@SCLeoX
Copy link

SCLeoX commented Oct 12, 2018

It is clear to me that this "consensus" in the committee is against the majority of the community other than tc39.

I just want to know, what people like me, who really do not want this private fields thing (with #) to be added into JavaScript, can do to prevent it from happening.

@littledan
Copy link
Member

Honest question: How do you think we in TC39 should assess how the majority of the community will feel about a proposal once they try it out a bit? I want to figure out how we can improve the process for future proposals.

(I suggested that we require a transpiler implementation earlier in the process, but this suggestion was rejected by the committee; anyway, just an implementation isn't enough without a mechanism for collecting feedback.)

@mbrowne
Copy link

mbrowne commented Oct 12, 2018

Just FYI to anyone who isn't aware, private fields using # are now available in Babel 7. I agree it would have been good if this had happened much earlier.

...and I just noticed that the readme of this repo has been updated as well, with the status of several implementations in progress, including a native one in Chrome (behind a flag).

@littledan
Copy link
Member

Yes, delaying the Babel implementation was definitely an error on my part in this proposal.

@SCLeoX
Copy link
Author

SCLeoX commented Oct 12, 2018

@littledan I think there should be a vote or something of similar nature when a proposal is controversial.

I had a discussion in a JavaScript group with a couple experienced JavaScript developer. We come to a consensus very quickly that the idea of having private fields are awesome, but # is just too ugly and weird.

Usually, when there is a new feature being add to JavaScript, we really get hyped but it is just not the case this time.

@jhpratt
Copy link

jhpratt commented Oct 12, 2018

@SCLeoX And what is the alternative to #? The private keyword was rejected because it didn't meet all of the TC39's requirements.

@mbrowne
Copy link

mbrowne commented Oct 12, 2018

@SCLeoX regarding developers who would vote solely based on their initial reactions of finding it "ugly and weird", without taking the time to deeply understand the technical considerations, I am glad that just the average developer cannot vote (and just to be clear, I am not a member of the committee). If the committee just had 2 or 3 members and/or they were totally disconnected from the community, that would be a real problem, but fortunately I think the community is overall pretty well-represented on the committee. At least 95% of the complaints about the syntax are coming from people who haven't really considered the technical issues involved, including those mentioned in the FAQ.

@SCLeoX
Copy link
Author

SCLeoX commented Oct 12, 2018

@jhpratt
That is my problem though. I am saying it will be better if there can be alternative, but if not, I would rather not having this than having it.

@SCLeoX
Copy link
Author

SCLeoX commented Oct 12, 2018

@mbrowne However, if you think about it, most of other proposal will not have any problem if any average developer can vote. On the other hand, I am almost certain that this # thing will have a hard time passing 50%.

Yes, I understand there is technical difficulties, but shouldn't we try not to disrupt the overall beauty of JavaScript at the same time?

@slikts
Copy link

slikts commented Oct 12, 2018

There is a deeper ugliness in not being able to hide implementation details while still taking advantage of delegation. It complicates API design and implementation and invites poor practices. This should outweigh the syntax just being unfamiliar.

On the topic of voting: it's a bad idea simply because it's so open for manipulation and reflexive reactions. What's needed is thoughtful consideration, not counting upvotes or downvotes or sloganeering.

@mbrowne
Copy link

mbrowne commented Oct 12, 2018

@SCLeoX

However, if you think about it, most of other proposal will not have any problem if any average developer can vote.

I highly doubt that is true. I haven't been very much involved in discussions about proposals other than this one (and a little bit with decorators), but I'm sure people can give examples of other proposals where making decisions just based on the community's initial uninformed reaction would have been disastrous.

Regarding the ugliness, that seems to be the common reaction and the committee members have said they don't find it aesthetically pleasing either and would have preferred to use a more intuitive syntax if possible. (I seem to be in the minority; I never disliked it for aesthetic reasons since I appreciated the conciseness, which is kind of handy if you believe as I do that encapsulation is really important and that "private" should be the starting point rather than just making things public without thinking about it. But I understand why others don't like it.) Anyway, it's not as if the committee deliberately chose this syntax against the wishes of the community. As explained in the FAQ and in past discussions here, significant problems were found with every other alternative that was presented.

@SCLeoX SCLeoX closed this as completed Oct 12, 2018
@hax
Copy link
Member

hax commented Oct 16, 2018

@SCLeoX @jhpratt

Alternatives without # existed. Check https://github.com/zenparsing/js-classes-1.1

Classes 1.1 proposal is created and presented by: zenparsing who is one of the champion of this proposal but do not agree # solution, awb who is the editor of ES2015, Brendan Eich who you must know.

But classes 1.1 is rejected, mainly because not include "public field", and I believe that is a big mistake.

You could check whether you like classes 1.1 and check recent issues in the repo for further discussion.

@hax
Copy link
Member

hax commented Oct 16, 2018

@littledan

How do you think we in TC39 should assess how the majority of the community will feel about a proposal once they try it out a bit?

Simple.

I'd like to invite you, or any other champion who can represent this proposal to the one of the biggest front-end and JavaScript conference in Hangzhou, China on Jan 6, 2019. You can introduce this proposal, and I would like to present classes 1.1 proposal, and let them vote. 😂

Or, if you think I use my mother language in China is unfair to you ... it seems you will go to Tokyo next month give a speech. Just ask the organizer invite me too. Remember my English is very poor, but I still like to have a try.

@littledan
Copy link
Member

littledan commented Oct 16, 2018

I'd be really happy to attend a conference in China and discuss these sorts of issues (even though I only speak European languages--sorry!). I'm a bit overloaded on travel right now, and was thinking to try to take it slow after the Japan trip, but maybe some time later in 2019 would be good. Is there another conference in China that you'd recommend (or I could attend this one in 2020)?

@littledan
Copy link
Member

I'd also be happy to have a video call to discuss this topic further, if folks would be interested.

@hax
Copy link
Member

hax commented Oct 16, 2018

@littledan

I'd be really happy to attend a conference in China and discuss these sorts of issues (even though I only speak European languages--sorry!).

I used to think English is one of the European languages, no? 🤣

I'm a bit overloaded on travel right now, and was thinking to try to take it slow after the Japan trip,

Do you like to recommend any other TC39 member like @bakkot , Jeff Morrison or Shu-Yu Guo for Jan 6, 2019 conf? Though I think you may be the best one. 😉

but maybe some time later in 2019 would be good. Is there another conference in China that you'd recommend

Some conferences have not started to arrange schedule, for example JS Conf China. I only know CSS Conf China will be in 2019-03-30 .

(or I could attend this one in 2020)?

I'm afraid it's too late, as current situation, it's likely you already push it to stage 4, and landed in browsers in that time. 😂

@hax
Copy link
Member

hax commented Oct 16, 2018

@littledan

Yes, delaying the Babel implementation was definitely an error on my part in this proposal.

It's unfair that classes 1.1 do not allow to forward even stage 0, which just make it can't have Babel implementation.

@hax
Copy link
Member

hax commented Oct 16, 2018

@SCLeoX regarding developers who would vote solely based on their initial reactions of finding it "ugly and weird", without taking the time to deeply understand the technical considerations, I am glad that just the average developer cannot vote (and just to be clear, I am not a member of the committee).

It's a dangerous assumption that the dislike of "ugly and weird" from average developers is pointless. I see it indirectly reflect the mental model of most people, which TC39 should consider when design syntax. Especially there are some alternatives which do not use #. On one hand, you treat the dislike of # as pointless, on other hand, you nitpick on the syntax of alternatives.

And, as my observation, the dislike of # is general, whoever he/she is newcomer, average, experienced or master!

At least 95% of the complaints about the syntax are coming from people who haven't really considered the technical issues involved, including those mentioned in the FAQ.

Well it's not very pleasant, but I hope all TC39 members should see it in another, more sympathetic way: most developers do not have the knowledge, experience, chance, power to design/evolve a programming language, and normally they just accept anything you give them and never complain. There are many other proposals, why they only came here? Because it's important to them, and they feel really bad and have no other way to feedback. I don't know how you get the number 95% , but I bet that even they read FAQ, there is 95% chance they will also complaint.

And it is said, when you see one cockroach in your kitchen, it already have hundreds. So you see one such complain here, there would be hundreds on twitter, thousands in private conversation. Think about it!

@SCLeoX
Copy link
Author

SCLeoX commented Oct 16, 2018

Beside this classes 1.1 proposal, there are many other proposal being rejected due to much less significant issues or without any proper evaluation. For example, using this#x instead of this.#x. (tc39/proposal-private-fields#39 (comment)) The only reason it is being rejected is it "would be an ASI hazard if we later introduced a shorthand syntax of #x". To be more clear, the entire reason is established upon an assumption that if a shorthand is to be implemented. When @jamiter questioned why there needs to be a shorthand, @littledan responded: "Even if the shorthand didn't exist, I kinda like the obj.#x syntax". That is just straight up BS. Saying you prefer "this.#x" does not invalidate "this#x".

@mbrowne
Copy link

mbrowne commented Oct 16, 2018

@hax Looking back and my previous comment, I regret that I didn't try to give it a friendlier tone. I know that in written discussions, honesty can be mistaken as meanness or condescension. As I have said in stronger terms on other issues, I think the committee did not communicate with the community as well as they could have. Even if they were really listening and seriously considering all the feedback they received (which I believe at least some of the committee members were, at least those who actively follow the discussions here), the community didn't get that impression. I think it's important to put it in context though, because in the past, the committee used a separate mailing list that I guess was public since its archives would show up on Google, but it didn't really seem like it (it looked mostly just like committee members talking to each other)...overall I feel like involvement with the community is much more open now than it used to be. After all, anyone with a github account can post comments here and someone will respond.

This open access is why I think it's important to discourage lots of uninformed comments and/or voting from people who have not taken the time to understand the deeper technical issues, even though I agree that most of that is coming from people who are just innocently trying to express their concerns. We are already all very aware that most people find the syntax ugly and weird when first encountering it, so more and more issues essentially just repeating that are not going to change anything and affects the signal to noise ratio. Can you imagine what StackOverflow would turn into if no one bothered to enforce their policies on questions and answers? Everyone's time is valuable, not just the committee's of course, and pointing people to the FAQ if it appears they haven't read it saves everyone time.

Also, it seems you missed the importance of the word "solely" in this sentence:

regarding developers who would vote solely based on their initial reactions of finding it "ugly and weird"

Well it's not very pleasant, but I hope all TC39 members should see it in another, more sympathetic way: most developers do not have the knowledge, experience, chance, power to design/evolve a programming language, and normally they just accept anything you give them and never complain.

You're right, the majority of developers don't have the background and/or opportunity (maybe just due to lack of time) to really dig into all the technical details and learn how to read and understand the spec, and understand the various tradeoffs being discussed. (Being mostly self-taught on things related to language design, I too find the spec hard to read.) This is why we have a committee, but on the other hand we need to be compassionate and remember how many millions of developers of all backgrounds will be affected by this, and it underscores the importance of developer-friendly documents like the readme and the FAQ (and hopefully a forthcoming document listing requirements and general justification of their prioritization for this proposal).

And it is said, when you see one cockroach in your kitchen, it already have hundreds. So you see one such complain here, there would be hundreds on twitter, thousands in private conversation. Think about it!

It's hard to know whether or not you are right about this. The other side of this coin is that usually the people who disagree the most are the ones who are most vocal. There could be just as many people who would be fine with this, even welcoming of it, even if it's not their favorite syntax. If this proposal moves forward as-is then the next task will be to explain more widely why the syntax was chosen. There are indeed good reasons that hopefully most people will understand when they read about it (even those who still wish the committee had prioritized things differently). It's not really a great test to just give a talk with a brief overview of this topic and assume that the audience really understands the ramifications if their immediate response would be to vote "no" on the syntax. OTOH, clearly other proposals including classes 1.1 could be viable, so I don't mean to be too dismissive of these reactions.

@SCLeoX SCLeoX reopened this Oct 16, 2018
@hax
Copy link
Member

hax commented Oct 16, 2018

@SCLeoX

Beside this classes 1.1 proposal, there are many other proposal being rejected due to much less significant issues or without any proper evaluation.

I agree!

For example, using this#x instead of this.#x. (tc39/proposal-private-fields#39 (comment))

Good catch.

The only reason it is being rejected is it "would be an ASI hazard if we later introduced a shorthand syntax of #x".

Actually this is not a big issue in practice. Just use this[no-newline]#x.

To be more clear, the entire reason is established upon an assumption that if a shorthand is to be implemented. When @jamiter questioned why there needs to be a shorthand, @littledan responded: "Even if the shorthand didn't exist, I kinda like the obj.#x syntax". That is just straight up BS. Saying you prefer "this.#x" does not invalidate "this#x".

You are right.

The main reason they prefer this.#x is the slogan: #x is new _x.

@hax
Copy link
Member

hax commented Oct 16, 2018

@mbrowne

It's not really a great test to just give a talk with a brief overview of this topic and assume that the audience really understands the ramifications if their immediate response would be to vote "no" on the syntax.

No. It's a good test.

You are not introducing a very big feature, so if you can't explain and convince them it's a good proposal in 45 mins, you can never in the future.

Actually I think "this.#x is new this._x" is a good slogan, and I'd like to see @littledan or other to try, which may prove that my worry about community break is superfluous.

@littledan
Copy link
Member

Actually this is not a big issue in practice. Just use this[no-newline]#x.

That's a technical fix, yes, but many people use method chaining like this:

foo
   .bar()
   .baz()
   .bing()

In this mode, if . is replaced by #, you run into the issue.

Anyway, I like .# because it reinforces that the hash is part of the name, rather than being an operator. I hope this makes it easier to remember to never leave it out.

@hax
Copy link
Member

hax commented Oct 17, 2018

@littledan

In this mode, if . is replaced by #, you run into the issue.

Yeah you are right, though I think chain like foo#a()#b()#c() is rare. I crossed out my original sentence.

Anyway, I like .# because it reinforces that the hash is part of the name, rather than being an operator. I hope this makes it easier to remember to never leave it out.

Actually, I totally agree with you in this single point. I can agree many specific point in many concrete cases. But the problem is your premises of this proposal are too many, too related, which I believe, make the whole proposal weak, and hard to convince all (even you could eventually convince me). And it will just cause community break which I think what's "this is the end day of JS" in twitter really mean.

Here is your premises I can collect from all the threads:

  1. semantics requirement of privacy solution, and impossible to Java-like syntax
  2. must land public field now, even no strong evidence tell us public field is a must to have uptonow, even redefinition of property from base class is a footgun, even other OO languages just discourage public field usage, even js programmers never have chance to try the replacement (accessor wrap private state)
  3. public/private field syntax duality is good, even the semantics very different, which cause issues
  4. can't add keyword for any reason, because it will bring syntax storm due to the duality

Note 2, 3, 4 are very related.

With all these premises established, I could agree the best available form for private is this.#x. But,

  • For point 1, I am not against it at all, but many try to challenge it as they see it's the reason of ugly #.
  • For point 2, I strongly disagree.
  • For point 3, I totally admit the good part of duality (aka. "this.#x is new this._x"), but the duality could be good only when point 2 establish. And the contradiction between "no java style" from point 1 with duality in point 2 just draw fire which I think you can never escape. And the ignorance of semantic difference could bring programmer (especially TS programmers) bad experiences when they do migration to JS real private.
  • For point 4 (you may not admit), it makes proposals fragile and rigid, significantly reduce the design space of the syntax for all related and future features, which I think it's bad. And eventually programmers are just forced to use decorators to mimic keyword.

This is all I can say, and I think classes 1.1 keep point 1, solve 2, 3, 4: no public field (at least in the form of this proposal), so no duality, adopt keyword, eventually no controversial # which I think is good to the community and make the whole ecosystem easier to move to the JS native privacy solution.

@SCLeoX
Copy link
Author

SCLeoX commented Oct 17, 2018

@littledan I do not see how

foo
  #bar()
  #baz()

having any problem. # is the new ..

It just means to access the private property.

@littledan
Copy link
Member

@SCLeoX It would only have a problem if we adopted @hax 's suggestion where we prohibit line terminators before #.

@SCLeoX
Copy link
Author

SCLeoX commented Oct 17, 2018

@littledan But why do we need to prohibit that...

this
  #bar()
  #baz()

will always mean this#bar()#baz() unless shorthand syntax (#bar()) is implemented. However, I don't think the original proposal mentioned anything about the shorthand.

@littledan
Copy link
Member

If we do add the shorthand syntax, we can't change the meaning of existing programs at the time that we're going back and adding it.

@ljharb
Copy link
Member

ljharb commented Nov 22, 2018

@hax no, a reflection mechanism for private would go against my use cases, as it's not actually private if it is in any way observable from outside the class - but we're talking about public. What Object.keys and friends were designed for is irrelevant - what I'm talking about is what they're used for.

@hax
Copy link
Member

hax commented Nov 22, 2018

PS. I still want to see use case in real "concrete form", aka. the code sample. For example, I never see Object.keys() usage in React class-based component, it's hard for me to understand, why handler = () => { this.setState(...) } is a data property which you want to reflect. 😂

@trotyl
Copy link

trotyl commented Nov 22, 2018

@mbrowne It will still break when there's a setter in base class:

class Base {
  set x(value) { }
}

class Sub extends Base {
  constructor() {
    super()
    this.x = 2
  }
}

const s = new Sub()
Object.keys(s) // []

So I'm not sure if this requirement really makes sense in practice.

@hax
Copy link
Member

hax commented Nov 22, 2018

@ljharb

no, a reflection mechanism for private would go against my use cases,

How? Could you give code sample?

as it's not actually private if it is in any way observable from outside the class

Provide a reflection mechanism for private never necessarily mean observable from outside. For example, assume we use private symbol as the underground mechanism, and expose them via meta property which only available inside the classbody, we just provide the reflection without leaking them to outside. Of coz the authors of classes could intentionally exposed the private keys to outside, and actually it's a good feature for protected or friend-like use cases and solve another important issue raised by objectors.

What Object.keys and friends were designed for is irrelevant - what I'm talking about is what they're used for.

I don't want argue whether using a feature in a way which against its original design purpose is a valid proof for future design. Let's just focus on real use cases now.

@hax
Copy link
Member

hax commented Nov 22, 2018

@trotyl

It will still break when there's a setter in base class

Good catch! 😂

Another -1 for [[Set]] though both scores of [[Define]] and [[Set]] are already very negative 🤣

You look much deeper, you just find much gotchas of current proposal!

So I'm not sure if this requirement really makes sense in practice.

Actually I think the motivation makes sense, but it just have gotchas! We should learn something from that, and guess what? The reflection mechanism for private states I previous described can really satisfy the use cases and have no such gotchas at all.

@mbrowne
Copy link

mbrowne commented Nov 22, 2018

What a mess...if we learn nothing else from this, we should learn the importance of long-term thinking and accounting for future evolution of the language when doing language design. I'm not trying to insult the champions of past proposals who are brilliant and had great foresight in many ways, I'm just saying this is an opportunity for reflection (no pun intended).

@rdking
Copy link

rdking commented Nov 22, 2018

Double standard...you've frequently talked about the importance of maintaining established conventions of the language, and yet here we are...

Not a double standard, but a potential new feature. I'm asking if his use case could be satisfied by such a new feature, which would be the case if the uses of the mentioned standard functions comes from code he can freely modify. If however, the code is 3rd party, then such a proposal still wouldn't satisfy his need. I'm trying to assess the source nature of the problem. Nothing more.

@hax
Copy link
Member

hax commented Nov 22, 2018

@mbrowne

because there are still valid use cases like the one above as well as classes that don't use inheritance.

You are suggesting we could only consider classes usage without inheritance and ruin the classes usage with inheritance.

To be honest, I think inheritance is a risky feature (in all OO languages), programmers need to use it cautiously, we could educate js programmers be careful about inheritance, but adding new language features with traps and footguns to inheritance could never be a education, it just harm the developers.

If such breaking thing landed, we will only have two choices:

  1. Do not use public field in classes which rely on inheritance, and pray all the programmers of upstream (baseclasses) and downstream (subclasses) acknowledge and agree this principle and have good disciplines and robust workflow to avoid any accidently violating of this rule.

  2. Never use inheritance.


Forgive my off-topic rant (I can't hold myself 😫):

Guess what? I will choose 2. And to be honest, it just make the class and prototype mechanism as garbage, yes, OO sucks, especially in JS with class field, and let move to FP (wait, could TC39 first solve STC vs PTC problem? Without tailcall, FP in JS is just garbage.)

@mbrowne
Copy link

mbrowne commented Nov 23, 2018

You are suggesting we could only consider classes usage without inheritance and ruin the classes usage with inheritance.

No, I'm saying that this already works in ES6 classes for public enumerable properties without getters and setters, so existing behavior should continue to be supported with the class fields feature. This wouldn't ruin anything that's not already broken. And it's already widely known that Object.keys/values/entries only works with own properties so I don't think people have the expectation that it will work with all inheritance cases anyway. The new feature should continue to enable useful patterns and methods that people are already using, as long as there are good reasons to motivate their usage which I think there are.

But I do agree that a new, more robust reflection API that avoids these problems would be a great thing and that idea should be pursued as well—in addition, not instead of.

@mbrowne
Copy link

mbrowne commented Nov 23, 2018

Regarding the OO paradigm in general, I realize this is primarily an engineering discussion, but given that people have so many different understandings of it and there's so little knowledge of the original history I think this brief article could be very educational:

https://medium.com/@egonelbre/relearning-oop-89f10e0e2f68

This is very relevant to the discussion because we shouldn't just be looking at Java, C# and C++ as perfect models to follow even if we only cared about OO and not any other paradigms. Many of my opinions have been about what's practical, but the bigger picture is more important; let's remember that OO doesn't have to be defined so narrowly.

@mbrowne
Copy link

mbrowne commented Nov 23, 2018

P.S. When I said, "There's so little knowledge of the original history" I didn't mean to imply that everyone here is unaware of this history; I probably should have phrased that better. But I'm sure at least some of the people reading this or who will read it in the future are unaware. And I too learned some things from the article (which I just discovered) even though I've researched this topic before.

@hax
Copy link
Member

hax commented Nov 23, 2018

@mbrowne

No, I'm saying that this already works in ES6 classes for public enumerable properties without getters and setters, so existing behavior should continue to be supported with the class fields feature.

A. We should never add feature which would break "using ES6 classes for public enumerable properties without getters and setters".

B. We should also never add feature which would break "using ES6 classes for encapsulation which may use accessors and inheritance".

Can we agree don't break current usage have much higher priority than introducing new features?

If you agree, as we discussed, current [[Define]] semantic just violate B. Though [[Set]] semantic doesn't violate B directly, it have many other issues. [[Set]] is not as worse as [[Define]], but it's hard to convince all it's better than [[Define]].

This wouldn't ruin anything that's not already broken.

Do you imply inheritance and/or accessors are already broken in ES6? I would like to see the proof. But I am very confident that follow the similar logic you would use, Object.keys/values/entries usage with ES6 classes was also already broken.

And it's already widely known that Object.keys/values/entries only works with own properties so I don't think people have the expectation that it will work with all inheritance cases anyway.

Not sure about it... How could a programmer use Object.keys/values/entries to inspect an object and make sure the class of the object never use inheritance and accessors if the class is out of his control?

The new feature should continue to enable useful patterns and methods that people are already using, as long as there are good reasons to motivate their usage which I think there are.

Before enabling, we first need to avoid disabling current usage.

@mbrowne
Copy link

mbrowne commented Nov 23, 2018

But I am very confident that follow the similar logic you would use, Object.keys/values/entries usage with ES6 classes was also already broken.

Yes, that was actually the point I was making. Object.keys/etc already doesn't work with getters and setters in ES6 classes but it does work with public enumerable properties. You've made it very clear that you're against public property declarations in the first place, but there are plenty of good reasons to want them including these enumeration use cases...and if we're going to have them then they definitely shouldn't "break current usage". This means ensuring that the old syntax still works (which it does; this proposal doesn't break any existing syntax) and also providing a new, declarative syntax for public properties that doesn't break established expectations based on the old syntax.

How could a programmer use Object.keys/values/entries to inspect an object and make sure the class of the object never use inheritance and accessors if the class is out of his control?

This is also a pre-existing issue, and the correct way to deal with it currently is to only use Object.keys/etc on instances of classes that you control (or, I suppose, if your third party library makes some sort of guarantee about this). This proposal doesn't change that.

Consider a class that produces immutable objects with only public but non-writable data properties (and no accessor methods). I think that using Object.keys/etc with such objects is entirely reasonable. Perhaps @ljharb has other uses in mind as well.

@hax
Copy link
Member

hax commented Nov 26, 2018

@mbrowne

Yes, that was actually the point I was making. Object.keys/etc already doesn't work with getters and setters in ES6 classes but it does work with public enumerable properties.

So we have agreement that Object.keys/etc doesn't fit ES6 classes well?

And we should also have agreement that Object.keys/etc fit factory pattern which do not use classes but only use object literals.

You've made it very clear that you're against public property declarations in the first place, but there are plenty of good reasons to want them including these enumeration use cases...

They can have good reasons, but we should agree it's not very wise to use classes for enumeration use cases, because you can only safely use it in classes without getters/setters. And it's very hard to enforce it. (especially when inheritance involved --- you need also enforce such rule in all upstream/downstream.) And such usage also collide with private fields.

From engineering point view, this is called: Bad Practice.

Why we develop a new language feature to support and encourage bad practice?

This is also a pre-existing issue, and the correct way to deal with it currently is to only use Object.keys/etc on instances of classes that you control (or, I suppose, if your third party library makes some sort of guarantee about this). This proposal doesn't change that.

Such constraint (only use Object.keys on what you can control) is hard to keep, and never scalable, if you consider the evolvement of the team and the project, for example when you factor out the class to be a separate component and eventually becoming a independent library.

Consider a class that produces immutable objects with only public but non-writable data properties (and no accessor methods). I think that using Object.keys/etc with such objects is entirely reasonable. Perhaps @ljharb has other uses in mind as well.

Too many prerequisites for you "reasonable use case". And () => ({ownprops:...}) is generally more suitable for such cases, and never require any prerequisites ( you could even use getter/setters in it! )

@rdking
Copy link

rdking commented Nov 26, 2018

The simple fact that we've had so many new features that involve object properties added without a complete set of tools to handle them is the reason for these types of debates.

@mbrowne

Consider a class that produces immutable objects with only public but non-writable data properties (and no accessor methods). I think that using Object.keys/etc with such objects is entirely reasonable. Perhaps @ljharb has other uses in mind as well.

This is a valid use case, but only 1 out of a very wide set of possibilities. What @hax has been trying to say is that this attempt to simplify use cases similar to this one ends up breaking the use cases that are dissimilar while simultaneously encouraging the use of this feature. The language loses flexibility as a result. If the feature isn't either useful or neutral to all reasonable use cases, then it encourages a bad practice.

@littledan
Copy link
Member

It seems like this thread discusses a number of different core design points for classes. I've tried to improve the documentation for these. I think we've reached a conclusion on the major questions, though.

@rdking
Copy link

rdking commented Jan 4, 2019

@littledan

I think we've reached a conclusion on the major questions, though.

No, we didn't as the main question was never answered. If I were to infer an answer based on what is present in so many other threads, the answer appears to be an unmitigated, unadulterated, unalterable

NO!

Stage 3 === Stage 4 - (docs + tweaks). It does not seem to matter if better ideas come along. No matter how it gets there, once a proposal is in Stage 3, only a catastrophic, unfixable, late discovered flaw in the proposal will prevent it from reaching Stage 4. Is this a valid assessment? That is the original, still unanswered question.

@littledan
Copy link
Member

Yes, a big enough problem with the proposal could lead to reconsideration. However, repeating things at length that have already been discussed in detail, where we have a good reason for having come to that conclusion, is unlikely to lead to changes in the proposal.

@hax
Copy link
Member

hax commented Jan 5, 2019

where we have a good reason for having come to that conclusion

Is this reason "good" enough?

Is that a real "conclusion"?


Even you had good reason for having come to conclusion for individual issue, Is there any process to measure the whole cost of all issues?

Obviously it's the motivation (avoid the whole cost) of classes 1.1 which prove that at least zenparsing, awb and BE don't agree the "conclusion"s of the whole, even they may agree the conclusion for individual issue before (actually I can't find their agreement for many individual issues in meeting notes.)


Repeat again, this is the process failure, not only this proposal, but also some other controversial issues of other proposals. The only difference is this proposal happened to have many controversial issues which make the failure much obvious.

@littledan
Copy link
Member

The process to measure the whole cost of the issues is asking the committee for consensus to advance stages. I'd like to improve the process by making sure the committee is more well-informed on community feedback in deciding on stage advancement. I believe the committee was well aware that various design decisions had a controversial dimension when it did agree to the advancement here, but I still think there's more to learn from the community, so I'd like to improve feedback mechanisms from here.

@rdking
Copy link

rdking commented Jan 5, 2019

@littledan I'm not trying to be mean. I'm just frustrated. So I'm going to try to say this as cleanly as I possibly can. Have you ever taken stock of how often you use an indefinite phrase like "I believe" when referring to the understanding of TC39 members when touting the "consensus"? It's not convincing at all when the documentation that does exist still shows concern being raised every time the issue of this proposal is addressed. Further, the simple fact that "!no !== yes" is being completely ignored by the voting process in use is perplexing at best. Every committee I've ever been on or watched has always taken a strict vote for such things:

  1. state the proposal
  2. all in favor - count
  3. all opposed - count
  4. notate abstained votes.
  5. follow some set of defined rules that accounts for all 3 types of vote.

I'm happy that you, as a representative of TC39 are showing signs that you understand the importance of the community opinion, and that you seem to want to improve the process being used by TC39. However, unless that change comes before the current proposal reaches Stage 4, it will be too little and too late to do anything about the damage this proposal will do, and with no decorators to fall back on to work around that damage.

@littledan
Copy link
Member

We just don't vote in TC39. It's an established practice from before I joined. Voting is only for certain formal procedural matters.

@mbrowne
Copy link

mbrowne commented Jan 6, 2019

In many cases, the "why" of this proposal has been explained but is scattered across many threads. In other cases things are still somewhat unclear, or at least it's still unclear why a particular X is deemed very important while Y is dismissed. It's often possible to infer the reasons for the latter cases and get a sense of the overall reasoning, but that obviously leaves room for misinterpretation or incorrect assumptions. These are the reasons why I created #178, to try to consolidate and clarify the reasoning. I think that thread is off to a good start.

@rdking
Copy link

rdking commented Jan 6, 2019

@littledan

We just don't vote in TC39.

And that's why the word "consensus" is such a misleading term. In truth, because TC39 does not gather and record the individual acceptance of the members, you really can't tell what the "consensus" is at all. All you really have is the knowledge that no one was willing to veto. The reasons apparently don't matter. This is not a judgement of TC39, but of the process it is using. This is a first for me, encountering a committee using such an indeterminate process.

I can't help but wonder if the results would be the same with a more deterministic process. But I'm letting this go. As an outsider, there's nothing I can do to affect it save for making my viewpoint clear. I think I've done more than enough of that. In the mean time, as with #202 and #203, I will keep pushing things that I think will decrease the severity of the issues TC39 seems willing to simply accept.

@ljharb
Copy link
Member

ljharb commented Jan 6, 2019

That’s what consensus means - taking a vote only makes sense if you have a voting-based process. For what it’s worth, i find consensus a far superior process to vote-taking, and I’m glad tc39 has taken the admittedly atypical path of avoiding votes. “Consensus” only means that nobody in the room blocked advancement, not that everyone agreed or that nobody disagrees - is there a better term you would prefer to describe that?

Determinism isn’t the goal, because the goal isn’t shipping things for the sake of shipping things - it’s to ship what’s hopefully the right thing, based on the information available and the stakeholders present throughout the process. I realize you disagree with the conclusion, but that doesn’t mean the process is broken (nor does it mean the process isn’t broken, of course - the two things are unrelated).

@rdking
Copy link

rdking commented Jan 6, 2019

@ljharb I'm sure you can understand my argument when "consensus" means "general agreement", but you just admitted that the way TC39 uses it's "not that everyone agreed". What you've been getting is a "tacit agreement". As an example: I hate the #. I don't think it fits the language at all. However, I agree that under the circumstances under which this proposal was formed, the sigil is probably the best choice. That's the nature of a consensus. People may disagree on the fine details, but over-all they agree with the result or concept. The mere fact that there are TC39 members vocal about and even producing counter proposals means you don't have a consensus. I think I'm going to stop quibbling over this here. You already get what I mean.

@ljharb
Copy link
Member

ljharb commented Jan 6, 2019

Consensus only matters in the room. Being vocal about counter proposals is not the same thing as “no consensus”, it’s simply an attempt to alter the consensus. A champion of a counterproposal who chose not to block advancement of this one has participated in that consensus process.

I get what you mean, but that’s not what consensus is - it’s indeed sufficient to have tacit agreement.

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