diff --git a/blog/2014/09/30/README.md b/blog/2014/09/30/README.md new file mode 100644 index 000000000..4de993703 --- /dev/null +++ b/blog/2014/09/30/README.md @@ -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* \ No newline at end of file diff --git a/my_modules/htmlout/lib/htmlout.js b/my_modules/htmlout/lib/htmlout.js index 284e0b8ae..1e7b127cb 100644 --- a/my_modules/htmlout/lib/htmlout.js +++ b/my_modules/htmlout/lib/htmlout.js @@ -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"); diff --git a/my_modules/htmlout/lib/httpapi.js b/my_modules/htmlout/lib/httpapi.js index 9b23aaaa2..aba7cdeb5 100644 --- a/my_modules/htmlout/lib/httpapi.js +++ b/my_modules/htmlout/lib/httpapi.js @@ -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) { diff --git a/pubs/pc/reference/intel/80286/README.md b/pubs/pc/reference/intel/80286/README.md index e020f0228..7a08968e4 100644 --- a/pubs/pc/reference/intel/80286/README.md +++ b/pubs/pc/reference/intel/80286/README.md @@ -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 diff --git a/pubs/pc/reference/intel/80286/b2_b3_information/README.md b/pubs/pc/reference/intel/80286/b2_b3_info/README.md similarity index 100% rename from pubs/pc/reference/intel/80286/b2_b3_information/README.md rename to pubs/pc/reference/intel/80286/b2_b3_info/README.md diff --git a/pubs/pc/reference/intel/80286/exceptions_and_early_errata/README.md b/pubs/pc/reference/intel/80286/early_errata/README.md similarity index 100% rename from pubs/pc/reference/intel/80286/exceptions_and_early_errata/README.md rename to pubs/pc/reference/intel/80286/early_errata/README.md diff --git a/pubs/pc/reference/intel/80286/long_instructions/README.md b/pubs/pc/reference/intel/80286/extra_prefixes/README.md similarity index 100% rename from pubs/pc/reference/intel/80286/long_instructions/README.md rename to pubs/pc/reference/intel/80286/extra_prefixes/README.md diff --git a/pubs/pc/reference/intel/80286/executing_real_mode_programs_in_protected_mode/README.md b/pubs/pc/reference/intel/80286/real_mode/README.md similarity index 100% rename from pubs/pc/reference/intel/80286/executing_real_mode_programs_in_protected_mode/README.md rename to pubs/pc/reference/intel/80286/real_mode/README.md diff --git a/pubs/pc/reference/intel/80286/rep_restartability/README.md b/pubs/pc/reference/intel/80286/rep_restart/README.md similarity index 100% rename from pubs/pc/reference/intel/80286/rep_restartability/README.md rename to pubs/pc/reference/intel/80286/rep_restart/README.md