Moved a few files and added a new post about JavaScript coding conventions
This commit is contained in:
parent
3b7a7b4d78
commit
9cefe2e700
9 changed files with 179 additions and 16 deletions
154
blog/2014/09/30/README.md
Normal file
154
blog/2014/09/30/README.md
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
My (JavaScript) Coding Conventions
|
||||
---
|
||||
|
||||
Some ramblings about my JavaScript coding conventions. This is not an attempt to change anyone's mind
|
||||
about anything, just an explanation of why things are they way they are (and will be more useful once PCjs
|
||||
moves from a private to a public GitHub repository).
|
||||
|
||||
### Tabs vs. Spaces
|
||||
|
||||
I've configured my IDE ([PhpStorm](http://www.jetbrains.com/phpstorm/)) to NEVER use tab characters in .js files
|
||||
(spaces only) and to ALWAYS use tab characters in almost every other type of text file. This is largely because
|
||||
when a web browser displays a JavaScript file (either in the main window or in the Developer Tools window), tabs
|
||||
usually screw up the formatting, which I find annoying when I'm debugging. XML files, on the other hand,
|
||||
are usually reformatted by the browser anyway, so in those cases, I opt for smaller files and use real tabs.
|
||||
|
||||
Note that most of the JavaScript delivered by a PCjs production server will have been compiled by Google's
|
||||
Closure Compiler, which completely eliminates all non-essential whitespace, so this is really a development
|
||||
preference, with little to no impact on production files.
|
||||
|
||||
Regardless of the choice of tab character however, I almost always use 4-column tab stops, except in legacy .asm
|
||||
files, where 8-column tab stops were the norm.
|
||||
|
||||
I've noticed that 2-column tab stops have recently become popular, especially in Node projects;
|
||||
NPM, for example, will rewrite package.json files, replacing my 4-column spacing with 2-column spacing.
|
||||
I don't fight that trend -- I just ignore it.
|
||||
|
||||
### Braces and Parentheses
|
||||
|
||||
Most of my opening braces appear at the end of the line containing the associated "if", "while", "for", "switch",
|
||||
"function" etc, preceded by a single space. And most of my opening parentheses are also preceded by a single space,
|
||||
except when following "function" or a function name, in which case there is NO space. This is just an historical
|
||||
preference, dating back to my BASIC and C programming days; it's not that those preferences matter anymore, it's just
|
||||
that I see no reason to change them.
|
||||
|
||||
Sometimes I break these conventions though. For example, for all the top-level (documented) functions in a
|
||||
module, I'll often move the opening brace of the function body to its own line, because I feel that the extra
|
||||
whitespace makes the code a bit more readable. It may sometimes depend on my mood, but I do try to be consistent
|
||||
within a given file at least.
|
||||
|
||||
### Variable Names
|
||||
|
||||
I still tend to follow Charles Simonyi's "[Hungarian](http://en.wikipedia.org/wiki/Hungarian_notation)" naming
|
||||
conventions -- or rather, a naming convention loosely inspired by Hungarian. I know lots of people sneer at
|
||||
those conventions and think they're useless, and all I can say is, they're wrong: they are not useless to ME.
|
||||
|
||||
I admit they may be useless to anyone who has a phenomenal memory and can remember that an obscure variable named
|
||||
"foo" was initialized with a string or a number, or whose IDE can answer that question with the press of a key (or two),
|
||||
but for me, with my non-phenomenal memory and lazy fingers, I prefer being able to simply look at a variable to
|
||||
immediately know what *type* of data it contains, if nothing else.
|
||||
|
||||
I rarely name a string or numeric variable something vague like "foo." At worst, I would name it "sFoo" if it
|
||||
was a string or "iFoo" if it was a number (or possibly "nFoo" or "cFoo" if it represented a total of Foos or a
|
||||
counter of Foos). And if a string or numeric variable has a very short-term use, I'll probably just name it "s"
|
||||
or "i" (or "n").
|
||||
|
||||
As I mention [below](./#quotation-marks), I still tend to distinguish single characters from strings too,
|
||||
which means I may sometimes prefix character variables with "ch" and character counters with "cch".
|
||||
|
||||
Of course, these letter prefixes like "s" and "n" are irrelevant if you already give your variables meaningful
|
||||
names like "nameOfPerson" or "numberOfPeople". And that's fine -- I do that sometimes, too. But in general,
|
||||
I still prefer variable names like "sPerson" and "nPeople".
|
||||
|
||||
I don't try to come up with special prefixes for Objects. If there's a Person object, for example, I'll probably
|
||||
use colloquial names like "personHere" or "personThere". I am stricter with Arrays though: I prefix array variables
|
||||
with "a", arrays of strings and numbers with "as" and "ai" (or "an"), arrays of arrays with "aa", etc. As for Arrays
|
||||
of anything else, I usually don't bother with anything more than an "a" prefix.
|
||||
|
||||
### Quotation Marks
|
||||
|
||||
Coming from a long C background, I prefer to use double-quotes around multi-character strings and single quotes
|
||||
around single-character strings. While the reasons for doing so are largely historical and currently irrelevant,
|
||||
characters are STILL the building blocks of strings, and even the JavaScript String class contains methods that
|
||||
deal with individual characters (eg, charCodeAt() and fromCharCode()). So for any code that deals explicitly with
|
||||
individual characters, I like to reinforce that with single quotes.
|
||||
|
||||
Also, to emphasize that object property names aren't really strings (even though strings can be used as property
|
||||
names), I tend to use single quotes when quoting property names. That does make me somewhat inconsistent with
|
||||
the JSON standard, which insists that property names be double-quoted, but JSON.stringify() takes care of that, so
|
||||
it's not really a problem. Besides, I have a lot of quibbles with the JSON standard, like its "disapproval" of
|
||||
comments and hexadecimal constants, and its failure to faithfully serialize and deserialize uninitialized Array
|
||||
objects, but I'll leave my gripes about JSON for another post.
|
||||
|
||||
Generally speaking, the only time I quote property names is when I have to. I'll use the "dot" syntax; eg:
|
||||
|
||||
obj.prop = true;
|
||||
|
||||
instead of:
|
||||
|
||||
obj['prop'] = true;
|
||||
|
||||
unless the property name doesn't conform to variable name syntax (eg, if it starts with a digit) or if it's a
|
||||
"public" property and therefore I can't risk Google's Closure Compiler "minifying" the property name to something
|
||||
else.
|
||||
|
||||
I break my own quoting rules slightly when dealing with strings that *contain* double-quotes, since it's more readable
|
||||
to put double-quotes inside single-quoted strings than to "escape" every double-quote with a backslash.
|
||||
|
||||
For code that I originally wrote in PHP and later ported to JavaScript, there was a tendency in the original
|
||||
code to always use double-quotes around strings and "escape" double-quotes regardless, and that tendency may linger
|
||||
in code I didn't feel like rewriting much, but the tendency was due more to idiosyncrasies of PHP than any convention
|
||||
of mine; for example:
|
||||
|
||||
- single-quoted PHP strings may not include any escaped characters (except for single-quote and backslash)
|
||||
- single-quoted PHP strings cannot resolve references to string variables (eg, "the value of foo is {$foo}")
|
||||
|
||||
Because of PHP's restrictions on single-quoted strings, I tended to avoid them. However, in JavaScript, those
|
||||
restrictions/features don't exist.
|
||||
|
||||
### JSDoc
|
||||
|
||||
I've taken a great deal of care to "[JSDoc](http://usejsdoc.org/)-ify" nearly all my JavaScript code, not
|
||||
because I want to be able to generate documentation (although that's something to think about), but because
|
||||
it's the only way to tell both Google's Closure Compiler and my IDE exactly what data types are passed around.
|
||||
The goals are to minimize the number of "code inspection" warnings in the IDE and produce warning-free
|
||||
compilations.
|
||||
|
||||
In order to use the Closure Compiler's ADVANCED_OPTIMIZATIONS option and get maximum performance
|
||||
(and maximum "minification", a form of "uglification"), every function and its parameters needs to
|
||||
be fully typed; otherwise, the Compiler generates way too many warnings/errors -- at least, that was the
|
||||
case when I first started using it a couple of years ago.
|
||||
|
||||
So, I've adopted a zero-tolerance policy for warnings: nothing gets checked in if the Closure Compiler
|
||||
generates even a single warning.
|
||||
|
||||
Unfortunately, I'm not sure the [JSDoc](http://usejsdoc.org/) folks and the
|
||||
[Closure Compiler](https://developers.google.com/closure/compiler/docs/js-for-compiler) are totally in sync on
|
||||
everything. And then there's [PhpStorm](http://www.jetbrains.com/phpstorm/webhelp/creating-jsdoc-comments.html),
|
||||
whose code inspections occasionally fail; sometimes a bogus code inspection warning can be fixed with some
|
||||
additional JSDoc @name or @class annotations, but not always.
|
||||
|
||||
In any case, the subset of variable and function type declarations I use works pretty well across the board;
|
||||
I ignore code inspection warnings in the IDE, as long as they are clearly erroneous (or clearly innocuous).
|
||||
|
||||
And finally, speaking of warnings, I've had to tell PhpStorm to "shut up" about a few:
|
||||
|
||||
- Unfiltered for…in loop
|
||||
- Bitwise operator usage
|
||||
- Comma expressions
|
||||
- “throw” of exception caught locally
|
||||
|
||||
I acknowledge those those features can introduce bugs if you're not careful, so I make sure I'm careful. I don't
|
||||
subscribe to the dogmatic approach that others (eg, the author of JSHint) take about so-called "risky" features.
|
||||
I agree that it's always a good idea to walk to the crosswalk before crossing a street, but I don't agree that it's
|
||||
*never* a good idea to cross in the middle sometimes, too.
|
||||
|
||||
I've also made the following "weak warnings" instead of "warnings":
|
||||
|
||||
- Unused JavaScript / ActionScript local symbol
|
||||
|
||||
because it's a useful warning, but I don't like being penalized for functions that have been "prototyped" a specific
|
||||
way but can't always be implemented exactly as prototyped.
|
||||
|
||||
*[@jeffpar](http://twitter.com/jeffpar)*
|
||||
*September 30, 2014*
|
||||
|
|
@ -38,8 +38,6 @@ var glob = require("glob");
|
|||
* @class exports
|
||||
* @property {function(string)} sync
|
||||
*/
|
||||
var mkdirp = require("mkdirp");
|
||||
|
||||
var HTTPAPI = require("./httpapi");
|
||||
var DumpAPI = require("../../shared/lib/dumpapi");
|
||||
var MarkOut = require("../../markout");
|
||||
|
|
|
|||
|
|
@ -962,6 +962,17 @@ HTTPAPI.verifyUserID = function(sUser, res, done)
|
|||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* getUserDir(sUser)
|
||||
*
|
||||
* @param {string} sUser
|
||||
* @return {string}
|
||||
*/
|
||||
HTTPAPI.getUserDir = function(sUser)
|
||||
{
|
||||
return path.join(sServerRoot, "/logs/users/" + /* sUser.substr(0, 2) + "/" + */ sUser);
|
||||
};
|
||||
|
||||
/**
|
||||
* createUserDir(sUser)
|
||||
*
|
||||
|
|
@ -972,7 +983,7 @@ HTTPAPI.verifyUserID = function(sUser, res, done)
|
|||
*/
|
||||
HTTPAPI.createUserDir = function(sUser)
|
||||
{
|
||||
var sDir = path.join(sServerRoot, "/logs/users/" + sUser.substr(0, 2) + "/" + sUser);
|
||||
var sDir = HTTPAPI.getUserDir(sUser);
|
||||
return (fs.existsSync(sDir) || !!mkdirp.sync(sDir));
|
||||
};
|
||||
|
||||
|
|
@ -987,7 +998,7 @@ HTTPAPI.verifyUserDir = function(sUser, done)
|
|||
HTMLOut.logDebug('HTTPAPI.verifyUserDir("' + sUser + '")');
|
||||
|
||||
if (sUser) {
|
||||
var sDir = path.join(sServerRoot, "/logs/users/" + sUser.substr(0, 2) + "/" + sUser);
|
||||
var sDir = HTTPAPI.getUserDir(sUser);
|
||||
fs.exists(sDir, function(fExists) {
|
||||
if (!fExists) {
|
||||
HTTPAPI.verifyUserID(sUser, null, function(iVerified, result, res) {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ Intel 80286 CPU Documentation
|
|||
### 80286 Errata
|
||||
|
||||
* [ARPL Behavior](arpl/)
|
||||
* [Coprocessor Operand Beyond Segment Limit](b2_b3_information/#coprocessor-operand-partially-beyond-limit-of-erc-segment)
|
||||
* [Instructions Longer than 10 Bytes](long_instructions/)
|
||||
* [Loading Null Selector Values Into DS or ES Registers](b2_b3_information/#loading-null-selector-values-into-ds-or-es-registers)
|
||||
* [Non-Restartable Protection Violations](b2_b3_information/#non-restartable-protection-violations)
|
||||
* [POPF Behavior](b2_b3_information/#popf-behavior)
|
||||
* [REP MOVS and REP INS Restartability](rep_restartability/)
|
||||
* [Early 80286 Errata of Interest](exceptions_and_early_errata/#early-80286-errata-of-interest)
|
||||
* [Coprocessor Operand Beyond Segment Limit](b2_b3_info/#coprocessor-operand-partially-beyond-limit-of-erc-segment)
|
||||
* [Instructions Longer than 10 Bytes](extra_prefixes/)
|
||||
* [Loading Null Selector Values Into DS or ES Registers](b2_b3_info/#loading-null-selector-values-into-ds-or-es-registers)
|
||||
* [Non-Restartable Protection Violations](b2_b3_info/#non-restartable-protection-violations)
|
||||
* [POPF Behavior](b2_b3_info/#popf-behavior)
|
||||
* [REP MOVS and REP INS Restartability](rep_restart/)
|
||||
* [Early 80286 Errata of Interest](early_errata/#early-80286-errata-of-interest)
|
||||
|
||||
### 80286 Undocumented Opcodes
|
||||
|
||||
|
|
@ -18,11 +18,11 @@ Intel 80286 CPU Documentation
|
|||
|
||||
### 80286 Real-Mode Emulation Notes
|
||||
|
||||
* [Executing Real Mode Programs in Protected Mode](executing_real_mode_programs_in_protected_mode/)
|
||||
* [Discrepancies from an iAPX 86/88 Using Emulation](executing_real_mode_programs_in_protected_mode/#discrepancies-from-an-iapx-86-88-using-emulation)
|
||||
* [Extending the Address Space of Current iAPX 86 Software](executing_real_mode_programs_in_protected_mode/#extending-the-address-space-of-current-iapx-86-software)
|
||||
* [Mixing Real Mode and Protected Mode](executing_real_mode_programs_in_protected_mode/#mixing-real-mode-and-protected-mode)
|
||||
* [Exceptions from Undefined Opcodes and String Instructions](exceptions_and_early_errata/)
|
||||
* [Executing Real Mode Programs in Protected Mode](real_mode/)
|
||||
* [Discrepancies from an iAPX 86/88 Using Emulation](real_mode/#discrepancies-from-an-iapx-86-88-using-emulation)
|
||||
* [Extending the Address Space of Current iAPX 86 Software](real_mode/#extending-the-address-space-of-current-iapx-86-software)
|
||||
* [Mixing Real Mode and Protected Mode](real_mode/#mixing-real-mode-and-protected-mode)
|
||||
* [Exceptions from Undefined Opcodes and String Instructions](early_errata/)
|
||||
|
||||
### Assorted Publications
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue