Skip to content
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

Rule proposal: Prevent abbreviations #169

Closed
sindresorhus opened this issue Apr 2, 2018 · 84 comments
Closed

Rule proposal: Prevent abbreviations #169

sindresorhus opened this issue Apr 2, 2018 · 84 comments
Labels
enhancement 🎁 Rewarded on Issuehunt This issue has been rewarded on Issuehunt help wanted

Comments

@sindresorhus
Copy link
Owner

sindresorhus commented Apr 2, 2018

Issuehunt badges

Using complete words result in more readable code. Not everyone knows all your abbreviations. You only write code once, but it's read many times.

For a start, we could go with these:

  • err => error
  • cb => callback
  • opts => options
  • str => string
  • obj => object
  • num => number
  • val => value
  • e => event/error
  • evt => event
  • el => element
  • req => request
  • res => response/result
  • btn => button
  • msg => message
  • len => length
  • env => environment
  • dev => development
  • prod => production
  • tmp => temporary
  • arg => argument
  • args => arguments
  • tbl => table
  • db => database
  • ctx => context
  • mod => module

Also i => index, but I have a feeling, that it's going to be too controversial.

Suggestions welcome for additional ones. Also looking for people's thoughts on this rule.

futpib earned $160.00 by resolving this issue!

@lukechilds
Copy link

Honestly, I think they're all quite controversial.

I agree with you that that in general abbreviations are not good variable names, but I personally prefer the shorter version of most of these and I think they're pretty widely understood. I'd say err is probably even more common than error. It's in all the official Node.js docs.

Also, how reliable will this be? What if cb is an abbreviation for circuit breaker. Obviously that's a bad variable name but it shouldn't be automatically changed to callback.

@sindresorhus
Copy link
Owner Author

But is it really worth sacrificing readability over saving a few characters? Swift has taught me a lot about writing readable code. Some would say it's too verbose, but I also think JS is generally too concise.

I know we have conventions and all that, but should we maybe stop and question those? I feel like everyone just does it because everyone else does it, without actually considering whether it's worth the downsides.

I'd say err is probably even more common than error. It's in all the official Node.js docs.

Neither the Node.js API nor docs are known for their approachability or user-friendliness, though.

Also, how reliable will this be? What if cb is an abbreviation for circuit breaker. Obviously that's a bad variable name but it shouldn't be automatically changed to callback.

I didn't intend for it to have auto-fixing, but if it did, it could only fix the non-ambiguous cases.

@jamesmosier
Copy link

jamesmosier commented Apr 3, 2018

arr => array

I've also seen elem => element but I see you have el above (which is more popular).

@FezVrasta
Copy link

event is also seen as evt quite often

@frontend-3
Copy link

btn -> button
msg -> message

@TGC79
Copy link

TGC79 commented Apr 3, 2018

len -> length

@savetheclocktower
Copy link

Abbreviations like obj and str, though arguably slightly less readable than object and string, are at least unambiguous. If this rule were to exist, it seems like it would be more useful if it targeted ambiguous abbreviations. For example: I've seen e used for both event and error, and it's made me more likely to write out event and error as a result just for clarity.

Hence, I have no problem with cb, evt, or req — I don't think I've ever come across one of those and not known what it was meant to stand for. I think val is a poor thing to name a variable, but value is just as bad — the problem there is the vagueness in the name, not the abbreviation.

@sindresorhus
Copy link
Owner Author

sindresorhus commented Apr 3, 2018

Abbreviations like obj and str, though arguably slightly less readable than object and string, are at least unambiguous.

Are they though? Only if you know that str always means string, which it usually does, but that's just a convention. It could just as easily be short for strength.

I think val is a poor thing to name a variable, but value is just as bad — the problem there is the vagueness in the name, not the abbreviation.

I agree, value is not a good name, but what would you call a variable that could be any value? You could call it any, but I don't think that's clearer.

@sindresorhus
Copy link
Owner Author

If you, for example, disagree with err=>error, I'm curious about why? It's only two extra characters and it improves readability. "Because archaic conventions" is not a great argument.

@savetheclocktower
Copy link

Are they though? Only if you know that str always means string, which it usually does, but that's just a convention. It could just as easily be short for strength.

It could, if you're building an RPG. In the general case I think that those abbreviations are common enough that (e.g.) str presumptively means string, and if you need strength then you should just type strength.

I agree, value is not a good name, but what would you call a variable that could be any value? You could call it any, but I don't think that's clearer.

This is the one caveat I should've added to my original comment, but I was growing tired of typing. :)

@mantoni
Copy link

mantoni commented Apr 3, 2018

I personally also base naming decisions on scope size. While having a catch(e) with a single line might be easy to read, a long function with short names becomes unreadable very quickly.

So as a rule of thumb, I’d say the larger the scope the more descriptive the variable names should be.

@mischah
Copy link

mischah commented Apr 3, 2018

The following ones came to my mind spontaneously:

  • env => environment
  • dev => development
  • prod => production
  • t => test

@abdullahtariq1171
Copy link

tmp => temporary
ans => answer

@therealklanni
Copy link

therealklanni commented Apr 3, 2018

Are we also considering shorthands like a/b/x => any, fn => function?

const curry = fn => a => b => fn(a, b)

I see this a lot more in more academic uses, though it does happen in the real world as well.

@praveenv4k
Copy link

arg => argument
args => arguments
rec => record
tbl => table
db => database

@therealklanni
Copy link

args => arguments is almost necessary, since arguments is reserved.

@felixfbecker
Copy link

I agree with avoiding abbreviations in general, but I think the problem with this rule is that it will forbid all the abbreviations that are okay because they are widely understood (e.g. err) while allowing all the abbreviations that are not common/context-dependent. It's hard to come up with concrete examples for this, but if I read most Go codebases they have 1-3 letter variable names everywhere, that are not only non-descriptive, they also make reading the code influent.

So I think a rule like this instead of blacklisting abbreviations, should for example check variable names against an English dictionary and/or enforce a minimum character length.

@sindresorhus
Copy link
Owner Author

Are we also considering shorthands like a/b/x -> any, fn -> function?

I think x and a & b are usually fine in inline arrow functions if it's clear from the context what they refer to.

@sindresorhus
Copy link
Owner Author

args => arguments is almost necessary, since arguments is reserved.

Not in arrow functions, which I personally use most of the time.

@sindresorhus
Copy link
Owner Author

I agree the main focus should be to reduce ambiguity, the other cases could potentially be opt-in.

@therealklanni
Copy link

Not in arrow functions, which I personally use most of the time.

That's fair, but then you have to ask yourself if you want consistency, too.

@sindresorhus
Copy link
Owner Author

@therealklanni If I had to choose, I would pick readability over consistency.

@savetheclocktower
Copy link

I think this has the potential to be the worst of all possible bikesheds, and you'll hear from three groups of people:

  1. people who would like this rule and would use it to help them stick to new conventions;
  2. people who already don't abbreviate these things and want to make their collaborators abide by the same rules; and
  3. people who have opinions about abbreviations in code, generally speaking, but wouldn't use this rule.

If the goal is to ship this rule with a recommended set of abbreviations to avoid, my guess is that you won't find a consensus for more than a tiny handful of identifiers.

@sindresorhus
Copy link
Owner Author

@savetheclocktower This is just exploratory right now. I'm happy to hear all opinions. The main focus is the ambiguity aspect, which I don't think many would object to. I've personally been using the non-abbreviations in my code for a while now. I'm liking it so far, but it takes some getting used to.

@hugmanrique
Copy link

ctx => context
mod => module

@kalisjoshua
Copy link

I use these pretty often:

_ => when I don't actually care about it - usually in an arguments list - but need it to take up the position
indx => index because index is a reserved word in JS
attrs => attributes because I'm super laz

@therealklanni
Copy link

index is not a reserved word.

@loilo
Copy link

loilo commented Apr 3, 2018

If you, for example, disagree with err=>error, I'm curious about why?

I'm not sure why I feel uncomfortable with those expanded terms replacing all those rather well-known abbrevations, but I think I've come up with a possible explanation.

  1. I, personally, as a user of these abbrevations, find them clearer than the long names. That's however only learned behaviour and could certainly be retrained.

  2. What I'm not sure about: I think it makes me uncomfortable because it bloats the code, just in pure character count.

    I feel like my chances of getting the hang of a snippet by taking a quick glimpse are greater for

    let spread = (arr, cb) => cb(...arr)

    than they are for

    let spread = (array, callback) => callback(...array)

    I'd mainly attribute that to the shorter line length, I can register more code at once in the same field of view — but I can't say that for sure. It could as well just be because of 1.

@therealklanni
Copy link

  1. What I'm not sure about: I think it makes me uncomfortable because it bloats the code, just in pure character count.

That's what minifiers are for (and character count is largely irrelevant for server-side)

@andrepolischuk
Copy link

I see the following sometimes:

ns -> namespace
prop -> property
ref -> reference
dt -> date
cmd -> command

@sonicdoe
Copy link

I don’t want to derail too much so I’m just going to link to the Nomenclature section of the Acronym article from Wikipedia. In short, one may draw a line between initialisms and acronyms but it’s not a clear-cut thing. In any case, I think the meaning behind my argument was clear.

@loilo
Copy link

loilo commented Jan 28, 2019

But what privileges x and y here?

I'd say what privileges x and y is general knowledge, they're not at all tied to the software development world. However I agree that this can be hard to categorize, it would probably be easy to find examples where it's not that easily decided.

There's probably no hard and fast rule — I'd say, if you have two choices, you'll go with the one that appears more comprehensible for a decently tech-savvy non-programmer. However this seems incredibly hard to decide for an algorithm/linter...

@CrossEye
Copy link

CrossEye commented Jan 28, 2019

@sonicdoe: sorry, I try not to let pedantry slip in; I failed there. Still, my main point is simply "How do we draw the lines?" If we're working on a calendaring application, event can be awfully confusing when it applies to both the business logic (calendar events) and UI primitives (HTML event.) . I would choose to use evt -- possibly even e -- for the UI event here, reserving event for the business object. And there are many such cases, which makes it seem extremely difficult to maintain a reasonable list.

@loilo: that difficulty for an algorithm is what concerns me here.

@loilo
Copy link

loilo commented Jan 28, 2019

Understandable. However, a non-exhaustive whitelist blacklist of the most common words could at least help the cause.

@loilo
Copy link

loilo commented Jan 28, 2019

I think we can all agree that this problem is not fully machine-solvable with current technology, so a curated blacklist is probably the only viable approach.

That said, we should discuss way less about whether individual terms should be blacklisted, but rather try to agree on a deciding question to "ask" for those terms — roughly like this, but probably still more precise:

Assuming usage in a reasonable context, is the abbreviation more comprehensible and clear for a tech-savvy non-programmer than any alternative long word?

This still omits aspects like proportionality (we probably should not use a comprehensible 100 character word for an identifier even if it's more comprehensible than a 5 character term) etc., but I guess we just cannot leave out common sense from this whole topic.

That said, if the declared question is not clearly and easily answered, then we got to the point where we'd have to draw a line.

So, I think your concerns are valid @CrossEye, but if we can find a reasonable, standardized approach to blacklisting terms, those concerncs should very much be the exception rather than the rule.

@sindresorhus
Copy link
Owner Author

sindresorhus commented Jan 30, 2019

Just to be clear, the point is not to enforce this for all acronyms/abbreviations. The rule should only enforce this list: #169 (comment) Additional entries can be discussion in new issues later on.

Everything in that list will be enabled by default and people can disable individual words if they want, like:

{
	words: {
		err: false
	}
}

It should also be possible to set your own words and replacements.

It should be possible to choose, both for the built-in and custom words, on individual words, whether the word should be auto-fixable or not.

If there are multiple replacements, auto-fix will not run, and the error message will include all the possible words, for example, e could be event or error.

If the user tries to enable auto-fix for a word with multiple replacements, it should be an error.


The list of words should be added directly to this plugin and not be in a separate module for now, so we can iterate faster.

@futpib
Copy link
Contributor

futpib commented Jan 30, 2019

I'd like to implement this rule (even though I'll probably end up disabling it).

What should the rule do if the preferred identifier is already taken?

@sindresorhus
Copy link
Owner Author

What should the rule do if the preferred identifier is already taken?

Report the error but don't auto-fix. Unless, you can think of something smarter?

@sindresorhus
Copy link
Owner Author

I would also like to see an additional option that let's users disable all the built-in words by default (builtInWordsEnabledByDefault: true or something shorter). This can be useful for companies/projects that want to supply their own totally custom list of words.

@futpib
Copy link
Contributor

futpib commented Jan 31, 2019

Report the error but don't auto-fix. Unless, you can think of something smarter?

The only other options I have in mind are

  • Do not even report it
  • Do what catch-error-name does (error1, error2, etc.)

@sindresorhus
Copy link
Owner Author

Do what catch-error-name does (error1, error2, etc.)

This would actually be nice. The less I have to fix manually the better.

I doubt it will come up that much anyway. Why would anyone use both an acronym and its long-form in the same scope for different variables? Could happen, but I can't imagine it's that common.

@futpib
Copy link
Contributor

futpib commented Feb 1, 2019

While coming up with tests, some expected awkward interactions between built-in arguments special and our args => arguments renaming surfaced.

Currently my plan is to make the rule prevent the collision with the special arguments by renaming to arguments2 (just like when colliding with common variables).

@sindresorhus please take a look at the WIP tests, maybe we should instead allow the args abbreviation, at least when colliding with arguments special (or when in a class method, or allow args altogether). Fixing every super(...args) into super(...arguments2) seems unreasonable.

image

@sindresorhus
Copy link
Owner Author

maybe we should instead allow the args abbreviation, at least when colliding with arguments special (or when in a class method, or allow args altogether). Fixing every super(...args) into super(...arguments2) seems unreasonable.

Yeah, I don't see a good way around this. Let's allow args when it collides with arguments.

@stroncium
Copy link
Contributor

I took a freedom to rethink the concept a bit to make the rule more general and usable by more people. It should also help testing various rules before finalizing default rule sets.

Initial rules implemented in default rule set, community suggestions implemented in extended rule set, but it is also fully configurable for highly specific and differently opinionated use cases.

I also used the name prefer-better-name as it seems to suit the rule better.
However, if needed the rule can be reverted to original specification in #169 by changing a couple of names.

@sindresorhus
Copy link
Owner Author

@stroncium There's already an open PR for this => #237

@stroncium
Copy link
Contributor

@sindresorhus Well, it wasn't put in submitted, and by the time I realized there was a PR, I've had it done already. Anyhow, perhaps you will find my version more useful. If not than so shall it be.

sindresorhus added a commit that referenced this issue Mar 13, 2019
Fixes #169


Co-authored-by: Sindre Sorhus <[email protected]>
@IssueHuntBot
Copy link

@sindresorhus has rewarded $144.00 to @futpib. See it on IssueHunt

  • 💰 Total deposit: $160.00
  • 🎉 Repository reward(0%): $0.00
  • 🔧 Service fee(10%): $16.00

@sindresorhus
Copy link
Owner Author

@gajus
Copy link

gajus commented Apr 26, 2019

@sindresorhus

Not in arrow functions, which I personally use most of the time.

It is a problem with ES6 classes, though.

constructor (...args) {
  super(...args);

  this.protocol = 'http:';
  this.defaultPort = 80;
}

is raising a "unicorn/prevent-abbreviations" warning.

@sindresorhus
Copy link
Owner Author

constructor (...arguments_) {
  super(...arguments_);

  this.protocol = 'http:';
  this.defaultPort = 80;
}

@issuehunt-oss issuehunt-oss bot added the 🎁 Rewarded on Issuehunt This issue has been rewarded on Issuehunt label May 10, 2019
@EvgenyOrekhov
Copy link
Contributor

@sindresorhus It is much more common to use args, not arguments_ or any other name, in place of arguments. Here is a couple of examples from popular sites:

@gajus
Copy link

gajus commented Sep 2, 2019

I think @sindresorhus suggestion is valid given what this rule is enforcing.

I have just added an exception using whitelist for props and args.

@gajus
Copy link

gajus commented Sep 2, 2019

Sorry, you should configure replacements, not whitelist, i.e.

"unicorn/prevent-abbreviations": [
  2,
  {
    "replacements": {
      "args": false,
      "props": false
    },
  }
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement 🎁 Rewarded on Issuehunt This issue has been rewarded on Issuehunt help wanted
Projects
None yet
Development

No branches or pull requests