Wednesday, February 27, 2008
Saturday, February 9, 2008
Strategies for Success (and other myths)
The writings and thoughts of Karl Marx and Friedrich Engels and orthodox Communism in general date themselves squarely between the Industrial Revolution and Darwin's historic Origins. The revolutionary implementation of Communism was doomed to failure, of course, because by the time it gained critical mass it was already obsolete; groups of humans can't be organized as machines are organized. Top-down mandates of economic equality don't work, because the system will always be more complex than even the most tyrannical police state can enforce. People under duress may provide acceptable manual labor but don't contribute new ideas or new efficiencies to the process when their main concern is not personal investment in work but in following orders; thus micromanaged economies will always underperform freemarket systems.
The lesson of Communism that especially American right-wing capitalists don't want to learn is that micromanagement and monopoly are anathema to the principles of the free market. Applying the principles of Darwinian natural selection to the economic domain, we see that a healthy economic ecosystem is one in which no single player is too dominant (see: super predators), but rather neck-and-neck competition keeps everyone on their toes while allowing smaller players to emerge as competitive with more established ones. Conversely, an economy of monoculture tends toward stagnation. Companies that grow too large become entrenched in a single business model and risk the ire of large partners when proposing innovations in production methods (see: Microsoft and IE).
Government clearly has a role to play in keeping the market competitive by regulating and sometimes smashing large corporations into smaller pieces. But more importantly, ownership of past success is not a guarantor for future success. Top-down institutionalization of past success models is a sure sign that the business is failing to see the next step in its evolution. In this regard, corporate (read: Stalinist) ownership of information and ideas will always fail in the face of bottom-up Darwinian trial-and-error. This is especially true in industries touched by technology, and we're already seeing established media companies, record companies, and television networks collapse under their own weight.
Enter the Internet. To the extent that it remains free, equal, and open, it provides the most fertile soil yet for innovation and progress (of ideas, of creativity, of economic advancement, of democracy). The chaotic hordes of the MySpace/YouTube generation will surely hasten the extinction of the giant record companies and the television networks, as the wisdom of crowds will do a better job determining what the crowds like than any closed, proprietary group of mavens in a boardroom or a laboratory ever will.
The lesson for internet companies trying to attract millions? Release early and often. Keep your coupling loose. Submit to what your users are telling you - investing 10 months in a project you're sure will be a hit is a huge risk; you'd better be basing your decisions on reams of user feedback and research, because your perfect vision for the product will always fail you unless you're playing with rules that have been subjected to the Darwinian rigor of millions of little trial-and-error tests.
Saturday, February 2, 2008
Easy Date Formatter
/** * takes a string in form 'd/m/Y' * * d => day (2 digits, leading 0) * D => day (2 digits, no leading) * l => day (of week, text, 3 chars) * L => day (of week, text, full length) * * m => month (2 digits, leading 0) * M => month (2 digits, no leading 0) * f => month (text, 3 chars) * F => month (text, full length) * * y => year (2 digits) * Y => year (4 digits) * * g => hour (12hr, leading 0) * G => hour (12hr, no leading) * i => minute * s => second * t => hour (12hr, formatted with am/pm) * * @param {String} format String for the formatting of this Date object * @return {String} */ Date.prototype.format = (function () { var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; var fulldays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; var fullmonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; function twoDigits(n) { return (n<10? '0':'')+n; } return function formatDate(format) { var d = this; var matches = this.matches || { 'd': function () { return twoDigits(d.getDate()); }, 'D': function () { return d.getDate()+''; }, 'l': function () { return days[d.getDay()]; }, 'L': function () { return fulldays[d.getDay()]; }, 'm': function () { return twoDigits(d.getMonth()+1); }, 'M': function () { return d.getMonth()+1; }, 'f': function () { return months[d.getMonth()]; }, 'F': function () { return fullmonths[d.getMonth()]; }, 'y': function () { return (d.getFullYear()+'').slice(2, 4); }, 'Y': function () { return (d.getFullYear()+''); }, 'g': function () { return twoDigits(d.getHours()%12); }, 'G': function () { return d.getHours()%12+''; }, 'i': function () { return twoDigits(d.getMinutes()); }, 's': function () { return twoDigits(d.getSeconds()); }, 't': function () { return (d.getHours() > 11? 'am' : 'pm'); } }; this.matches = matches; return format.replace(/[dDlLmMfFyYgGist]/g, function (match) { return matches[match](); }); }; })();
Friday, January 25, 2008
Introducing CSSx
Sick of the lack of syntactic sugar for CSS? While many designers are fine with the simplicity of CSS, some developers managing large codebases (such as Zillow's still-terse 2500-line master.css) have been flailing for sanity. Enter CSSx, a syntax-enhancing compiler for CSS. It accepts all currently-valid CSS syntax, so you can use your current CSS chops unaltered, but adds variables and block nesting to the language.
/* sample.cssx */
$red = #f00 /* a comment here*/;
$block = {
div {
padding: 10px;
}
color: $red;
border-width: 1px;
margin: 20px 10px 15px 0;
}
.warning {
color: $red;
}
.content {
.warning {
width: 200px;
}
cite { @rule($block); }
p {
span.tooltip {
color: blue;
}
font-size: 1.1em;
}
.header {
@rule($block);
font-size: 0.8em;
}
font-family: Verdana, Arial, sans-serif;
}
It's still very beta (I'd peg it at 0.1), but please download, give it a spin, and give me feedback on what works/doesn't work for you, or what you'd like to see added. Download CSSx from Google Code.
Saturday, October 13, 2007
Type-Converting Operator Considered Ridiculous
I have come to question the wisdom of the type-converting == operator in JavaScript. The algorithm (defined in §11.9.3 of the ECMA-262 v3 spec) requires no fewer than 22 steps to execute, and produces such amazing intrasitivities as:
>>> '0' == 0 true >>> 0 == '' true >>> '' == '0' false
and random quirkiness such as:
>>> ' \t\r\n' == 0 true
but:
>>> null == 0 false >>> null == false false >>> null == '' false >>> null == undefined true
Do these behaviors strike anyone else as, well, a bit off? In the first example (discussed elsewhere) the intransitivity of the equality operator is a result of wanting an equality operator to play well within a weakly-typed language. If you want to be able to compare numbers to their string representations as though they were of the same type, while still preserving string comparison, this is the logical result. The second example is a result of the ToNumber algorithm, described in §9.3ff. The whitespace conversion to number value 0 is strange, but defined in the spec (in fact, it's a result of the same algorithm that dictates Number(' ') => 0). The third example seems bizarre as well; I'm not sure why null would be treated differently than 0 or false, but the same as undefined, in such expressions. Many articles from otherwise reputable sources often describe all of these values in terms of "truthiness" and "falsiness", but these articles sometimes gloss over these distinctions.
I don't condone transitioning JS into a strongly-typed system, but some of these behaviors are quite subtle. Given the fact that the vast majority of JavaScript programmers seem to be unaware of the strict-equality operator === (and its negative counterpart, !==), it's no wonder behaviors such as these can cause confusion. See also this article for even more pitfalls, this time simply with math operators combining string and numeric types.
So as Crockford says, use the strict comparison operator === unless you know what you're doing.
Thursday, October 4, 2007
All the Code Security You Need
Lots of beginning JS coders seem to have this idea that the web is all about having your cake and eating it too. I want to participate in the glorious Internet revolution, I just don't want to share my ideas or information with anybody else. I'm writing rich internet applications that are so great, just so unique, that I want to make sure nobody else can possibly look at my code and steal all those great juicy super-awesome proprietary ideas I've got. And maybe, just for bragging rights, I want my files to look HUGE as well. I've mocked up a handy little device that can take care of both tasks at once. Behold, the decompressJS module:
var decompressJS = (function () {
var encoding = [' ', '\t', '\n', '\r'];
var revEncoding = (function () {
var ec = {};
for (var i=0; i<encoding.length; i++) {
ec[encoding[i]] = i;
};
return ec;
})();
return {
encode: function (codeText) {
var out = [], cc, i=0, len=codeText.length;
while (i<len) {
cc = codeText.charCodeAt(i++);
// JS chars are actually 16-bit UTF-16 chars,
// so we need 4 chars encoded per source char
// to fully encode
for (var j=0; j<8; j+=2) {
out.push(encoding[(cc>>j)&3]);
}
}
return out.join('');
},
decode: function (encodedText) {
var out = [], cur, i=0, len=encodedText.length;
while (i<len) {
cur = 0;
for (var j=0; j<8; j+=2) {
cur += revEncoding[encodedText.charAt(i++)]<<j;
}
out.push(String.fromCharCode(cur));
}
return out.join('');
}
};
})();
Like any mature programming paradigm, my decompressJS can even effectively encode and decode itself, the above 1225-character-long code example (including whitespace) decompressed neatly into an all-whitespace string with no fewer than 4900 characters! Just run your code through this baby and it'll come out the other end fully converted into only invisible whitespace characters! Transfer your JS code over the wire, making it look like nothing but an empty file with all whitespace! Magically increase your file size by a factor of 4! Impress your colleagues with your invisible code! Who's laughing now, code stealers?
Friday, July 27, 2007
Glorious links
BoingBoing's been on a good tear recently. Better than usual. For those of you whose eyes have glazed over, go back and re-read these posts: