sindresorhus / eslint-plugin-unicorn

More than 100 powerful ESLint rules
MIT License
4.24k stars 367 forks source link

Rule proposal: Prevent abbreviations #169

Closed sindresorhus closed 5 years ago

sindresorhus commented 6 years ago

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:

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!

maximandrews commented 6 years ago

As other people already suggested I believe it should be configurable. It is a great idea in general, but there are some tradeoffs.

1) If you are creating this eslint plugin for your own projects then you can set whatever you want; 2) If you are looking to make it a popular feature, then I would go with configurable multiple options. Like { "error": ["e", "err", "error"] }. Also, you should be able to pass it as a string like { "error": "err" }.

Every software engineering manager or architect will have their own preference for their project based on their experience and other unknown factors like weather on the day of a project creation.

normanzb commented 5 years ago

I know we have conventions and all that,

but that's just a convention.

"Because archaic conventions" is not a great argument

The language you are speaking right now, is in fact a convention as well. If there are more people calling "newbies" "noobs" than I think "noobs" is defacto standard of modern language, and so does err is the modern coding defacto standard version of error

sholladay commented 5 years ago

For anyone who doesn't remember, err became popular in JavaScript because at the time, the community had an aversion to names that were simply a camelCase copy of a class. Back then, there were no true classes, no linter rules that could catch mistakes related to capitalization, and this convention made people feel more confident that a variable was definitely an error instance rather than a reference to Error, perhaps being a typo. These days, those concerns are basically moot. New language features and linter rules have made those problems way less common. We don't pass around classes nearly as often as we used to when there was more ceremony involved in setting up a prototype chain. I think it's about time everyone started using error instead of err.

haysclark commented 5 years ago

This entire argument is very common and you can find many articles from other languages like C++, Java, Actionscript, etc. Abbreviations and other common-conventions are rarely timeless because they obfuscate the intended meaning and eventually fall out of the common lexicon. While outside the scope of Computer Science, I believe Shorthand in an interesting example of a once ubiquitous and justifiable means to write an abbreviating version of English. Yet, due to advancements in technology, the one ubiquitous skill became obsolete, and as a result, anything authored in Shorthand today would be considered cryptic if not indecipherable by most. To me, it's an example of a collection of abbreviations which did not survive the test of time because the purpose of abbreviating the language was made moot by advancements in technology. In 2019 with lightning fast compilers, excellent IDE's with object-type, code, and templet hinting, there are few good reasons for justifying the using cryptic abbreviations in one's code.

IssueHuntBot commented 5 years ago

@issuehuntfest has funded $160.00 to this issue. See it on IssueHunt

futpib commented 5 years ago

max => maximum min => minimum

How far should we go with this :thinking:

loilo commented 5 years ago

I'd say min and max are fine as they are common abbreviations in natural language.

CrossEye commented 5 years ago

@futpib:

How far should we go with this

Clearly all the way. If it's a good thing, then it's a good thing, so let's make sure to include

json2html => javaScriptObjectNotationToHyperTextMarkupLanguage

felixfbecker commented 5 years ago

I mean, how would the rule be implemented? I assume it would use some kind of dictionary/wordlist to check that all terms are actual words, and error on any term not found in the dictionary? So if the abbreviation is common enough that it would appear in the dictionary, like HTML, then that would be allowed, but msg, obj, val, etc certainly all would not be.

sonicdoe commented 5 years ago

As a rough guideline, I also feel like acronyms are usually okay whereas abbreviations are not.

For example, acronyms such as HTML, API, or URL are arguably more well-known and therefore result in more readable code. If I would be talking about a uniform resource locator, you’d probably have to do a double-take to actually understand what I’m referring to.

On the other hand, abbreviations such as env or msg are arguably not as easily understood as their counterparts “environment” and “message”. You would also never use such abbreviations in spoken language.

CrossEye commented 5 years ago

@sonicdoe: Note that all of those are considered abbreviations.

Two common types of abbreviations are acronyms and initialisms. HTML, API and URL are all initialisms, and not acronyms. (You pronounce them as individual letters.) . Things like NATO or SCUBA are acronyms. (You pronounce them as words.) . Other abbreviations such as env and msg are neither of these, and you don't pronounce them directly, although I personally always pronounce "msg" as "message".

My problem is that it's really hard to find a consensus on the allowable alternative. You probably don't want to write

const point = new PointOnTheCartesianPlane(horizontalAxisValue, verticalAxisValue)

when you could simply write

const point = new Point(x, y)

But what privileges x and y here?

sonicdoe commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

@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 commented 5 years ago

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

loilo commented 5 years ago

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 commented 5 years ago

Just to be clear, the point is not to enforce this for all acronyms/abbreviations. The rule should only enforce this list: https://github.com/sindresorhus/eslint-plugin-unicorn/issues/169#issue-310403396 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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

The only other options I have in mind are

sindresorhus commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

stroncium commented 5 years ago

@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.

IssueHuntBot commented 5 years ago

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

sindresorhus commented 5 years ago

This rule is now available: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/master/docs/rules/prevent-abbreviations.md

gajus commented 5 years ago

@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 commented 5 years ago
constructor (...arguments_) {
  super(...arguments_);

  this.protocol = 'http:';
  this.defaultPort = 80;
}
EvgenyOrekhov commented 5 years ago

@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 commented 5 years ago

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 commented 5 years ago

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

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