-
Notifications
You must be signed in to change notification settings - Fork 113
Do we still have a chance to stop private fields (with #)? #142
Comments
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.) |
Just FYI to anyone who isn't aware, private fields using ...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). |
Yes, delaying the Babel implementation was definitely an error on my part in this proposal. |
@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. |
@SCLeoX And what is the alternative to |
@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. |
@jhpratt |
@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? |
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. |
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. |
Alternatives without Classes 1.1 proposal is created and presented by: zenparsing who is one of the champion of this proposal but do not agree 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. |
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. |
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)? |
I'd also be happy to have a video call to discuss this topic further, if folks would be interested. |
I used to think English is one of the European languages, no? 🤣
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. 😉
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 .
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. 😂 |
It's unfair that classes 1.1 do not allow to forward even stage 0, which just make it can't have Babel implementation. |
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 And, as my observation, the dislike of
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! |
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 |
@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:
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).
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. |
I agree!
Good catch.
You are right. The main reason they prefer |
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 " |
That's a technical fix, yes, but many people use method chaining like this: foo
.bar()
.baz()
.bing() In this mode, if Anyway, I like |
Yeah you are right, though I think chain like
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:
Note 2, 3, 4 are very related. With all these premises established, I could agree the best available form for private is
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 |
@littledan I do not see how
having any problem. It just means to access the private property. |
@littledan But why do we need to prohibit that...
will always mean |
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. |
@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 |
PS. I still want to see use case in real "concrete form", aka. the code sample. For example, I never see |
@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. |
How? Could you give code sample?
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.
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. |
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!
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. |
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). |
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. |
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:
Forgive my off-topic rant (I can't hold myself 😫): Guess what? I will choose 2. And to be honest, it just make the |
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. |
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. |
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. |
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]].
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,
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?
Before enabling, we first need to avoid disabling current usage. |
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.
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. |
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.
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?
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.
Too many prerequisites for you "reasonable use case". And |
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.
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. |
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. |
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. |
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. |
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. |
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. |
@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:
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. |
We just don't vote in TC39. It's an established practice from before I joined. Voting is only for certain formal procedural matters. |
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. |
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. |
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). |
@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 |
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. |
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.
The text was updated successfully, but these errors were encountered: