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

Remove the private fields idea ("#"), at least for now #73

Closed
TheNavigateur opened this issue Jan 18, 2018 · 16 comments
Closed

Remove the private fields idea ("#"), at least for now #73

TheNavigateur opened this issue Jan 18, 2018 · 16 comments

Comments

@TheNavigateur
Copy link

TheNavigateur commented Jan 18, 2018

I often publicise private variables and privatise public variables (when developing in other languages). The "#" scheme increases the effort to do so and increases the chances of bugs being introduced in doing so (by failing to remove/add the "#" in one or more cases).

If this.x and this.#x are both allowed, then obviously changing the access status of one would cause a clash. I don't accept therefore that allowing this would be desirable let alone necessary.

An alternative is to allow access control at development time only, where all the value of access control really exists anyway, via e.g. a decorator like @Private. This solves all requirements. But I don't see the value of having private fields implementation at run time anyway. Who does it help, and in what cases? As a developer utilizing private fields I don't need any run time error that says "that field is private". I need a development time "error"/filter that simplifies the interface of a class to public properties and methods only.

@ljharb
Copy link
Member

ljharb commented Jan 18, 2018

There’s many kinds of decorators, so the “i typed the wrong thing” hazard would apply to that too. There’s never a substitute for manual or automated testing (and linting), so if you mis-type a #, you’d discover it when running your code, just like many other bugs.

@TheNavigateur
Copy link
Author

"you’d discover it when running your code" is not a good rationale for allowing a surface area for a bug. With the decorator idea, all you need to do is remove the decorator to publicize a private variable. With "#", you need to change every occurrence, which could be dozens or even more. So the hazard is much wider.

Access control doesn't have value at run time. It's a way to simplify and filter auto complete while accessing an instance's fields and methods from outside the class.

@ljharb
Copy link
Member

ljharb commented Jan 18, 2018

We’re not optimizing for converting from private to public - imo that’s a very rare operation. It’ll be far more common to convert from public to private.

Access control has tons of value at runtime - it’s got literally nothing to do with autocomplete and 100% to do with preventing any observation of private state.

@TheNavigateur
Copy link
Author

TheNavigateur commented Jan 18, 2018

I've never used "private" for anything other than cleaning up my class's public interface for external consumption, so in my experience, everything to do with autocomplete. What is the value in "preventing any observation of private state"? Can you give an example? (please don't point me to articles, I want an example that clarifies your assertion)

@ljharb
Copy link
Member

ljharb commented Jan 18, 2018

https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md#what-do-you-mean-by-encapsulation--hard-private explains the requirement rather well.

What someone is used to doing in most other languages is irrelevant, because most other languages have a broken concept of “private” in that you can always reflect and observe that private state. In JS, private will truly mean “private”.

@bakkot
Copy link
Contributor

bakkot commented Jan 18, 2018

I want an example that clarifies your assertion

Here's a specific example.

I also want to say that private state is also typically a mechanism for avoiding name collisions, which a decorator wouldn't help with.

@TheNavigateur
Copy link
Author

Has this ever been proven? Those who want to expose internal code will just edit the source code. It is conjecture therefore to presume about what this would solve, since there isn't a language case that does the same, as far as I know. The downside also hasn't been examined: people drill into undocumented code for a reason: it allows functionality that is not otherwise possible/offered. So the rationale for this entire feature therefore seems incredibly one-sided, besides conjecture about whether it'll achieve its "goal", leaving aside who prefers it or not.

@ljharb
Copy link
Member

ljharb commented Jan 18, 2018

If you don’t want it, you don’t need to use it. You can already use symbols or naming conventions to make something quasi-private, if you truly don’t care if people mess with it. For those who do care, it’s currently impossible in a practical sense, and this proposal makes it ergonomic.

@bakkot
Copy link
Contributor

bakkot commented Jan 18, 2018

The more general reflection vs encapsulation debate has been had at great length already, both on Github and in committee, and I don't think we want to revisit it yet again. We have examined the tradeoffs involved, including the freedom to tinker and to add functionality not otherwise possible.

(Incidentally, other languages do have similar facilities - for example, Java 9 introduced modules in large part because the language's existing "private" wasn't good enough, and they needed strong encapsulation in exactly the sense offered by this proposal. And closures have offered very much the same sort of privacy in JavaScript for a long, long time; they were just less practical to use with classes.)

@TheNavigateur
Copy link
Author

TheNavigateur commented Jan 19, 2018

I'm guessing there's no way of having "hard private" and allowing a one-step refactoring to convert from public to private and vice versa.

@ljharb I think you probably meant to say that converting from private to public (at least read-only) is more common, because e.g. a library that converts a public property to private would be a breaking change.

@bakkot
Copy link
Contributor

bakkot commented Jan 19, 2018

I'd expect tooling to be more than up to the task of refactoring between public and private in a single step. There's no way to do it by changing just the definition site, though, no.

@TheNavigateur
Copy link
Author

If that really is the case, then I'd have to say I'm satisfied with the proposal as-is, despite the downsides:

  1. Changing access control in a single step requires adequate tooling
  2. "Hard private" could be over-used to restrict access to sometimes desired information & functionality

The upside (accepted)

"Hard private" has its value in libraries where consumer code is unseen, and allows "internals" to be changed freely without fear of breaking anyone's code.

Given the balance of these pros and cons, I am closing this issue, until I become aware of any way to avoid downside number 1 while preserving "hard private".

@babakness
Copy link

This is so ugly. Can there be something other than the '#' character? Why not just a keyword

class {
  whatever x = 5
}

Where "whatever" is a clean word that anyone reading would understand and is also not painful to the eyes of time.

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

@babakness "ugly" is subjective; if you'd read the FAQ you'll see why no keyword is feasible.

@babakness
Copy link

babakness commented Jan 27, 2018

OK but its such an edge case to make something really private than to just hide it from auto-complete that giving up "#" is throwing away a symbol with lots of potential in the future.

Why not, '###' if it has to be '#'

@ljharb
Copy link
Member

ljharb commented Jan 27, 2018

It’s not an edge case. It’s one of the primary goals of the feature.

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

4 participants