-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add rule for const outside of module scope. #77
Add rule for const outside of module scope. #77
Conversation
Ugh, tests are failing because the rule is not enabled. I'll add a mechanism to force a given test to use a subset of rules. |
I personally like the rule and would prefer that we align our best practices of |
105a6ca
to
41a98d9
Compare
We decided today that we do want to start enforcing the rule as well for DockYard projects moving forward. |
Just because I'm curious: what's the motivation/reasoning behind this (disallowing |
@cdl This explanation probably sums it up the best. |
Quoting @ef4 from ember-cli/ember-cli#5091 (comment):
Using
|
I am not a huge fan of this rule. If this is applied, would it then make sense to move variables that will never have their references mutated outside of function scope as e.g. test('it does stuff', function(assert) {
let expectedText = 'foo'; // never changes programatically
assert.equal(this.$().text(), expectedText, 'should be foo');
}); vs const EXPECTED_TEXT = 'foo';
test('it does stuff', function(assert) {
assert.equal(this.$().text(), EXPECTED_TEXT, 'should be foo');
}); Personally, the number of times I have gone back to change a I am very curious to know how often going back to change |
I don't think we should start moving any and all variables that won't get reassigned outside the scope where they are used. const EXPECTED_TEXT = 'foo';
test('it does stuff', function(assert) {
assert.equal(this.$().text(), EXPECTED_TEXT, 'should be foo');
}); The expected text should stay in the test, in my opinion. |
Then, should it just be: test('it does stuff', function(assert) {
assert.equal(this.$().text(), 'foo', 'should be foo');
assert.equal(this.$('input').val(), 'foo', 'should be foo');
}); Since |
I don't see an issue with |
But in that example, it is fair to assume that test('it does stuff', function(assert) {
let frameworkName = 'Ember';
let tagLine = 'A framework for creating ambitious web applications';
assert.equal(this.$().text(), `${frameworkName}, ${tagLine}`, 'should be Ember');
}); or const FRAMEWORK_NAME = 'Ember';
const TAG_LINE = 'A framework for creating ambitious web applications';
test('it does stuff', function(assert) {
assert.equal(this.$().text(), `${FRAMEWORK_NAME}, ${TAG_LINE}`, 'should be Ember');
}); |
Not necessarily. You could have this, and that should be fine: test('it does stuff', function(assert) {
let expectedText = 'foo';
assert.equal(this.$().text(), expectedText, 'should be foo');
// do more things
// ...
expectedText = 'bar';
assert.equal(this.$().text(), expectedText, 'should now be bar');
}); |
I see nothing wrong with the example in #77 (comment), and this rule as proposed would not prevent it. |
My main problem with this rule is that it educates developers about not abusing test('it does stuff', function(assert) {
const beforeText = 'foo';
const afterText = 'bar';
assert.equal(this.$().text(), beforeText, 'should be foo');
// do more things
// ...
assert.equal(this.$().text(), afterText, 'should now be bar');
}); Which is arguably better since we know the perils of unexpected side effects. My point is that it is better to have lots of |
What value does this give you:
Over:
The test should pass or fail based on the assertions, not a random compilation error because you decided to change a local variable at some later date.
It is an issue, because the cognitive overhead of choosing whether to use However, things that are truly constants tend to be declared outside of function bodies which would be allowed with this rule. |
I definitely agree that The point is to opt-in to mutation as opposed to opt-out. I think that "mental energy" cost to be extremely negligible, given that preferring In any case, ¯_(ツ)_/¯ I can live with this rule, but I still don't think the argument for it is very compelling. |
My thinking has been that |
I'm definitely interested to hear everyone's thoughts on the usage of |
41a98d9
to
6385650
Compare
Good: ``` const FOO = 'FOO'; export const BAR = 'BAR'; ``` Bad: ``` function derp() { const FOO = 'FOO'; } if (false) { const BLAH = 'BLAH'; } ``` --- I did not add configuration for this rule in the default preset (but I can if we want it)...
6385650
to
02f93c3
Compare
@brzpegasus - Thanks for summarizing, this is good to go now. |
Add rule for const outside of module scope.
I am a mega 👎 for this rule as a default. I use It's refreshing to know your variable is not changing it's binding unless you've explicitly allowed it to. |
@devinus: The rules are yours to customize:
The defaults have been thoughtfully considered, as you can see above. |
This is the result of setting it to either |
FYI, the latest npm package does not have that rule yet, but I assume you're using the master branch of |
oh, :P no I was using the npm release. Perils of watching repos |
No worries! I'll probably release by the end of the week. |
I think it makes sense to use The benefit of using |
@wycats I think there's an even better argument for the reverse that is more concrete. If you see This, along with the IDE benefits of using |
@wycats @devinus I see both sides of this coin, and I'm not convinced either side is totally right. What I am convinced of is that this particular code style rule limits use of There is unfortunately no way to my knowledge to write a rule that simply says "you are using const here, do you mean this can never be rebound or that it currently isn't?". In thinking more about this, I'm trending towards @wycats' opinion that the knowledge that something ought to be |
That's actually my opinion, @wycats is the reverse (i.e. the knowledge that something ought to be |
@devinus it actually isn't, there's a deeper level of understanding I think you missed. Comes down to this.
You opinion, as I understand it, boils down to statements (2) and (3), Wycats' boils down to (1) and (4). e.g. The difference here is in where |
@runspired I definitely didn't miss it, but like I alluded to (1) and (4) are emotions and subject to differences of the authors opinion, (2) and (3) are facts about the code expressed in the code. You can tell with a quick glance at the code that a The Erlang community loves single assignment and often touts it as a language feature that reduces stupid errors, but I often found some algorithms ugly or hard to express without the ability to rebind variables. Being able to tell by the variable declaration whether it's rebindable or not is a feature. |
This is why I'm uncertain myself what the answer is, but sticking to what I've said before, regardless of the answer to the metaphysical debate here, the rule itself in question in this PR helps neither side. |
Indeed, it doesn't represent either argument. |
By the way, I don't think this is bikeshedding. These kinds of arguments are important when you're figuring out and imposing a style on a community. Imposing a style opinion that doesn't represent the majority of it's users is how you end up with funky shit like https://github.com/feross/standard. |
The rules defined in Ensures super stylish code by enforcing the DockYard JavaScript and Ember style guide rules. We have, however, built it in such a way that it would also benefit the rest of the community, should they choose to use the addon as a starting point for style enforcement. Your opinions may align 100% with the defaults we've established, or they may align only 80%, or 90%. Either way, the preset can be customized to suit your needs by disabling those rules you would rather not see in your own projects. |
@brzpegasus That's a good point, I didn't catch that. If this is to enforce DockYard's code style then we're indeed barking up the wrong tree. |
I don't think it's entirely the wrong tree, this project may be Dockyard's but it's named |
@runspired come on, the naming convention for ember addons is |
@bcardarella come on? but that's my point exactly, there's a lot to a name. If this is being promoted as an ember-addon for the community then Dockyard has less of an expectation of this being "Dockyard's exact style guide" with that name, and needs to be open to community opinions on it. |
@runspired I honestly didn't know this was meant to reflect DockYard's style rather than a community style, but in the end it's just a name and I can blame my reading comprehension. But maybe DockYard's Ember style guide should be updated to reflect this rule @brzpegasus ? https://github.com/dockyard/styleguides/blob/master/engineering/ember.md |
@runspired so you're implying that all of your addons that are named "ember-" are the "official ember community standard" ? The naming convention for ember addons is "ember-". This is getting absurd. |
@bcardarella I'm implying that if |
@runspired ok, I can buy that argument |
I can't believe that this got merged. You are basically telling new developers to follow bad programming practices. The I really respect @rwjblue but I come from a Java background and it has the As a contrived example (I realise that the local method variable are unnecessary here but they are in real life examples).
I follow this convention in ES6 also:
This will cover all cases mentioned by @rwjblue and others.
What do people think of this as a convention in Ember? |
@jackmatt2 the problem here is that |
@bcardarella Most of the arguments in the article I disagree with but the one I believe does hold merit is the following:
Those nasty Javascript nuances bite back! |
@jackmatt2 its clear you disagree with them but unfortunately that doesn't change anything. The purpose and proper use of |
👍 |
@jackmatt2 That is easily disallowed by ESLint by the way: |
I'm locking this issue. If you would like to disable this rule, simply add the following to your {
"preset": "ember-suave",
"disallowConstOutsideModuleScope": false
} |
Good:
Bad:
I did not add configuration for this rule in the default preset (but I
can if we want it)...