Monday, February 28, 2005 |
|
|
I don’t use FogBugz for bug tracking, so I read Painless Project Management with FogBugz by Mike Gunderloy more out of curiosity than real need. Since I have little experience with formal bug-tracking systems (I know, shame on me), I found it interesting to read about the various features of this particular bug-tracking system and some of the philosophy behind those features. If you are considering purchasing FogBugz, or are learning how to use it, this book is sure to be useful to you.
(I did end up with one particularly practical nugget of information, though. We’re currently using Visual SourceSafe for source control, and I wondered how a bug-tracking system could easily integrate with VSS – it would need to know which files were most recently checked in, but I know that the History feature of VSS is quite slow. As it turns out, there’s a useful Journal feature that’s available through the Options dialog of the VSS Administrator. It records every change to the database to a log file, which could come in handy for any tools I might write to monitor the database.) |
2/28/2005 3:22:25 PM (Pacific Standard Time, UTC-08:00) | | Books
|
|
|
|
Friday, February 18, 2005 |
|
|
In JavaScript, the “Boolean” operators && and || aren’t very Boolean at all. In most C-style languages, a || b returns a Boolean – true if either a or b are “true,” and false otherwise. (Remember that lots of things are “true” in JavaScript – in fact, the only things that are “false” are the false Boolean, the numbers 0 and NaN, the empty string, null, and undefined.)
Actually, that’s a somewhat simplified view, because the && and || operators of C-style languages short-circuit, meaning that b is not evaluated if a is “false.” Thus it is safe to have an expression like a == null || a.isEmpty() – the isEmpty method will not be called if a is null.
Where was I? Ah, yes, in most C-style languages, a || b returns a Boolean, so it’s the same as a ? true : (b ? true : false)
But in JavaScript, a || b doesn’t necessarily return a Boolean, because it is really the same as a ? a : b
How does this work? Well, if a is “true,” then a || b returns a, which is “true.” If a is “false” but b is “true,” then a || b returns b, which is “true.” If both a and b are “false”, then a || b returns b, which is “false.”
The danger is in assuming that a || b returns a Boolean when a and b are not Booleans themselves. For example: var hasItems = a && a.getCount();
if (hasItems == true) // should be: if (hasItems)
...
Now, you shouldn’t be comparing Booleans to true or false anyway, but if you did, you’d find that hasItems equals true only when a.getCount() returns 1 (and then only because 1 equals true in JavaScript). Furthermore, hasItems equals false only when a.getCount() returns 0 (because 0 equals false). If a is null, hasItems will be null, which equals neither true nor false. If a.getCount() returns 2, hasItems equals 2, which, again, equals neither true nor false.
Be aware that the MSDN documentation is stunningly inaccurate here; it suggests that && and || always return true or false. (The JScript.NET documentation is more accurate, thankfully.)
Why does JavaScript evaluates the binary Boolean operators this way? Well, a || b provides a great shortcut for a ? a : b that only evaluates a once. Similarly, a && b provides a nice shortcut for a ? b : a. For example, instead of var pane = null;
if (view != null)
pane = view.getPane();
or var pane = view == null ? null : view.getPane();
you can use var pane = view && view.getPane();
You could argue that it’s not as clear, of course, particularly to anyone that doesn’t know about this feature of JavaScript, so take advantage of it at your own discretion.
I should also mention the unary Boolean operator of JavaScript. The “not” operator (!) is quite Boolean, because it always returns true or false. That is, !a evaluates to true if a is false, 0, NaN, "", null, or undefined; otherwise, !a evaluates to false. To explicitly convert a value to a Boolean, you could use a ? true : false, or you can simply use a double-not: !!a. |
2/18/2005 4:45:39 PM (Pacific Standard Time, UTC-08:00) | | Code | JavaScript
|
|
|
|
Wednesday, February 16, 2005 |
|
|
The this statement in JavaScript is important, particularly when writing “object oriented” code. What this is depends on when you ask.
Outside of a function call, this is the global object. If your code is being hosted by a browser, this is the window object. Other script hosts provide their own global object.
Inside of a function call, what this is depends on how the function was called. A function can be called in one of four ways:
F(arg1, arg2)
obj.F(arg1, arg2)
F.call(obj, arg1, arg2)
F.apply(obj, args)
In the first case, any reference to this in the function definition will evaluate to the global object. In the second case, references to this evaluate to the specified object (obj), which is why this is so important to “object oriented” JavaScript code. In the third and fourth cases, references to this also evaluate to the object, unless obj is set to undefined, in which case this will evaluate to the global object, as with the first case.
It’s interesting to consider the relative speed of each of the four ways to call a function. Unsurprisingly, the last is generally the slowest. Quite surprisingly, to me at least, under Internet Explorer, the second case is faster than the third. That’s right – calling a function property of a global object is faster than calling a global function. Only the Great Implementor would know for sure, but it looks like the extra time in the first case is spent determining what this should be. In fact, the third case is also faster than the first case when the first argument to call is anything but undefined. (Thus, when performance is an issue, and I’ve got a function variable, I call it with the call method and specify an explicit this.)
Update: I forgot to mention another useful use of this. When an HTML element raises an event, the event handler function can use this to access the element to which the event handler was attached. window.event.srcElement provides access to the element that raised the event. There's no difference between the two unless the event has bubbled to the element. For example, if you handle onclick in document.body, window.event.srcElement will be the actual descendant element that was clicked, but this will always be document.body. |
2/16/2005 9:23:08 AM (Pacific Standard Time, UTC-08:00) | | Code | JavaScript
|
|
|
|
Tuesday, February 15, 2005 |
|
|
What is true in JavaScript? It depends on how you ask.
X === true is true only if and only if X is a Boolean variable set to true.
(What, you’ve never heard of the “triple-equals” operator? It’s actually called the “identity” operator, and X === Y when typeof(X) == typeof(Y) && X == Y. There’s also X !== Y, which is the same as !(X === Y). You’re probably familiar with the typeof operator – it returns “number”, “string”, “boolean”, “object”, “function”, or “undefined”. Notice that there’s no “integer” or “real”, so it is unsurprising (but dangerous, given the unpredictability of floating-point math) that 1 + 1 === 0.5 + 1.5. Anyway, back to what is true…)
X ? true : false is true most of the time. It’s only false when X is the number 0, or the number NaN, or the empty string, or the false Boolean, or the null object, or undefined. (This is the same logic used by the if and while statements.)
Now, equality gets really confusing. X == true whenever X can be directly converted to the Boolean true. The following meet that criteria: the true Boolean, the number 1, and strings that convert to the number 1, such as “1”, “1.0”, “1E0”, “0.1E1”, “ +1.0 ”, etc. Note that leading and trailing whitespace is ignored! Surprisingly, strings like “true” or “True” do not meet the criteria – so "1" == true, but "true" != true.
In the case of equality, we must also talk about what is false. X == false whenever X can be directly converted to the Boolean false: the false Boolean, the number 0, and strings that convert to the number 0, such as “0”, “0.0”, “ -0E1”, etc. But wait; there’s more! The empty string (“”) is also “equal to” false, as well as any string that contains only whitespace! So " \n\t\r\u2002" == false! Who knew? However, a few things that you’d think might be “equal to” false aren’t: "false" != false, NaN != false, null != false, and undefined != false.
What's particularly confusing is considering which of the following similar statements are true for any given X:
X == true
X != false
X ? true : false
If X is "1", they are all true. If X is "", none are true. But if X is null, only the second is true. If X is " ", only the last is true. And if X is "2", the last two are true. The funny thing is that it really does work as you’d expect, most of the time. The subtleties of JavaScript…
Disclaimer: My experience is actually with Microsoft’s JScript, particularly as it is implemented inside Internet Explorer. I presume that this is all true for all JavaScript engines, but I haven’t actually tested it.
Update: I replaced the second to last paragraph with something that is hopefully more interesting and more accurate. (Thanks, Bradley!) |
2/15/2005 9:16:02 AM (Pacific Standard Time, UTC-08:00) | | Code | JavaScript
|
|
|
|
Monday, February 14, 2005 |
|
|
Pattern Hatching: Design Patterns Applied is small book that serves as a follow-up to Design Patterns. It was written by John Vlissides, one of the “Gang of Four,” and published back in 1998.
I enjoyed chapter two of this book, “Designing with Patterns,” as it provided a concrete example of patterns at work. The rest of the book seemed aimed at writers of patterns, so I found it much less interesting. One big problem was that I didn’t heed the warning in the introduction that I needed to be very familiar with all of the classic patterns – I don’t know them as well as I ought, so I sometimes had a little trouble following. It must be time to reread Design Patterns. I also need to brush up on my UML – there can be a lot of meaning hidden behind the style of arrowhead used in a diagram.
In summary, I can’t give the book a formal recommentation, but I did find it interesting, and if you’re really into patterns, then you certainly need to have read this book. |
2/14/2005 12:44:58 PM (Pacific Standard Time, UTC-08:00) | | Books
|
|
|
|
Thursday, February 10, 2005 |
|
|
Write Great Code (Volume I: Understanding the Machine), by Randall Hyde, wants to help you write better software by teaching you more about the hardware. I found the book quite fascinating when I didn’t find it uninteresting. I skimmed through his software implementations of floating-point operations, the design of a hypothetical instruction set, and some of the other really deep material, so I ended up really enjoying the book overall.
I enjoyed the refresher on how floating-point works. I’ve never paid much attention to hardware, so I learned a lot about what the data buses are and how they’re used, how memory is accessed, what a wait state is, etc. I thought I knew Boolean logic until I read (and then skimmed) chapter 8. I learned a lot about I/O in the last chapter as well.
The less you understand about the hardware, the more you stand to gain from reading this book. I don’t intend to leverage the material to go out and exercise premature optimization in all of my future code, of course; after all, code should be written for humans, not machines, until it becomes clear that there’s a performance problem.
I’m somewhat tempted to read Hyde’s other book, The Art of Assembly Language. However, from what I can tell, that book teaches you how to write assembly language in HLA (High-Level Assembly). I’d be much better off learning how to read assembly language for x86 processors, since that still comes in handy when debugging high-level languages.
I highly recommend this book to anyone that knows more about software than hardware, and I’m looking forward to Volume II: Thinking Low-Level, Writing High-Level. |
2/10/2005 3:26:19 PM (Pacific Standard Time, UTC-08:00) | | Books
|
|
|
|
|
|
|
| Archive |
| March, 2008 (1) |
| January, 2008 (1) |
| September, 2007 (1) |
| July, 2007 (1) |
| June, 2007 (3) |
| May, 2007 (2) |
| January, 2007 (2) |
| December, 2006 (1) |
| November, 2006 (2) |
| August, 2006 (6) |
| July, 2006 (3) |
| May, 2006 (4) |
| April, 2006 (2) |
| March, 2006 (1) |
| February, 2006 (1) |
| January, 2006 (1) |
| December, 2005 (2) |
| November, 2005 (5) |
| October, 2005 (11) |
| September, 2005 (7) |
| August, 2005 (1) |
| July, 2005 (2) |
| June, 2005 (2) |
| April, 2005 (5) |
| March, 2005 (11) |
| February, 2005 (6) |
| January, 2005 (2) |
| December, 2004 (1) |
| November, 2004 (1) |
| October, 2004 (3) |
| September, 2004 (1) |
| August, 2004 (5) |
| July, 2004 (10) |
| June, 2004 (3) |
| May, 2004 (5) |
| April, 2004 (3) |
| March, 2004 (10) |
| February, 2004 (10) |
| January, 2004 (15) |
| December, 2003 (1) |
| November, 2003 (2) |
| October, 2003 (13) |
| September, 2003 (20) |
| August, 2003 (24) |
|
|
|
|